二次元配列と二重ループを使って、ブロック並べをしてみよう
複雑な問題を、プログラムで解こうとするとき、問題の対象のデータをうまく表現するデータ構造と、そのデータ構造を適切に利用できる制御構造を組み合わせられると、良いアルゴリズム、良いプログラムにすることができます。
この記事では、様々な問題を解くアルゴリズムを考える上で基本になる、二次元配列と二重ループ(二重の繰り返し)を扱います。
ブロック並べ
題材として、Monaca Educationのメニュー「新しいプロジェクトを作る」から簡単に作成できる『ブロック崩し』のプログラムを使います。
ただし、以下の説明では、二次元配列と二重ループに集中するため、ブロック崩しの他の部分(パドルの操作や、ボールの移動など)は削除したプロジェクトを用意しました。「ブロックを画面に並べる」、つまり「ブロック並べ」のプログラムで学んでいくことにしましょう。
サンプルプロジェクト「ブロック並べ」をインポートする
最初に、この記事で使っているサンプルプロジェクトを、Monaca Educationにインポートします。
WebブラウザでMonaca Educationにログインした上で、下記のボタンをクリックしてください。
Monaca Educationにインポートする(要ログイン)
サンプルプロジェクト「ブロック並べ」の動作(表示のみ)
Monaca IDEでサンプルプロジェクト「ブロック並べ」を開くと、上のようにプレビューパネルに表示されます。
このプロジェクトでは、フォルダimgの中にあるブロックの画像ファイルを、PIXI.jsというゲーム制作用のライブラリを用いて、画面に配置しています。
ブロック崩しのプログラムを流用していますが、二次元配列と二重ループを見るために、プログラムを変更して、表示方法や動作を変えました。このプログラムは、ブロックを表示するだけで、ブロック崩しゲームとして遊ぶことは出来ません。
プログラムの確認①二次元配列を使って、ブロックの配置を行・列で指定
この「ブロック並べ」プログラムを実現しているのは、プロジェクトのフォルダjsの中にあるmain.jsです。
main.jsの、23行目から26行目の部分が二次元配列で、ここでブロックの色・並べ方(何行・何列で並べるか)を決めています。
var blockMap = [
['red','green','blue'],
['green','blue','red']
];
プログラムに書かれている内容と、実際の実行結果を見比べて、プログラムの記述と画面表示がどのように対応しているか考えてみましょう。
プログラムを詳しく確認します。
var blockMap は、blockMap(ブロックのマップ)という名前の変数を宣言しています。=は右辺の内容を左辺に代入するという意味です。続く大カッコ [ ] は、配列を作る記号です。
var blockMap = [
];
23行目で開いた大カッコ( [ )は、26行目で閉じて( ] )います。
その大カッコの中には、さらに大カッコで囲まれた行が2つ( [‘red’, ‘green’, ‘blue’] と、 [‘green’, ‘blue’, ‘red’] )含まれています。この2つの行の間には、カンマ( , )があり、区切りとなっています。
[ … ],
[ … ]
この2つの行は、それぞれブロックの行に対応しています。
それぞれの行の、大カッコ [ ] の中には、色の名前が一重引用符( ‘ )で囲まれたかたちで書いてあります。色の名前同士は、カンマ( , )で区切られています。
['red', 'green', 'blue']
配列を二重に使うことで、行と列を持つ二次元の情報(今回の場合は、ブロックの配置の情報)を扱うことが出来ます。
JavaScriptでは、大カッコ [ ]と、カンマ( , )による区切りの使い方に注意する必要があります。
プログラムの確認②二重の繰り返しを使って、二次元配列のデータを順に全て処理する
続く28行目から39行目の部分は、繰り返しが二重になっています。
23行目から26行目で定義した二次元配列(ブロックの並べ方)の各要素にアクセスしながら、画面に配置する関数(addBlock())を呼び出して、実際に画面に配置しています。
30行目から始まり、39行目で終わる外側の繰り返しのfor文は、二次元配列の全ての行を処理します。
最初に変数jに0を代入し、その変数jに1ずつ足しながら、繰り返し処理を行います。変数jの値が、配列blockMapの長さ(※配列の「長さ」とは、要素の数のこと。この配列の要素は2行なので、要素数は2となる)より小さい間、繰り返します。変数jの値が、配列blockMapの長さと等しいか、より大きくなったら終わりです。つまり、j=0から初めて、j=1の時は実行です。j=2になったら、配列blockMapの要素数と等しいので、繰り返しは終了です。
31行目から始まり、38行目で終わるfor文は、二次元配列のある行(※変数jが指す行)の、全ての列を処理するために書かれています。
最初に変数iに0を代入し、その変数iに1つずつ足しながら、変数iの値がその行(blockMap[j]、つまりJ行目)の要素数より小さい間繰り返します。0列目から始まり、1列目、2列目…と処理を進めます。
外側の繰り返し(全ての行について繰り返す)と、内側の繰り返し(ある行について、全ての列について繰り返す)を組み合わせることで、二次元配列の全てのデータにアクセスすることが出来ます。
二次元配列を変更して、ブロックの並べ方を変えてみよう
二次元配列のデータを変更して、ブロックの並べ方を変えてみましょう。
ブロックを1段増やす
二次元配列の記述のうち、24行目の1行をコピーして、すぐ下に貼り付けます。
var blockMap = [
['red','green','blue'],
['red','green','blue'],
['green','blue','red']
];
結果、3行の配列になりました。
ここで、2行目の最後にカンマ( , )が付いていることを確認しましょう。二次元配列なので、行の中の要素同士だけでなく、行同士を区切るためにも、カンマ( , )が必要です。
ファイルを保存して、実行結果を確認しましょう。
ブロックが1段増えています。
ブロックを1列増やす
二次元配列の記述のうち、24行目の大カッコ [ ] の中に、1つ要素を追加してみましょう。
['red','green','blue','silver'],
色の名前silver(銀)を、一重引用符( ‘ )で囲み、‘silver’としています。前の要素’blue’との間に、カンマ( , )を入れて区切っていることも確認しましょう。結果は次の通りです。
色々な並べ方をしてみよう
今回紹介したプロジェクトは、ブロック崩しのプログラムから、二次元配列によるブロックのレイアウトの表現と、二重ループによる配置処理を抜き出したものでした。
なお、本サンプルには、ブロック崩しアプリに元々含まれている赤、緑、青、銀、金、の他に、黒、白、バイオレットのブロックを含めてあります。nullという記述をすると、ブロックの空白を作ることもできます(nullは「空」という意味のキーワードで、引用符で囲まないで書きます。)。
['red','green',null,'silver'],
配列の書き方、二次元配列の書き方に注意しながら(※大カッコ [ ] の開く・閉じるの対応をつけること、要素同士をカンマで区切ること)、様々な書き方を試して、色々なブロックの並べ方を作ってみてください。