配列クラス
配列とは、ただ一つの名前で複数のデータを管理できるクラスで、データを順番に並べて管理します。 普通のクラスと異なる点は、インデックスと呼ばれる数値(0~)でデータを管理できる所です。
これによって、大量のデータを反復文等で一度に処理できる…それが配列の強みなのです。
配列クラスの使い方
配列クラスは普通の設計図ですから、実物を作る必要があります。 配列クラスの名前はArrayです。 よって、実物を作るのは次のようにします。
var dim = new Array();
たったこれだけで、配列クラスを使う事が出来ます。 一からクラスを作る事の難しさを分かっているからこそ、 とても重宝しますので、大いに活用する事にしましょう。
また、次のように書く事も出来ます。
var dim = [];
本入門では、後者の方式を採用します。 後に説明しますが、配列は通常のクラスとは違った使い方をするので、 一般的なクラスと区別するためです。
配列の基本
配列クラスは、通常のクラスとは違う特別な書き方をします。 最初は戸惑うかもしれませんが、使ううちに慣れるので問題ありません。
さて、変数が何かを入れる箱なら、配列は変数を多数入れる事が出来る大きな箱です。 例えば、文房具は筆箱、漫画の本なら本棚、というように特定の種類毎に容器を変えますよね。 TJSの配列も考え方は同じで、特定種類の複数の変数をグループ化してしまおうというのが配列の考え方です。

C/C++
TJSではデータ型を自動的に判断してくれますので、 同一配列の中に整数や文字列、オブジェクト等を混同して入れることが出来ます。
よって、C言語の構造体を使わなくても、配列だけで解決できるのです。
しかし、配列の中に入れる変数に名前は必要ありません。 配列という名前の通り、配列クラスは中に入れる変数という箱を、順番どおりに並べて管理しています。
各箱は数字で管理され、箱の並び順は数字の大小で容易に分かります。 つまり、数字が小さいほど最初にある箱です。

各箱を参照するのは簡単で、次のように書きます。
配列名[箱の数字]
dimという配列の2番目にある箱を使うなら次のように書きます。
dim[2]
この書き方が分かりづらければ、次のように考えてください。
dim.2
配列クラスが管理しているメンバー変数と考える事が出来ますね。 (ただし、実際は2というメンバー変数が存在しているわけではなく、 箱を順番どおりに並べた結果、3番目にある変数という意味です。)
この時、箱に入っているデータの事を要素と呼び、 箱の順番を指す数字をインデックス、または添え字と呼びます。
配列の最初にある箱の数字は0です。勘違いしやすいので注意してください。
0番目の箱、1番目の箱……99番目の箱...
この時、99番目の箱は、0番目から数えて100個目の箱という事になります。
要素に代入する
実際に配列の中に箱を作ります。 代入は変数と同じ考え方なので、代入演算子「=」を使います。 配列は0番目から順番に管理しますので、最初に入れる箱の番号は0です。
var dim = new Array(); dim[0]=1; dim[1]=100;
これで、0番目の箱に1という数字が、1番目の箱に100という数字がそれぞれ代入出来ました。 この使い方は、普通の変数と全く同じです。
では、0番目の箱~9番目の箱という10個の箱を用意し、 それぞれ最初から順番に1~10の数字を代入してみましょう。
var dim = new Array(); dim[0]=1; dim[1]=2; dim[2]=3; dim[3]=4; dim[4]=5; dim[5]=6; dim[6]=7; dim[7]=8; dim[8]=9; dim[9]=10; System.inform("2番目の箱="+dim[2]); System.inform("4番目の箱="+dim[4]);
うまく表示されましたか?
反復文を使った代入
配列は、その特徴から反復文を使って全要素を操作できます。 これが配列を使う最大のメリットであり、逆に言えば、配列の要素を一つずつ操作したのでは、 配列を使う意義が薄れます。
以下に、while文を使った例を挙げます。
- ループ変数iを用意し、配列の最初の添え字0を代入する
- 条件式には、ループ変数が配列の希望要素数になるように設定する
var i=0; while ( i<10 ) { ...箱を作る処理... ++i; }
この例では、要素を10個用意しました。
箱の数が10個だからといって、変数iが10になるまで処理をさせるのは間違いです。
i<11 ……ダメ!
箱が10個という事は、0番目から数えて9番目までの箱を作るという事だからです。 よって、上のような指定をすると11個の箱が作られてしまいます。
配列[0] 配列[1]...配列[9] 配列[10]
配列番号10は、0番目から数えて11個目の箱。
ただ、while文だとループ変数を用意する手間がありますので、 for文を使って書く方が好まれます。
var dim = new Array(); for (var i=0; i<10; i++) { dim[i] = i+1; } System.inform("2番目の箱="+dim[2]); System.inform("4番目の箱="+dim[4]);
変数iは0から始まり、9になるまで処理を繰り返しますから、 この変数iを箱番号の指定に使ってしまおう、という考え方です。 変数iに1を足せば、箱番号+1の数字が代入できるという事になります。
この処理は、次の指定と同じです。
var dim = new Array(); dim[0]=1; dim[1]=2; : 中略 : dim[8]=9; dim[9]=10;
要素の数を知る
配列は管理している箱を普通の変数のように扱えます。配列[箱番号]という指定ですね。
ですが、予め箱の数を決めておき、それを表示するだけなら良いのですが、配列の箱の数が分からないと困る場合があります。 例えば、ユーザから入力と配列を使った簡易データベースを作った場合。 プログラムする段階では、ユーザがいくつのデータを扱うのか知る事は出来ません。
// ユーザが55個のデータを作っていると…… //全ての箱に対して操作 for (var i=0; i<10; i++) ↑これでは9番目の箱までしか操作できない。 //大きな数を指定してしまうと… for (var i=0; i<100; i++) ↑99番目まで箱が無い!(エラーになる)↑
かといって、最初に最大数は100と決めてしまうのもいけません。 学校の生徒数をデータベースにすると、軽く800人を超えるでしょうから、 予め最大データが決まったデータベースほど使えないものは無いですね。
このような状況を避けるために、 配列クラスは管理している箱の数を指すプロパティをメンバーに持っています。 このプロパティ名はcountです。
プロパティcountは、実物(ここでは配列)が持っているメンバーですから、 普通のメンバーの参照と同じように、次のように書けます。
配列名.count
よって、dim.countと書けば、 配列dimが管理している箱の数を求める事が出来ます。 (この箱の数を要素数、配列の大きさ、配列のサイズなどと表現する事があります。)
では、反復文を使って、ある連続したデータを入れた箱0~9を作り、 それを全て表示するという例を見てみましょう。
var dim = new Array(); //10個の箱を作り、代入する for (var i=0; i<10; i++) { dim[i] = "データ"+i; } //変数iがdim.countより低ければ処理する var str=""; for (var i=0; i<dim.count; i++) { str += i+"番目の箱="+dim[i]+"\n"; } System.inform( str );
これが、配列の使い方の基本となります。
簡単な代入方法
では、配列を使う例の一つを見てみましょう。
あなたが小学校の教師だとして、ある学級のテストの結果(点数)を生徒別、教科別に分けてまとめたいとします。 ただし、教科は主要四教科(国語・算数・理科・社会)とし、生徒数は3名とする。
これまでの知識より、変数を別々に管理するのは宜しくない事は分かると思います。
var name1="山田"; var math1=100; //山田君 算数 var jpn1=91; //山田君 国語 :
このように共通した変数がある場合、新しくクラスにすれば……と考えますが、 単純にテストの結果をまとめ、全て表示するだけの簡単な処理ですから、わざわざ自分でクラスを作るまでもありません。 よって、ここでは配列クラスを使用します。
var Yamada = new Array(); //山田君 var Saito =new Array(); //斉藤君 :
しかしながら、配列の箱一つ一つに代入していくのは少し面倒です。 代入したいのはテストの点数ですから、規則的な数では無いので反復文では代入出来ません。
var Yamada = new Array(); Yamada[0] = "山田"; Yamada[1] = 100; //国語結果 :
人数分の入力をするのは少々骨が折れます。 これを簡単な書き方で代入出来ます。
var Yamada = ["山田",100,90,88,95]; var Saito = ["斉藤",65,75,80,99]; :
newを使っていませんが、この場合でもオブジェクト(実物)が作られ、 同時に値を設定出来ています。(コンストラクタに引数を渡しているとも考えられますね。)
これを分かりやすいように図解すると、次のようになります。

この例では、Yamadaという名前の配列オブジェクトを作っています。 0番目の箱に生徒の名前を入れ、1番目~4番目の箱には、それぞれ「国語」「算数」「理科」「社会」の順番で点数を入れる事にします。
では、3名分のデータを配列で管理し、 全てのテスト結果を表示させるサンプルを見てみましょう。
var datas = ["名前","国語","算数","理科","社会"]; var Yamada = ["山田",100,90,88,95]; var Saito = ["斉藤",65,75,80,99]; var Tanaka = ["田中",90,92,74,100]; function pointDisp( pupil ) { var tmp=""; for ( var i=0; i<pupil.count; i++ ) { tmp += pupil[i]+"\t"; } return tmp+"\n"; } var result=""; for ( var i=0; i<datas.count; i++ ) { result += datas[i]+"\t"; } result += "\n"; result += pointDisp( Yamada ); result += pointDisp( Saito ); result += pointDisp( Tanaka ); System.inform(result);
ところどころ、改行を示す「\n」やタブ文字を指す「\t」を書いていますが、 後は特に難しいような場面は無いと思います。
ただ、この書き方ではとても効率が悪いですね。極端な話、生徒の数が300名分になったとしたら? 一つ一つ生徒用の配列を作り、手作業で関数「pointDisp」を呼ばなければならない。 とにかく煩雑で、修正する箇所が多すぎるのです。
これを解決するため、全ての配列内容を自動で処理できる様に改良します。
簡単な代入方法2
次の項目に移る前に、配列の使い方をもう一点紹介しておきます。
入門の最初の方で示したとおり、TJSは自由な書式で書く事が出来ます。 よって、最小単位(トークン)さえ崩さなければ、どのように書いても構わないのです。 これを利用して、配列を更に読みやすく記述できます。
var Yamada = [ "山田", ←0番目の要素 100, ←1番目の要素 90, ←2番目の要素 88, ←3番目の要素 95 ←4番目の要素 ];//セミコロンを忘れないように注意
ここで、配列の初期化のおさらいをしておきましょう。 ご自分の使いやすい書き方で書いて構いませんから、全てを覚える必要はありません。
//配列の初期化(要素の数は0) var dim = new Array();
//配列の初期化(要素の数は0) var dim = [];
//配列の初期化と代入 var dim = new Array(); dim[0] = 100; dim[1] = 5; :
//配列の初期化と代入 var dim = ["山田",100,5];
//配列の初期化と代入 var dim = [ "山田", 100, 5 ];
二次元配列
変数にはどのようなデータも入れる事が出来る、と以前に書いたとおり、 何でも入れる事が出来ましたね。例えば、そう、オブジェクト(実物)であっても。 今回は、これを利用して前回のプログラムを改良します。
訂正するのはただ一つ。全ての要素をfor文などの反復文を利用して表示させる事。 よって、全データを配列としてしまうのです。 簡単に言えば、配列の要素の中に配列を作ってしまえば良いのです。

//配列に配列を入れる var dim = [ ["山田",100,5], ["田中",90,88] ];
今回は、以前の配列を管理する為の配列として「pupil」を用意します。 その構成は以下のようにします。
//生徒データを管理する配列 var pupil = [ 各要素の種類を指す配列……箱番号0 山田くんの情報配列……箱番号1 斉藤くんの情報配列……箱番号2 田中くんの情報配列……箱番号3 ];
実際に改良したプログラムが以下になります。
var result=""; var pupil =[ ["名前","国語","算数","理科","社会"],//箱番号0=pupil[0] ["山田",100,90,88,95],//箱番号1=pupil[1] ["斉藤",65,75,80,99],//箱番号2=pupil[2] ["田中",90,92,74,100]//箱番号3=pupil[3] ]; //配列pupilに対して全て for ( var i=0; i<pupil.count; i++) { //各要素に入っている配列に対して全て for ( var j=0; j<pupil[i].count; j++) { result += pupil[i][j]+"\t"; } result += "\n"; } System.inform(result);
前回のプログラムと比べても、随分すっきりしましたね。 おまけに、修正する箇所は配列pupilの要素だけで終わります。
簡単に解説しておきます
- (1)配列の中の配列を指す
-
配列の要素の中の配列を指すには、もう一つ[]を追加して書きます。 配列pupilの箱番号1に入っている配列を指すにはpupil[1]と書きますよね。 更に、その中にある配列の箱番号2を指すなら
pupil[1][2]
と書きます。今回は山田君の点数90が得られます。
- (2)多重ループを使う
-
for文の中にfor文を書く使い方は以前にもやりましたが、覚えているでしょうか? 最初のfor文の条件は「pupil.count」が変数iより低ければ、とあります。 よって、変数iがpupilの箱の数になるまで繰り返す事を意味します。
二つ目のfor文は「pupil[i].count」が変数jより低ければ、とあります。 これも同じ考え方で、pupilの箱番号(ここでは変数iを指す)に入っている配列を操作します。 よって、変数jがpupil[i]に入っている配列の箱の数になるまで繰り返す事を意味します。
このように、配列は単体で使用するよりも、 配列の中に配列を入れて操作するほうが、用途は更に広がります。
配列の中に配列を入れる形を配列の配列、または多次元配列と呼ぶ事があります。 また、配列の中に配列を入れた形を特に二次元配列と呼び、配列の使い方の基本となります。
二次元配列の要素の中に更に配列を入れる事も出来ます。
配列→配列→配列……配列[番号][番号][番号]
この形を三次元配列と呼び、同様に四次元、五次元…といくつでも作れます。 が、あまり使われることはありませんので、頭の片隅にでも入れておけば大丈夫です。
少しややこしいのですが、 配列という箱のイメージがしっかり出来れば、 必ず理解できると思うので、諦めずに何度も読み返して理解してください。 多次元配列と多重ループの組み合わせは、ゲームなどを作る際によく利用される手法です。
2D迷路を作る
最後に二次元配列を使用して簡単な迷路を作ります。 まだ画像を扱うことは出来ませんので、 壁を「*」で、歩ける場所を「-」で表現します。

あまり広げても仕方ないので縦×7、横×15の小さな迷路にします。
var result=""; //迷路のデータ var maze =[ [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], [0,1,1,1,1,1,0,1,1,1,1,1,0,0,0], [0,1,0,0,0,1,1,1,0,0,0,1,1,1,0], [0,1,1,1,0,0,0,0,0,1,1,0,0,1,0], [0,1,0,1,1,1,1,1,0,0,1,1,0,1,0], [0,1,0,1,1,0,0,1,1,1,1,1,1,1,0], [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0] ]; for ( var i=0; i<maze.count; i++) { for ( var j=0; j<maze[i].count; j++) { result += ( !maze[i][j] ) ? "*" : "-"; } result += "\n"; } System.inform( result );
迷路のデータは二次元配列mazeに入れていますが、じ~っと眺めていると、迷路みたいに見えてきますよね? (0が壁、1が通路として見ると……。)
これを利用して、もっと複雑な迷路に仕上げてみてください。 縦幅や横幅を広げ、大きなマップにするのもいいですね。 今回の手法は様々なゲームに応用できるはずですから、是非是非、お試しください。