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?

Same Game を vanilla JS で実装した - フラッドフィル + 重力 + 列圧縮

0
Posted at

作ったもの

Same Gamehttps://sen.ltd/portfolio/same-game/

スクリーンショット

  • 3 難易度(10×10/3 色、15×12/4 色、20×15/5 色)
  • ホバーで候補グループをハイライト、クリックで削除(モバイルはダブルタップ)
  • Undo 機能
  • 難易度別ベストスコア(localStorage)
  • 全消しボーナス(+1000)
  • 日英 UI、ダーク / ライト

vanilla JS、ゼロ依存、ビルド不要node --test で 53 ケース。
昔作った自作の Same Game を、portfolio 用にリファクタして移植しました。

スコア = (個数 - 2)²

指数スコアが戦略を生む。2 個だと 0 点、3 個で 1、5 個で 9、10 個で 64、20 個で 324。1 つの大きい塊を作る方が、小さく削るより圧倒的に得。上手いプレイヤーは色を溜めて一気に消す。

3 段階のアルゴリズム

1. フラッドフィル(グループ検出)

const stack = [[row, col]];
while (stack.length > 0) {
  const [r, c] = stack.pop();
  for (const [dr, dc] of [[-1,0],[1,0],[0,-1],[0,1]]) {
    if (board[r+dr]?.[c+dc] === target) {
      points.push([r+dr, c+dc]);
      stack.push([r+dr, c+dc]);
    }
  }
}

DFS + Set で訪問済み管理。1 マスしか見つからなければ null を返す(単独クリックで消えるのはルール違反)。

2. 重力(各列を底に詰める)

各列について、下から順に非 null 値を積み直す:

for (let col = 0; col < cols; col++) {
  const stack = [];
  for (let row = rows - 1; row >= 0; row--) {
    if (board[row][col] !== null) stack.push(board[row][col]);
  }
  for (let i = 0; i < stack.length; i++) {
    result[rows - 1 - i][col] = stack[i];
  }
}

3. 列圧縮(空の列を左に寄せる)

列全体が空になったら、右側の列を左にシフト。これで盤面が散らばらず、連鎖が続きやすくなる。

次の手の有無チェック

// 右と下だけ見れば十分(重複チェック回避)
if (board[row][col + 1] === v) return true;
if (board[row + 1][col] === v) return true;

(r, c)(r, c+1) がマッチしている場合、(r, c) から見つかる。左や上を見る必要はない。

Undo は参照コピーで無料

play() が新しい盤面オブジェクトを返すので、履歴には参照を積むだけ。deep-copy 不要。50 手分の履歴でもメモリはほぼゼロ。

シリーズ

100+ 公開ポートフォリオ シリーズの #101 です(目標通過後のオーバーアチーブ)。

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?