2048は、4x4のグリッド上でタイルをスライドさせて同じ数字を合体させるパズルゲームです。このゲームを作ることで、2次元配列の操作やキーボード入力の処理といったゲーム開発の基本が身につきます。
まずは4x4のグリッドを2次元配列で作りましょう。グリッドはゲームの「盤面」にあたります。最初は全てのセルを0(空)で埋めて、ランダムな場所に2つのタイルを置きます。
var SIZE = 4;
var grid = [];
function init() {
grid = [];
for (var r = 0; r < SIZE; r++) {
grid[r] = [];
for (var c = 0; c < SIZE; c++) {
grid[r][c] = 0;
}
}
addRandomTile();
addRandomTile();
}
grid[r][c] で行(r)と列(c)の位置にあるタイルの値にアクセスできます。0は「空きマス」を表しています。
空いているセルを探して、そこにランダムに2か4のタイルを追加しましょう。90%の確率で2、10%の確率で4が出るようにします。
function emptyCells() {
var cells = [];
for (var r = 0; r < SIZE; r++) {
for (var c = 0; c < SIZE; c++) {
if (grid[r][c] === 0) cells.push({ r: r, c: c });
}
}
return cells;
}
function addRandomTile() {
var empty = emptyCells();
if (empty.length === 0) return;
var cell = empty[Math.floor(Math.random() * empty.length)];
grid[cell.r][cell.c] = Math.random() < 0.9 ? 2 : 4;
}
emptyCells() で空きマスの一覧を作り、そこからランダムに1つ選んで値を入れています。Math.random() を使ったランダム選択は、ゲーム開発でとてもよく使うテクニックです。
2048のコアとなるのが「スライド処理」です。プレイヤーが方向キーを押したとき、タイルを寄せて同じ数字のタイルを合体させます。まず、1行分を左にスライドする関数を作りましょう。
function slideRow(row) {
// ゼロ(空きマス)を除去
var filtered = row.filter(function (v) { return v !== 0; });
var merged = [];
var scoreGain = 0;
for (var i = 0; i < filtered.length; i++) {
if (i + 1 < filtered.length && filtered[i] === filtered[i + 1]) {
var newVal = filtered[i] * 2;
merged.push(newVal);
scoreGain += newVal;
i++; // 次をスキップ
} else {
merged.push(filtered[i]);
}
}
// 残りをゼロで埋める
while (merged.length < SIZE) {
merged.push(0);
}
return { row: merged, scoreGain: scoreGain };
}
このコードでは、まず0を除いて詰めてから、隣り合う同じ数字を合体させています。[2, 2, 4, 0] なら [4, 4, 0, 0] になります。
上下左右すべての方向に対応するために、グリッドを回転させて「常に左方向のスライド」で処理する方法を使います。
function rotateGrid(g, times) {
var result = g;
for (var t = 0; t < times; t++) {
var newGrid = [];
for (var r = 0; r < SIZE; r++) {
newGrid[r] = [];
for (var c = 0; c < SIZE; c++) {
newGrid[r][c] = result[c][SIZE - 1 - r];
}
}
result = newGrid;
}
return result;
}
左を0回転、上を1回転、右を2回転、下を3回転させることで、すべての方向を1つのslideRow関数で処理できます。これはとてもスマートなテクニックです。
プレイヤーの操作を受け取るために、キーボードイベントを設定しましょう。矢印キーとWASDキーの両方に対応させます。
document.addEventListener('keydown', function (e) {
var keyMap = {
ArrowLeft: 'left', ArrowRight: 'right',
ArrowUp: 'up', ArrowDown: 'down',
a: 'left', d: 'right', w: 'up', s: 'down'
};
var dir = keyMap[e.key];
if (dir) {
e.preventDefault();
move(dir);
}
});
keyMapオブジェクトでキーと方向を対応させています。e.preventDefault()は、矢印キーでページがスクロールしてしまうのを防ぎます。
全てのマスが埋まり、隣り合う同じ数字がなくなったらゲームオーバーです。
function canMove() {
for (var r = 0; r < SIZE; r++) {
for (var c = 0; c < SIZE; c++) {
if (grid[r][c] === 0) return true;
var val = grid[r][c];
if (c + 1 < SIZE && grid[r][c + 1] === val) return true;
if (r + 1 < SIZE && grid[r + 1][c] === val) return true;
}
}
return false;
}
空きマスがあるか、隣り合う同じ数字があるかをチェックします。どちらもなければ、もう動かせないのでゲームオーバーです。
おつかれさまでした!ここまでで2048の基本が完成しました。2次元配列でグリッドを管理し、スライド&マージのロジックを組み、キー入力で操作できるようにしました。さらに発展させるなら、タイルにアニメーションを付けたり、スワイプ操作でスマホ対応にしたり、5x5の大きなグリッドに挑戦してみましょう。
A: はい、大丈夫です。このチュートリアルではステップごとにコードを書いていくので、初めての方でも順番に進めれば完成できます。わからないところがあれば、ひなテックの教室で質問もできますよ。
A: 基本部分は約30分〜1時間で作れます。見た目をこだわったり機能を追加すると、さらに楽しく発展させられます。