【Unity C#】配列② 多次元配列を図入りで詳細に説明【初心者向け】

UnityC#

勉強しながら個人でゲームをせっせと作っています、えきふるです。

こんな人向け!

・多次元配列が意味わからん
・配列は分かったけど多次元配列って何?
・表計算ソフトやオセロ盤のようなデータ配列は扱えないの?
・多次元配列の記述の仕方教えて

ここでは、配列②として多次元配列の説明を丁寧に説明していきます。
配列って何?という方やまだ基本的な配列に関して不安のある方下記を見てくださると嬉しいです!

えきふる
えきふる

わかりやすく丁寧を心がけていますので安心して欲しいふる

多次元配列

多次元配列とは?

今までの配列は1次元(一方向だけの情報)でしたが配列では複数の次元を持つことができます。
複数次元とは、例えば画像データの「縦1920pix 横1080pix」やオセロ盤「8×8」のように
2つの方向の情報を持っているもの=これは2次元の情報です。

2次元以外にも3次元、4次元も配列で表現ができます。

5次元以上も表現できるようですが、正直4次元以上の時点で数が多く、扱うのはかなり難しく、稀なような気もします。

多次元配列には2種類あり、
四角い多次元配列
配列の配列があります。

えきふる
えきふる

焦らず1つ1つ見ていきましょうふる

おまけ:xyz軸の事

上記のイメージ画像ではxyzの3軸方向で多次元配列を説明しました。
z方向が下から上に向いているので少し違和感を覚えた方もいるかもしれません。
これは後での説明をしやすくするためにz軸を上にしただけですので、あまり意味はありません。

xyzの3軸の関係性の基本は「xyの平面にz方向が直行している」
ですのであまり方向はお気になさらず。今回はこういう設定にしたんだ〜程度の認識でOKです。

ちなみに、
z軸の方向は3Dを作成するツールやゲームエンジンによっても設定がバラバラだったりします。
例えば3Dを作成する代表的なツール「Maya」はZ軸が奥行き方向ですが、「3dsMax」はz軸は縦方向だったりします。(これをzアップなんて呼んだりします)Blenderもzアップだったかと思います。

ですので一方向で決めて覚えてしまうと混乱するかもしれません。
軸方向はアプリケーション毎で確認する必要がありますね。

多次元配列(四角い多次元配列)

何で四角い多次元配列なの?

多次元配列とは一般に四角い多次元配列のことを指します。
どの辺も同じ数の分が伸びて、イメージとして立方体や四角形を形作るので
「四角い」多次元配列となります。
先程のイメージ画像で言うとどのX軸の値もY方向の「数」は一緒ですよね。

※と言うことで先程のイメージは厳密には「四角い多次元配列のイメージ」になっています。

四角い多次元配列の記述の仕方

C#では四角い多次元配列の2次元、3次元、4次元…を下記のように記述します。

データ型名[] 変数名 = new データ型名[配列数];
データ型名[,] 変数名 = new データ型名[配列数1, 配列数2]; // 2次元配列の場合
データ型名[,,] 変数名 = new データ型名[配列数1, 配列数2, 配列数3]; // 3次元配列の場合
・
・

例)
int[,] a = new int[4, 5]; // 4列5行の2次元配列の場合

それではUnityゲームエンジンで実際に使用してみましょう!
下記のようなコードを作成してみました。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class hairetu : MonoBehaviour
{
    void Start()
    {
        int[,] a = new int[3,4];//2次元配列でインスタンス生成

        a[0, 0] = 00; a[0, 1] = 01; a[0, 2] = 02; a[0, 3] = 03;
        a[1, 0] = 10; a[1, 1] = 11; a[1, 2] = 12; a[1, 3] = 13;
        a[2, 0] = 20; a[2, 1] = 21; a[2, 2] = 22; a[2, 3] = 23;

        Debug.Log(a[1,2]);

    }
}

2次元配列で作成してみました。
今回はインスタンス生成の後に3列4行で要素を作成したのでわかりやすく四角形に並べながら値を入れていきましたが、1要素ずつ改行しても勿論問題ありません。

こちらをUnityゲームエンジンで実行すると下記のようにコンソールに出ました。

Unityゲームエンジンのコンソール表示
えきふる
えきふる

ちゃんと動いているね!

TIPS:四角い多次元配列の要素にインスタンスと同時に初期値を入れる方法

上記のコードでは各要素の値はインスタンス化してから後に代入していましたが、
下記の方法で一度に入れることも可能です。

データ型名[,] 変数名 = new データ型名[,] //二次元配列
{
  {値0-0, 値0-1, ,,,},
  {値1-1, 値1-2, ,,,},
};

例)
 int[,] a = new int[,]
        {
            {00,01,02,03},
            {10,11,12,13},
            {20,21,22,23},
        };

また、一番最初の宣言時であればnewを省略して書くことも可能です。

データ型名[] 変数名 = 
{
  {値0-0, 値0-1, ,,,},
  {値1-1, 値1-2, ,,,},
};

例)
int[,] a =
        {
            {00,01,02,03},
            {10,11,12,13},
            {20,21,22,23},
        };
えきふる
えきふる

どちらも配列①でやったものと同じふるね。

配列の配列(ジャグ配列・ギザギザ配列)

配列の配列とは?

多次元配列(四角い配列)が四角形のように揃ったイメージになる配列でしたが、
これを配列の中に配列を並べることでバラバラで、ジャギーな、ギザギザした構造の配列にすることができます。

名前の通り配列の中に配列を入れる方法で、1つ1つの配列変数に対してそれぞれ配列を生成していくようなイメージです。

ただし生成された配列の最初の箱の添字が[0]になることに注意して下さい。
例えば、
二次元配列の場合の四角い配列の[0][1]が配列の配列では[0][0]に、
三次元配列の場合は[0][1][1]が[0][0][0]になっています。

つまり、X次元の配列を生成する土台になっている(X-1)次元の要素はX次元を考える時カウントされない、と言う事です。

えきふる
えきふる

配列変数の要素の中にさらに配列を生み出していくイメージ!

配列の配列 記述の仕方

配列の配列の記述の仕方は下記になります。

データ型名[][] 変数名 = new データ型名[配列の行数][];//2次元の配列の配列
データ型名[][][] 変数名 = new データ型名[配列の行数][][]//3次元の配列の配列
・
・
・
例)
int[][] a = new int[3][]; 

四角い多次元配列との違いは、二次元配列で見てみると
四角い多次元配列 int[,] a = new int[3,4];
配列の配列 int[][] a = new int[3][];
と言う風に四角い方は最初に全ての要素数を生成しているのに対し、
配列の配列では一次配列部分だけ生成し、次の次元に関してはその後の記述で生成していく
と言う違いがあります。

後で生成していくと言うのはどう言うことでしょうか。
次のサンプルコードで実際に見てみましょう。

二次元の配列の配列のサンプル

二次元でサンプルコードを記述しましたので確認していきましょう。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class hairetu : MonoBehaviour
{
    void Start()
    {
       
        int[][] a = new int[3][];
        {
            a[0] = new int[] { 1 };
            a[1] = new int[] {2,3,4 };
            a[2] = new int[] { 5 };
        }
        Debug.Log("a[1][2]の値は" + a[1][2]);

    }
}

解説です。まず

int[][] a = new int[3][];

のところでイメージ画像の青箱部分を作成しています。
ここが2次元目の配列を生成するためのベースの要素になります。
その下の

{                              
            a[0] = new int[] { 1 }; 
            a[1] = new int[] {2,3,4 };
            a[2] = new int[] { 5 };
}                             

の所で
青箱部分に当たる要素a[0]a[1]a[2]にそれぞれ配列を生成、データを入れています。
a[0] = new int[] { 1 };
は要素a[0]から新しく配列を作成し、要素が1つ、その要素に整数1を入れています。
つまりa[0]から伸びている配列の1番目の要素[0]=a[0][0]は1、
a[0][0]番号の箱に1が入っていると言うことです。

同様に
a[1] = new int[] {2,3,4 };
要素a[1]から要素が3つある配列を生成し、それぞれの要素に2、3、4を入れています。
つまりa[1]から伸びている配列の1番目の要素[0]番=a[1][0]は2、
同様にa[1][1]は3、a[1][2]は4
と言うことになります。

a[0][0]などの番号がどこを指すのかは下の画像を再度確認して下さいね。

このコードをUnityゲームエンジンで実行すると下記のように出ました。

unityゲームエンジンのコンソール表示
えきふる
えきふる

a[1][2]が4なので、ちゃんと指定した座標に入れた値が返ってきているふる!

ちなみに、このサンプルで作成した配列は上で見せたイメージ画像のまさにこれ↓です。

三次元での配列の配列のサンプル

二次元で確認してみましたが、三次元ではどうなるのでしょうか、
こちらもサンプルコードを用意しましたので確認してみましょう!

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class hairetu : MonoBehaviour
{
    void Start()
    {
       
        int[][][] a = new int[3][][];
        {
            a[0] = new int[1][];
            a[1] = new int[3][];
            a[2] = new int[1][];

            a[0][0] = new int[] { 1 };

            a[1][0] = new int[] { 2 };
            a[1][1] = new int[] { 3,4,5 };
            a[1][2] = new int[] { 6 };

            a[2][0] = new int[] { 7 };
        }
        Debug.Log("a[1][1][1]の値は" + a[1][1][1]);
    }
}

2次元の時とやっていることは同じなのですが、入れ子のようになっているので少し複雑です。
まず、

int[][][] a = new int[3][][];

ここの部分で3次元配列に向けて、まずは要素を3つ持つイメージ画像の青箱部分の配列を生成します。
そして、

a[0] = new int[1][];
a[1] = new int[3][];
a[2] = new int[1][];

ここの部分で青箱部分の要素から緑箱部分の配列を作成します。
2次元と違うのは、この要素には整数値は入れず、配列変数を生成し、入れています。
つまり
a[0]では要素を1つ作り、その要素に配列変数を入れています。
a[1]では要素を3つ作り、それら全てに配列変数を入れています。
a[2]はa[0]と同様に要素を1つ作り、その要素に配列変数を入れています。

ここまでで下記の画像の緑箱部分に配列変数がそれぞれ入っている、と言う状態になりました。
※2次元の時はこの要素には値が入っていました。

次に緑箱に入っている配列因数からさらに3次元目の配列を生成します。

 a[0][0] = new int[] { 1 };

 a[1][0] = new int[] { 2 };
 a[1][1] = new int[] { 3,4,5 };
 a[1][2] = new int[] { 6 };

 a[2][0] = new int[] { 7 };

この部分で3次元目、イメージ画像の赤箱部分を作成します。
a[0][0] = new int[] { 1 };
要素a[0][0]から新しく配列を作成し、要素が1つ、その要素=a[0][0][0]に整数1を入れています。
2次元配列の時の緑箱部分と一緒ですね。
同様に
a[1][0] = new int[] { 2 };
はa[1][0]から要素1つの配列生成=a[1][0][0]に2を入れる。

a[1][1] = new int[] { 3,4,5 };
はa[1][1]から要素3つの配列生成=a[1][1][0],a[1][1][1],a[1][1][2]
それぞれの要素に順番に3、4、5を入れる。

a[1][2] = new int[] { 6 };
はa[1][2]から要素1つの配列生成=a[1][2][0]に6を入れる。

a[2][0] = new int[] { 7 };
はa[2][0]から要素1つの配列生成=a[2][0][0]に7を入れる。
と言う風になっています。

このコードをUnityゲームエンジンで実行すると

unityゲームエンジンのコンソール表示
えきふる
えきふる

a[1][1][1]が4なので、こっちもちゃんと指定した座標に入れた値が返ってきているふる!

もうお分かりだと思いますが、
このコードで作成した三次元の配列のイメージは先ほどから見せているこれ↓です。

えきふる
えきふる

青と緑の箱には値を入れられないのでちょっぴり損した気持ちになるふる

TIPS:配列を生成した要素の配列にデータを入れられない

サンプルコードの中でも説明していますが、
配列を生成するベースとなる要素には値を入れられません。
だって配列変数を入れているんだもの。
では実際に二次元の「配列の配列」のサンプルで作成したコードで確認してみましょう。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class hairetu : MonoBehaviour
{
    void Start()
    {
        int[][] a = new int[3][];
        {
            a[0] = new int[] { 1 };
            a[1] = new int[] {2,3,4 };
            a[2] = new int[] { 5 };
        }

        Debug.Log("a[1]の値は" + a[1]);

    }
}

これをUnityゲームエンジンで実行してa[1]の値を見てみると…

unityゲームエンジンのコンソール表示

上記のようにa[1]の値はSystem.Int32[]と出ました。
これはa[1]はint32[]、つまりint型の配列だよ〜と返ってきていると言うことだと思います。

ちなみに
a[0] = 1;
とか記述してデータを入れようとしても記述エラーが出てしまうので、入れることはできません。
※型が違うよ、といわれると思います。

TIPS:配列の配列の要素にインスタンスと同時に初期値を入れる方法

ここまでお疲れ様でした。
最後に、お馴染みのインスタンス生成と同時に初期値を要素に入れる、
省略形の書き方です。
二次元配列で記載します。

データ型名[][] 変数名 = new データ型名[要素数][] //二次元配列
{
new int[]{値},
new int[]{値},
};

例)
int[][] a = new int[2][]
{
  new int[] { 1 },
  new int[] { 2, 3, 4 },
};

また、一番最初の宣言時であればnewを省略して書くことも可能です。

データ型名[][] 変数名 =
{
new[]{値},
new[]{値},
}

例)
int[][] a =
{
    new[] { 1 },
    new[] { 2, 3, 4 },
};
えきふる
えきふる

お疲れ様でした!!!

コメント

タイトルとURLをコピーしました