PR

3日目 テトリミノの設定と描写【JavaScriptの多次元配列】

テトリスを作ろう

はじめに

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

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

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

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

3日目でやること

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

今回は、テトリミノ(テトリスのブロック)を多次元配列の変数で設定して、フィールド上に描画するところまでをやっていきます。

3日目 テトリミノの設定と描写

全体のソースコード

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

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",   // 枠の線
    "#00F2F2",   // Iミノ 水色
    "#F2F200",   // Oミノ 黄色
    "#00F200",   // Sミノ 黄緑
    "#F20000",   // Zミノ 赤
    "#0000F2",   // Jミノ 青
    "#F2A200",   // Lミノ オレンジ
    "#F200F2"    // Tミノ 紫
]

// フィールドの初期設定
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 mino_x = Math.ceil((FIELD_X / 2) - 2)
let mino_y = 0

let mino_type = Math.trunc(Math.random() * 7)
let mino_angle = 0

let minoshapes = [
// mino_type_I
    // mino_angle_0
    [[
        [0,2,0,0],
        [0,2,0,0],
        [0,2,0,0],
        [0,2,0,0]
    ],
    // mino_angle_90
    [
        [0,0,0,0],
        [0,0,0,0],
        [2,2,2,2],
        [0,0,0,0]
    ],
    // mino_angle_180
    [
        [0,2,0,0],
        [0,2,0,0],
        [0,2,0,0],
        [0,2,0,0]
    ],
    // mino_angle_270
    [
        [0,0,0,0],
        [0,0,0,0],
        [2,2,2,2],
        [0,0,0,0]
    ]],
// mino_type_O
    // mino_angle_0
    [[
        [0,3,3,0],
        [0,3,3,0],
        [0,0,0,0],
        [0,0,0,0]
    ],
    // mino_angle_90
    [
        [0,3,3,0],
        [0,3,3,0],
        [0,0,0,0],
        [0,0,0,0]
    ],
    // mino_angle_180
    [
        [0,3,3,0],
        [0,3,3,0],
        [0,0,0,0],
        [0,0,0,0]
    ],
    // mino_angle_270
    [
        [0,3,3,0],
        [0,3,3,0],
        [0,0,0,0],
        [0,0,0,0]
    ]],
// mino_type_S
    // mino_angle_0
    [[
        [0,4,4,0],
        [4,4,0,0],
        [0,0,0,0],
        [0,0,0,0]
    ],
    // mino_angle_90
    [
        [0,4,0,0],
        [0,4,4,0],
        [0,0,4,0],
        [0,0,0,0]
    ],
    // mino_angle_180
    [
        [0,4,4,0],
        [4,4,0,0],
        [0,0,0,0],
        [0,0,0,0]
    ],
    // mino_angle_270
    [
        [0,4,0,0],
        [0,4,4,0],
        [0,0,4,0],
        [0,0,0,0]
    ]],
// mino_type_Z
    // mino_angle_0
    [[
        [5,5,0,0],
        [0,5,5,0],
        [0,0,0,0],
        [0,0,0,0]
    ],
    // mino_angle_90
    [
        [0,0,5,0],
        [0,5,5,0],
        [0,5,0,0],
        [0,0,0,0]
    ],
    // mino_angle_180
    [
        [5,5,0,0],
        [0,5,5,0],
        [0,0,0,0],
        [0,0,0,0]
    ],
    // mino_angle_270
    [
        [0,0,5,0],
        [0,5,5,0],
        [0,5,0,0],
        [0,0,0,0]
    ]],
// mino_type_J
    // mino_angle_0
    [[
        [0,0,6,0],
        [0,0,6,0],
        [0,6,6,0],
        [0,0,0,0]
    ],
    // mino_angle_90
    [
        [0,6,0,0],
        [0,6,6,6],
        [0,0,0,0],
        [0,0,0,0]
    ],
    // mino_angle_180
    [
        [0,6,6,0],
        [0,6,0,0],
        [0,6,0,0],
        [0,0,0,0]
    ],
    // mino_angle_270
    [
        [6,6,6,0],
        [0,0,6,0],
        [0,0,0,0],
        [0,0,0,0]
    ]],
// mino_type_L
    // mino_angle_0
    [[
        [0,7,0,0],
        [0,7,0,0],
        [0,7,7,0],
        [0,0,0,0]
    ],
    // mino_angle_90
    [
        [0,7,7,7],
        [0,7,0,0],
        [0,0,0,0],
        [0,0,0,0]
    ],
    // mino_angle_180
    [
        [0,7,7,0],
        [0,0,7,0],
        [0,0,7,0],
        [0,0,0,0]
    ],
    // mino_angle_270
    [
        [0,0,7,0],
        [7,7,7,0],
        [0,0,0,0],
        [0,0,0,0]
    ]],
// mino_type_T
    // mino_angle_0
    [[
        [8,8,8,0],
        [0,8,0,0],
        [0,0,0,0],
        [0,0,0,0]
    ],
    // mino_angle_90
    [
        [0,8,0,0],
        [8,8,0,0],
        [0,8,0,0],
        [0,0,0,0]
    ],
    // mino_angle_180
    [
        [0,8,0,0],
        [8,8,8,0],
        [0,0,0,0],
        [0,0,0,0]
    ],
    // mino_angle_270
    [
        [0,8,0,0],
        [0,8,8,0],
        [0,8,0,0],
        [0,0,0,0]
    ]]
]


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

// フィールドの表示
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)
        }
    }
}

// テトリミノの表示
function drawmino() {
    for (let i = 0; i < 4; i++) {
        for (let j = 0; j < 4; j++) {
            if (minoshapes[mino_type][mino_angle][i][j] >= 1) {
                // 新しい座標を定義
                let px = MINO_SIZE * (mino_x + j)
                let py = MINO_SIZE * (mino_y + i)

                // 塗りつぶしの四角を描画
                conText.fillStyle = COLOR[minoshapes[mino_type][mino_angle][i][j]]
                conText.fillRect(px, py, MINO_SIZE, MINO_SIZE)

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


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

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

JavaScriptの解説

色の設定

// 色の設定
const COLOR = [
    "#F2F2F2",   // フィールド背景
    "#C8C8C8",   // 枠の線
    "#00F2F2",   // Iミノ 水色
    "#F2F200",   // Oミノ 黄色
    "#00F200",   // Sミノ 黄緑
    "#F20000",   // Zミノ 赤
    "#0000F2",   // Jミノ 青
    "#F2A200",   // Lミノ オレンジ
    "#F200F2"    // Tミノ 紫
]

配列の変数 COLOR に要素を追加します。

テトリスでは7種類の形のブロックを使います。このブロックのことをテトリミノと呼びます。

テトリミノとは、パズルゲーム「テトリス」に登場するブロックの名称です。4個の正方形をつなげた図形「テトロミノ」が名前の由来です。

ちなみに、複数の同じ大きさの正方形を辺どうしでつなげた多角形の総称は「ポリオミノ」で、4個の正方形をつなげた図形を「テトロミノ」、5個の正方形をつなげた図形を「ペントミノ」と呼びます。2個の正方形をつなげた図形が「ドミノ」です。

テトリミノの初期設定

// テトリミノの初期設定
let mino_x = Math.ceil((FIELD_X / 2) - 2)
let mino_y = 0

let mino_type = Math.trunc(Math.random() * 7)
let mino_angle = 0
let mino_x = Math.ceil((FIELD_X / 2) – 2)

テトリミノを描画する x座標「mino_x」を指定します。座標は、テトリミノ 4×4マスの左上の座標です。

変数mino_xの初期値は、フィールド幅の真ん中から 2マス(4マスの半分)左の位置です。

FIELD_X(フィールドの横のマス数)を 2で割って、2マス引きます。FIELD_X が奇数のとき、2で割ると端数が出るので Math.ceil() を使って小数部分を切り上げます。

Math.ceil( .. ) は、小数部分を切り上げた値を取得します。Math.ceil(3) ならそのまま「 3 」を返し、Math.ceil(3.5) なら「 4 」となります。

let mino_y = 0

テトリミノを描画する y座標「mino_y」を指定します。座標は、テトリミノ 4×4 マスの左上の座標です。

変数mino_yの初期値は、「 0 」(一番上)です。

let mino_type = Math.trunc(Math.random() * 7)

テトリミノの形を7種類の中から1つ選びます。

Math.random() は、0 から 1 未満の小数をランダムで生成します。(例:0.72956・・・)

生成された小数を7倍して小数部分を切り捨てると「0, 1, 2, 3, 4, 5, 6」の7つの中から1つの値が取得できます。

Math.trunc( .. ) は、小数部分を切り捨てた値を取得します。

0.72956・・ * 7 = 5.1069・・となるので、Math.trunc((0.72956・・・) * 7) なら「 5 」となります。

Math.ceil( .. ) と Math.trunc( .. ) と Math.floor( .. ) の関係

Math.ceil が「切り上げ」で、Math.ceil(1.3) → 2、Math.ceil(-1.3) → -1
Math.trunc が「切り捨て」で、Math.trunc(1.3) → 1、Math.trunc(-1.3) → -1
Math.floor が「切り下げ」で、Math.floor(1.3) → 1、Math.floor(-1.3) → -2

マイナスの値をあつかう時には注意しましょう。

let mino_angle = 0

テトリミノの回転した形を指定します。時計回りに回転する(0 → 90 → 180 → 270 → 0 →・・)ごとに変数mino_angleの値を 0 → 1 → 2 → 3 → 0 →・・と変更します。

変数mino_yの初期値は、「 0 」(回転角度)です。

let minoshapes = [ .. ]

テトリミノの形を多次元配列の変数minoshapesで定義します。

let minoshapes = [
// mino_type_I
    // mino_angle_0
    [[
        [0,2,0,0],
        [0,2,0,0],
        [0,2,0,0],
        [0,2,0,0]
    ],
    // mino_angle_90
    [
        [0,0,0,0],
        [0,0,0,0],
        [2,2,2,2],
        [0,0,0,0]
    ],
  :
  :
    // mino_angle_270
    [
        [0,8,0,0],
        [0,8,8,0],
        [0,8,0,0],
        [0,0,0,0]
    ]]
]

テトリミノの形は、4×4 の2次元配列で定義します。

Iミノ(長い棒のテトリミノ)は、

// mino_type_I
[
    [0,2,0,0],
    [0,2,0,0],
    [0,2,0,0],
    [0,2,0,0]
]

となります。

テトリミノの回転した形を、4×(4×4) の3次元配列で定義します。

Tミノ(T字のテトリミノ)の回転を含んだ配列は、

// mino_type_T
    // mino_angle_0
    [[
        [8,8,8,0],
        [0,8,0,0],
        [0,0,0,0],
        [0,0,0,0]
    ],
    // mino_angle_90
    [
        [0,8,0,0],
        [8,8,0,0],
        [0,8,0,0],
        [0,0,0,0]
    ],
    // mino_angle_180
    [
        [0,8,0,0],
        [8,8,8,0],
        [0,0,0,0],
        [0,0,0,0]
    ],
    // mino_angle_270
    [
        [0,8,0,0],
        [0,8,8,0],
        [0,8,0,0],
        [0,0,0,0]
    ]]

となります。

7種類のテトリミノの回転した形を、7×(4×4×4) の4次元配列で定義します。

let minoshapes = [
    [
        // mino_type_I
    ],
    [
        // mino_type_O
    ],
    [
        // mino_type_S
    ],
    [
        // mino_type_Z
    ],
    [
        // mino_type_J
    ],
    [
        // mino_type_L
    ],
    [
        // mino_type_T
    ]
]

JavaScriptの多次元配列から要素を呼び出す

多次元配列の変数minoshapesから、テトリミノの配列や値を呼び出します。

「7種類のテトリミノの形」「4つの回転角度」「縦4マス」「横4マス」の四次元配列が、変数minoshapesです。

minoshapes[0] でIミノの4つの回転角度を、minoshapes[1] でOミノの4つの回転角度を、minoshapes[2] でSミノの4つの回転角度を呼び出します。

また、minoshapes[2, 0] でSミノの0度の回転角度を、minoshapes[2, 1] でSミノの90度の回転角度を、minoshapes[2, 2] でSミノの180度の回転角度を呼び出します。

そして、minoshapes[(テトリミノの形), (回転角度), (縦), (横)] で1つ値を呼び出すことができます。

多次元配列の変数minoshapesから要素を呼び出し、テトリミノを表示します。

// テトリミノの表示
function drawmino() {
    for (let i = 0; i < 4; i++) {
        for (let j = 0; j < 4; j++) {
            if (minoshapes[mino_type][mino_angle][i][j] >= 1) {
                // 新しい座標を定義
                let px = MINO_SIZE * (mino_x + j)
                let py = MINO_SIZE * (mino_y + i)

                // 塗りつぶしの四角を描画
                conText.fillStyle = COLOR[minoshapes[mino_type][mino_angle][i][j]]
                conText.fillRect(px, py, MINO_SIZE, MINO_SIZE)

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

function drawmino() { .. }

関数名を drawmino にして、{ } 内に実行する処理を定義します。drawmino() で関数を呼び出すことができます。

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

繰り返し「for文」です。{ .. } 内の処理を、i が 0から 1、2、3 と繰り返します。

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

for文内にある「for文」です。{ .. } 内の処理を、i が 0のときに j が 0から3まで繰り返し、i が 1のときに j が 0から3まで繰り返し、i が 2のときに j が 0から3まで繰り返し、i が 3のときに j が 0から3まで繰り返します。

if (minoshapes[mino_type][mino_angle][i][j] >= 1) { .. }

「if文」です。

if文は、条件を満たすときに { } 内の処理を行います。条件を満たさないときは { } 内の処理を飛ばします。

if (条件) {
    処理
}

のように記述します。

変数minoshapesは、[(テトリミノの形), (回転角度), (縦), (横)] で1つ値を呼び出すことができます。

変数mino_typeは7種類あるテトリミノの形で、0から6までのランダムな値です。

変数mino_angleはテトリミノの回転角度で、初期値は 0です。

minoshapes[mino_type][mino_angle][i][j]で、ランダムで選ばれたテトリミノの回転 0度の形で(4×4マスの)縦 i番目、横 j番目の値です。

例えば、minoshapes[0, 0, i, j] の場合、

// mino_type_I
[
    [0,2,0,0],
    [0,2,0,0],
    [0,2,0,0],
    [0,2,0,0]
]

上の配列の i行目の j番目の値となります。

minoshapes[0, 0, 0, 0] → 0、minoshapes[0, 0, 0, 1] → 2です。

minoshapes[mino_type][mino_angle][i][j] >= 1

配列minoshapesから呼び出した値が 1以上なら { } 内の処理を実行します。

let px = MINO_SIZE * (mino_x + j)|let py = MINO_SIZE * (mino_y + i)

変数pxに、四角を描画するために「キャンバスの左上端から右方向の距離」を指定します。

MINO_SIZE * (mino_x + j)は、(マスの大きさ) × ( (テトリミノを描画する x座標) + (横 j番目) )です。

変数pyに、四角を描画するために「キャンバスの左上端から下方向の距離」を指定します。

MINO_SIZE * (mino_y + i)は、(マスの大きさ) × ( (テトリミノを描画する y座標) + (横 i番目) )です。

conText.fillStyle = COLOR[minoshapes[mino_type][mino_angle][i][j]]

conText.fillStyle = COLOR[ ] で、塗りつぶしの色を指定します。

minoshapes[mino_type][mino_angle][i][j]は、ランダムで選ばれたテトリミノの回転 0度の形で(4×4マスの)縦 i番目、横 j番目の値です。

値は、テトリミノの形によって変わります。Iミノは「 2 」、Oミノは「 3 」、Sミノのときは「 4 」です。

// 色の設定
const COLOR = [
    "#F2F2F2",   // フィールド背景
    "#C8C8C8",   // 枠の線
    "#00F2F2",   // Iミノ 水色
    "#F2F200",   // Oミノ 黄色
    "#00F200",   // Sミノ 黄緑
    "#F20000",   // Zミノ 赤
    "#0000F2",   // Jミノ 青
    "#F2A200",   // Lミノ オレンジ
    "#F200F2"    // Tミノ 紫
]

配列の変数COLORから、それぞれに対応した色の値を取得します。

conText.fillRect(px, py, MINO_SIZE, MINO_SIZE)

conText.fillStyle( ) で、塗りつぶす四角の位置とサイズを指定します。

.fillStyle(左上端から右方向の距離, 左上端から下方向の距離, 横幅, 高さ) の四角形です。

conText.strokeRect(px, py, MINO_SIZE, MINO_SIZE)

同様に、輪郭の四角の位置とサイズを指定します。

.strokeRect(左上端から右方向の距離, 左上端から下方向の距離, 横幅, 高さ) の四角形です。

関数を呼び出す

定義した関数は、呼び出すことで実行することができます。

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

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

フィールドを表示する関数を呼び出します。

drawmino()

テトリミノを表示する関数を呼び出します。

最後に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",   // 枠の線
    "#00F2F2",   // Iミノ 水色
    "#F2F200",   // Oミノ 黄色
    "#00F200",   // Sミノ 黄緑
    "#F20000",   // Zミノ 赤
    "#0000F2",   // Jミノ 青
    "#F2A200",   // Lミノ オレンジ
    "#F200F2"    // Tミノ 紫
]

// フィールドの初期設定
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 mino_x = Math.ceil((FIELD_X / 2) - 2)
let mino_y = 0

let mino_type = Math.trunc(Math.random() * 7)
let mino_angle = 0

let minoshapes = [
// mino_type_I
    // mino_angle_0
    [[
        [0,2,0,0],
        [0,2,0,0],
        [0,2,0,0],
        [0,2,0,0]
    ],
    // mino_angle_90
    [
        [0,0,0,0],
        [0,0,0,0],
        [2,2,2,2],
        [0,0,0,0]
    ],
    // mino_angle_180
    [
        [0,2,0,0],
        [0,2,0,0],
        [0,2,0,0],
        [0,2,0,0]
    ],
    // mino_angle_270
    [
        [0,0,0,0],
        [0,0,0,0],
        [2,2,2,2],
        [0,0,0,0]
    ]],
// mino_type_O
    // mino_angle_0
    [[
        [0,3,3,0],
        [0,3,3,0],
        [0,0,0,0],
        [0,0,0,0]
    ],
    // mino_angle_90
    [
        [0,3,3,0],
        [0,3,3,0],
        [0,0,0,0],
        [0,0,0,0]
    ],
    // mino_angle_180
    [
        [0,3,3,0],
        [0,3,3,0],
        [0,0,0,0],
        [0,0,0,0]
    ],
    // mino_angle_270
    [
        [0,3,3,0],
        [0,3,3,0],
        [0,0,0,0],
        [0,0,0,0]
    ]],
// mino_type_S
    // mino_angle_0
    [[
        [0,4,4,0],
        [4,4,0,0],
        [0,0,0,0],
        [0,0,0,0]
    ],
    // mino_angle_90
    [
        [0,4,0,0],
        [0,4,4,0],
        [0,0,4,0],
        [0,0,0,0]
    ],
    // mino_angle_180
    [
        [0,4,4,0],
        [4,4,0,0],
        [0,0,0,0],
        [0,0,0,0]
    ],
    // mino_angle_270
    [
        [0,4,0,0],
        [0,4,4,0],
        [0,0,4,0],
        [0,0,0,0]
    ]],
// mino_type_Z
    // mino_angle_0
    [[
        [5,5,0,0],
        [0,5,5,0],
        [0,0,0,0],
        [0,0,0,0]
    ],
    // mino_angle_90
    [
        [0,0,5,0],
        [0,5,5,0],
        [0,5,0,0],
        [0,0,0,0]
    ],
    // mino_angle_180
    [
        [5,5,0,0],
        [0,5,5,0],
        [0,0,0,0],
        [0,0,0,0]
    ],
    // mino_angle_270
    [
        [0,0,5,0],
        [0,5,5,0],
        [0,5,0,0],
        [0,0,0,0]
    ]],
// mino_type_J
    // mino_angle_0
    [[
        [0,0,6,0],
        [0,0,6,0],
        [0,6,6,0],
        [0,0,0,0]
    ],
    // mino_angle_90
    [
        [0,6,0,0],
        [0,6,6,6],
        [0,0,0,0],
        [0,0,0,0]
    ],
    // mino_angle_180
    [
        [0,6,6,0],
        [0,6,0,0],
        [0,6,0,0],
        [0,0,0,0]
    ],
    // mino_angle_270
    [
        [6,6,6,0],
        [0,0,6,0],
        [0,0,0,0],
        [0,0,0,0]
    ]],
// mino_type_L
    // mino_angle_0
    [[
        [0,7,0,0],
        [0,7,0,0],
        [0,7,7,0],
        [0,0,0,0]
    ],
    // mino_angle_90
    [
        [0,7,7,7],
        [0,7,0,0],
        [0,0,0,0],
        [0,0,0,0]
    ],
    // mino_angle_180
    [
        [0,7,7,0],
        [0,0,7,0],
        [0,0,7,0],
        [0,0,0,0]
    ],
    // mino_angle_270
    [
        [0,0,7,0],
        [7,7,7,0],
        [0,0,0,0],
        [0,0,0,0]
    ]],
// mino_type_T
    // mino_angle_0
    [[
        [8,8,8,0],
        [0,8,0,0],
        [0,0,0,0],
        [0,0,0,0]
    ],
    // mino_angle_90
    [
        [0,8,0,0],
        [8,8,0,0],
        [0,8,0,0],
        [0,0,0,0]
    ],
    // mino_angle_180
    [
        [0,8,0,0],
        [8,8,8,0],
        [0,0,0,0],
        [0,0,0,0]
    ],
    // mino_angle_270
    [
        [0,8,0,0],
        [0,8,8,0],
        [0,8,0,0],
        [0,0,0,0]
    ]]
]


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

// フィールドの表示
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)
        }
    }
}

// テトリミノの表示
function drawmino() {
    for (let i = 0; i < 4; i++) {
        for (let j = 0; j < 4; j++) {
            if (minoshapes[mino_type][mino_angle][i][j] >= 1) {
                // 新しい座標を定義
                let px = MINO_SIZE * (mino_x + j)
                let py = MINO_SIZE * (mino_y + i)

                // 塗りつぶしの四角を描画
                conText.fillStyle = COLOR[minoshapes[mino_type][mino_angle][i][j]]
                conText.fillRect(px, py, MINO_SIZE, MINO_SIZE)

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


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

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

次回は「4日目 テトリミノの落下と回転」です。