2048の作り方 — JavaScriptでブラウザゲームを作ろう

このゲームで遊ぶ → ソースコード全文 →

このチュートリアルで学べること

2048は、4x4のグリッド上でタイルをスライドさせて同じ数字を合体させるパズルゲームです。このゲームを作ることで、2次元配列の操作やキーボード入力の処理といったゲーム開発の基本が身につきます。

ステップ1: グリッドの初期化とタイル追加

まずは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() を使ったランダム選択は、ゲーム開発でとてもよく使うテクニックです。

ステップ2: タイルのスライドとマージを作ろう

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] になります。

4方向への対応

上下左右すべての方向に対応するために、グリッドを回転させて「常に左方向のスライド」で処理する方法を使います。

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関数で処理できます。これはとてもスマートなテクニックです。

ステップ3: キー入力とゲームオーバー判定を実装しよう

プレイヤーの操作を受け取るために、キーボードイベントを設定しましょう。矢印キーと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の大きなグリッドに挑戦してみましょう。

よくある質問

Q: プログラミング初心者でも作れますか?

A: はい、大丈夫です。このチュートリアルではステップごとにコードを書いていくので、初めての方でも順番に進めれば完成できます。わからないところがあれば、ひなテックの教室で質問もできますよ。

Q: どのくらい時間がかかりますか?

A: 基本部分は約30分〜1時間で作れます。見た目をこだわったり機能を追加すると、さらに楽しく発展させられます。