PR

2日目 フィールドの設定と描写【JavaScriptの二次元配列】

テトリスを作ろう

はじめに

スマホだけを使って、一週間でテトリスを作っていきます。

1日目 キャンバスの設定と描写
▶︎2日目 フィールドの設定と描写
3日目 テトリミノの設定と描写
4日目 テトリミノの落下と回転
5日目 スマホでの操作と画面固定
6日目 テトリミノの当たり判定
7日目 ラインを消す処理

パソコンがなくても、スマホだけでwebアプリケーションの開発ができます。

プログラミングに興味がある人やプログラミングの勉強を始めたばかりの人に向けて、一からわかりやすく解説していきます。

2日目でやること

前回は、キャンバスに横10マス、縦20マスのフィールドを表示するところまでやりました。

今回は、フィールドを配列の変数で設定して、フィールド変数の値を参照してキャンバスに色を付けるところまでをやっていきます。

2日目 フィールドの設定と描写

全体のソースコード

まずは完成したソースコードをご覧ください。

HTMLのコード

<!DOCTYPE html>
<html lang="ja">

<head>
    <meta charset="utf-8">
    <link rel="stylesheet" href="style.css">
    <title>テトリス</title>
</head>

<body>
    <div class="main">
        <canvas id="canvas01"></canvas>
    </div>
    <script src="script.js"></script>
</body>

</html>

CSSのコード

html {
    height: 100%;
}

body {
    height: 100%;
    margin: 0;
}

.main {
    height: 100%;
    text-align: center;
}

#canvas01 {
    height: calc(100% - 8px);
}

JavaScriptのコード

// ============ 変数 ============

// フィールドサイズ
const FIELD_X = 10   // 横のマスの数
const FIELD_Y = 20   // 縦のマスの数
const MINO_SIZE = 30 // マスの大きさ

// キャンバスの設定
let canvas = document.getElementById("canvas01")
let conText = canvas.getContext("2d")
canvas.width = MINO_SIZE * FIELD_X
canvas.height = MINO_SIZE * FIELD_Y
canvas.style.border = "4px solid #050505"

// 色の設定
const COLOR = [
    "#F2F2F2",    // フィールド背景
    "#C8C8C8"     // 枠の線
]

// フィールドの初期設定
let field = []
for (let i = 0; i < FIELD_Y; i++) {
    field[i] = []
    for (let j = 0; j < FIELD_X; j++) {
        field[i][j] = 0
    }
}

// フィールド描画のテスト
field[0][0] = 1
field[3][5] = 1
field[19][9] = 1

// ============ 関数 ============

// フィールドの表示
function display() {
    for (let i = 0; i < FIELD_Y; i++) {
        for (let j =0; j < FIELD_X; j++) {
            // 塗りつぶしの四角を描画
            conText.fillStyle = COLOR[field[i][j]]
            conText.fillRect(MINO_SIZE * j, MINO_SIZE * i, MINO_SIZE, MINO_SIZE)

            // 輪郭の四角を描画
            conText.strokeStyle = COLOR[1]
            conText.lineWidth = 1
            conText.strokeRect(MINO_SIZE * j, MINO_SIZE * i, MINO_SIZE, MINO_SIZE)
        }
    }
}


// ============ 実行 ============

// 初期画面の表示
display()

JavaScriptの解説

フィールドの初期設定

// フィールドの初期設定
let field = []
for (let i = 0; i < FIELD_Y; i++) {
    field[i] = []
    for (let j = 0; j < FIELD_X; j++) {
        field[i][j] = 0
    }
}
let field = []

field という名前の配列の変数を作ります。

let で変数を宣言して、間違って同じ名前の変数を作ること(再宣言)がないようにしています。let で変数を宣言すると、再宣言(同じ名前の変数を作ること)はできませんが再代入(値を変えること)は可能です。

配列の初期化は [ ] を利用して行います。今の変数 field は、中身を何も持たない配列の変数です。

for (let i = 0; i < FIELD_Y; i++) { .. }

繰り返し「for文」です。{ .. }内の処理を、i が 0 から 1、2、3・・と FIELD_Yの値(20になれば処理しない)まで繰り返します。

field[i] = []

配列の変数 field の i 番目に、空の配列 [ ] を入れます。

i = 0 のとき、field = [[]] となり、
i = 1 のときに、field = [[], []] となります。

これで、配列の変数 field は二次元配列になります。

二次元配列については、後ほど詳しく解説します。

for (let j = 0; j < FIELD_X; j++) { .. }

{ .. }内の処理を、j が 0 から 1、2、3・・と FIELD_Xの値(10になれば処理しない)まで繰り返します。

field[i][j] = 0

二次元配列の変数 field に値を入れていきます。

配列の変数 field の i 番目の配列 [ ] の j 番目に、0 の値を入れます。

field = [[], []・・・] が
i = 0、j = 0 のとき、field = [[0], [],・・・] となり、
i = 0、j = 1 のときに、field = [[0, 0], []・・・] となります。

上記のJavaScriptのコードを、for文を使わずに書き換えるとこのようになります。

// フィールドの初期設定
let field = [
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
]

for文を使うことで、横のマスの数(10)や縦のマスの数(20)を変更しやすくなります。

フィールド描画のテスト

フィールドが正しく表示されるかのテスト用です。

// フィールド描画のテスト
field[0][0] = 1
field[3][5] = 1
field[19][9] = 1
field[0][0] = 1

field[0][0] は、配列の変数 field の 0 番目の配列 [ ] の 0 番目の値を指します。
配列の変数 field の 0 番目の配列 [ ] の 0 番目の値を 1 に変えます。(再代入)

同じように、
field[3][5] = 1 は、変数 field の 3 番目の配列 [ ] の 5 番目の値を 1 に変えます。
field[19][9] = 1 は、変数 field の 19 番目の配列 [ ] の 9 番目の値を 1 に変えます。

0番目や3番目、5番目と説明していますが、この何番目というのを「インデックス」と呼び、配列のインデックスは 0 から始まります。
正確には1つ目、4つ目、6つ目ですが、ここではわかりやすくインデックス番号を使って、1つ目のことを0番目、4つ目のことを3番目、6つ目のことを5番目と言っています。

配列の変数 field を書き換えるとこのようになります。

// フィールド描画のテスト
let field = [
    [1, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 1, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
]

フィールドの描画

// フィールドの表示
function display() {
    for (let i = 0; i < FIELD_Y; i++) {
        for (let j =0; j < FIELD_X; j++) {
            // 塗りつぶしの四角を描画
            conText.fillStyle = COLOR[field[i][j]]
            conText.fillRect(MINO_SIZE * j, MINO_SIZE * i, MINO_SIZE, MINO_SIZE)
        }
    }
}
conText.fillStyle = COLOR[field[i][j]]

.fillStyle = COLOR[field[i][j]] で、塗りつぶしの色を指定します。(前回の「COLOR[0]」を「COLOR[field[i][j]]」に変更しました。)

field[i][j] は変数の値で、配列の変数 field の i 番目の配列 [ ] の j 番目の値が入ります。

JavaScriptの二次元配列について

JavaScriptの配列とは

JavaScriptの配列とは、複数の値を持った変数のことです。変数とは、数値や文字列などの値を名前をつけて保存するものです。

// 配列
array1 = ["a", "b", "c"]
array2 = [1, 2, 3]

上記のように、配列は [ ] の中に複数の値を持ちます。

配列の要素番号(インデックス番号)を指定することで対応する値を呼び出すことができます。

array1[0] で「”a”」を、array1[1] で「”b”」を、array1[2] で「”c”」を呼び出します。
array2[0] で「 1 」を、array2[1] で「 2 」を、array2[2] で「 3 」を呼び出します。

JavaScriptの二次元配列とは

JavaScriptの二次元配列とは、複数の配列を持った変数のことです。二次元以上の配列はまとめて多次元配列と呼ばれます。

// 二次元配列
array3 = [
    [1, 2, 3],
    [4, 5, 6],
    [7, 8, 9]
]

配列の要素番号(インデックス番号)を指定することで対応する配列や値を呼び出すことができます。

// 二次元配列
array3[0]で[1, 2, 3]を呼び出します。
array3[1]で[4, 5, 6]を呼び出します。
array3[2]で[7, 8, 9]を呼び出します。
// 二次元配列
array3[0][0]で 1 を呼び出します。
array3[0][1]で 2 を呼び出します。
array3[0][2]で 3 を呼び出します。

わかりやすく array3[0] を配列「array4」にすると、

// 一次元配列
array4 = array3[0] のとき(array4 = [1, 2, 3] のとき)
array4[0]で 1 を呼び出します。
array4[1]で 2 を呼び出します。
array4[2]で 3 を呼び出します。

ここで気をつけていただきたいのが、array3[n][m] で n 行目の m 番目を呼び込むということです。

二次元配列array3 から「 6 」の値を呼び出したいときは、array3[1][2] となります。

変数Xや変数Yを使うとき、X は横軸(列)、Yは縦軸(行)で使うことが多いです。
その場合、array3[X][Y] ではないので注意です。正しくは array3[Y][X] です。

最後にJavaScript全体のソースコードを載せておきます。

// ============ 変数 ============

// フィールドサイズ
const FIELD_X = 10   // 横のマスの数
const FIELD_Y = 20   // 縦のマスの数
const MINO_SIZE = 30 // マスの大きさ

// キャンバスの設定
let canvas = document.getElementById("canvas01")
let conText = canvas.getContext("2d")
canvas.width = MINO_SIZE * FIELD_X
canvas.height = MINO_SIZE * FIELD_Y
canvas.style.border = "4px solid #050505"

// 色の設定
const COLOR = [
    "#F2F2F2",    // フィールド背景
    "#C8C8C8"     // 枠の線
]

// フィールドの初期設定
let field = []
for (let i = 0; i < FIELD_Y; i++) {
    field[i] = []
    for (let j = 0; j < FIELD_X; j++) {
        field[i][j] = 0
    }
}

// フィールド描画のテスト
field[0][0] = 1
field[3][5] = 1
field[19][9] = 1


// ============ 関数 ============

// フィールドの表示
function display() {
    for (let i = 0; i < FIELD_Y; i++) {
        for (let j =0; j < FIELD_X; j++) {
            // 塗りつぶしの四角を描画
            conText.fillStyle = COLOR[field[i][j]]
            conText.fillRect(MINO_SIZE * j, MINO_SIZE * i, MINO_SIZE, MINO_SIZE)

            // 輪郭の四角を描画
            conText.strokeStyle = COLOR[1]
            conText.lineWidth = 1
            conText.strokeRect(MINO_SIZE * j, MINO_SIZE * i, MINO_SIZE, MINO_SIZE)
        }
    }
}


// ============ 実行 ============

// 初期画面の表示
display()

次回は「3日目 テトリミノの設定と描写」です。