0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

マインスイーパを純粋関数エンジン + BFS フラッドフィルで実装した

0
Posted at

なぜ作ったか

マインスイーパは誰もがプレイしたことのあるゲームですが、自分で実装すると「初手安全保証」「フラッドフィルの停止条件」「フラグと残り地雷のカウンタ」など、意外と設計判断が必要。純粋関数として切り出すと、テストも書きやすく構造がきれいになります。

作ったもの

Minesweeperhttps://sen.ltd/portfolio/minesweeper/

スクリーンショット

  • 4 段階の難易度(初級 9×9 / 中級 16×16 / 上級 30×16 / カスタム)
  • 初手安全保証(クリック位置 + 周囲 8 セルに地雷なし)
  • BFS フラッドフィル(空セルの自動展開)
  • キーボード操作(矢印 / Space / F)
  • タイマー、ベストタイム記録(localStorage)
  • クラシック Win95 風 3D ボーダー
  • 日本語 / 英語 UI

vanilla JS、ゼロ依存、ビルド不要node --test で 24 ケース。

初手安全保証

初手で地雷を踏まないために、ボードは最初のクリック後に生成。クリック位置 + 周囲 8 セルを「安全ゾーン」として除外:

export function createBoard(rows, cols, mineCount, safeRow, safeCol) {
  const safeSet = new Set();
  for (let dr = -1; dr <= 1; dr++) {
    for (let dc = -1; dc <= 1; dc++) {
      safeSet.add((safeRow + dr) * cols + (safeCol + dc));
    }
  }
  // 安全ゾーン外からランダムに地雷配置
  let eligible = positions.filter(([r, c]) => !safeSet.has(r * cols + c));
}

安全ゾーンが 9 セルなので、初手は必ず領域が開く。1 セルだけ開くよりずっと良い UX。

BFS フラッドフィル

隣接地雷数 0 のセルを開くと、連続する空セルを自動展開:

while (queue.length > 0) {
  const [r, c] = queue.shift();
  cur.revealed = true;

  if (cur.neighbors === 0) {
    // 周囲 8 セルをキューに追加
    queue.push([nr, nc]);
  }
}

ポイント: neighbors === 0 のセルだけ展開を継続。数字セル(1-8)は開示するが、そこでフロンティアを止める。これで「数字で縁取られた空き領域」が自然にできます。

イミュータブルな更新

revealCelltoggleFlag は新しいボードを返す:

const newBoard = board.map(r => r.map(c => ({ ...c })));

前のボード参照を保持するだけで undo が可能。純粋関数なのでテストも容易。

勝利判定

export function checkWin(board) {
  for (const row of board) {
    for (const cell of row) {
      if (!cell.mine && !cell.revealed) return false;
    }
  }
  return true;
}

地雷でないセルがすべて開示されたら勝利。フラグは関係ない(全地雷にフラグを立てる必要はない)。Windows 版と同じ仕様。

テスト

node --test で 24 ケース:

  • ボード生成(サイズ、地雷数、安全ゾーン)
  • フラッドフィル(地雷なしボードで全セル展開)
  • 地雷踏み判定
  • フラグトグル
  • 勝利判定
  • 隣接カウントの正確性

シリーズ

100+ 公開ポートフォリオ シリーズの #35 です。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?