
ココパズルのすべて
〜1日で作ったスライドパズルが、シンクロした話〜

この記事は team411 Advent Calendar 2025 の 6日目 の記事です。
他の投稿された記事は 👉️ こちら 👈️ からどうぞ。
昨日は 湯葉あれま さんの「初学者のためのReactによるToDoアプリ作成手順」でした。新入生研修から React をやり始めて、ここまで自分で学習しているのを見て、学習意欲を感じました。
はじめに
突然ですが、「ココパズル」という名前を聞いたことはあるでしょうか。
ブラウザで開くと、その場で遊べるスライドパズルが出てきます。
これは、最初から大層な目的があったわけではなくて、完全に身内ノリで始まったものです。
好きな画像でスライドパズル作って遊ぶことが目標でした。
ということでこの記事では、
- ココパズルがどんなゲームなのか
- 中でどんな仕組みで動いているのか
あたりを、ゆるく書いていきます。
ココパズルってどんなゲーム?
仕組み自体は、昔からあるスライドパズルそのものです。
N×N のマスにタイルが並んでいて、そのうち 1 マスだけが空白。空白の上下左右にあるタイルだけ動かせて、最終的に「1, 2, 3…」と順番に並べ直せたらクリア、というタイプのやつです。
ココパズルでは、盤面サイズを 2×2 から 6×6 まで選べます。
3×3 だと割とすぐに解けますが、5×5 や 6×6 まで行くと、考えなしではなかなか簡単に解くことはできません。
特徴をざっくり挙げると、
- 好きな画像をアップロードして、その画像を切り刻んだパズルにできる
- ゲーム開始と同時にタイマーが動き始めて、クリアすると経過時間が出る
- クリアした瞬間に紙吹雪が舞ったり、トーストが出たりする
といった感じで、最低限ちゃんとゲームになっている、くらいの内容です。
どうやってパズルを作っているか
あまりフロントのスタックの話はしませんが、ざっくりいうと「ブラウザで動く普通の React アプリ」です。
盤面は一次元の配列で持っています。
例えば 3×3 なら長さ 9 の配列を用意して、[1,2,3,4,5,6,7,8,0] みたいな形で「0 を空白、そのほかの数字をタイル」として扱うイメージです。
画面にはこの配列をグリッド状に並べて表示していて、タイルをクリックすると、そのタイルの位置と 0 の位置を見て、同じ行や同じ列の隣同士なら入れ替える、という処理をしています。
面倒なのは「どうやってシャッフルするか」です。
スライドパズルって、適当にランダムで並べると「そもそも絶対に解けない並び」になってしまうことがあります。
そこでココパズルでは、完成状態からスタートして、そこから、隣接しているもののみランダムにタイルを動かしまくるという方式にしています。
空白の上下左右にあるタイルだけを候補にして、その中からランダムに 1 枚を選んで動かす、という操作を繰り返すと、それっぽくグチャグチャになります。このとき、直前に動かしたタイルをすぐ戻すような手だけは除外して、無意味な往復にならないようにしています。
ここがポイントで、完成状態から合法な手だけで崩しているので、必ずどこかに「元の状態へ戻る経路」が存在します。
さらに、どのタイルを動かしたのかを全て記録しておけば、その履歴を逆順にたどるだけで、自動的に解答してくれる機能も作れます。
実際に自動回答では、シャッフル時に保存しておいた履歴をひっくり返して 1 手ずつ適用していくだけです。そこに少し待ち時間を挟んで、CSSアニメーションではなかなか綺麗なアニメーションが組めなかったので、Web Animations API でタイルをスッと動かすアニメーションを付けています。
最短手順を計算しているわけではありませんが、「ゲームを始めたときに実際に通ったルート」をそのまま再生しているので、ちゃんとゴールまでたどり着きます。
応用情報の問題とそっくりだった話
さて、本題です。
なんと、このココパズルを作成した10日後、2025 年春期の応用情報技術者試験午後問題の 1 つとして、3×3 のスライドパズルを題材にした設問が出題されました。[1]
内容としては、
- 3×3 の盤面の初期配置とゴール配置が与えられる
- 空白マスと隣接タイルの交換を 1 手とする
- 盤面を「ノード」、1 手の移動を「辺」とみなして探索していき、
ゴールまでの手順を求める
というものです。
問題文の中では、盤面を一次元配列で表現したり、キューを使って次に調べるノードを管理したり、既に調べた状態は二度と探索しないようにしたり、といった説明が丁寧に書かれていました。
要するに「スライドパズルをプログラムで解くためのアルゴリズムを理解しているか?」を問う問題です。
ここでココパズルの話に戻ると、
- 盤面を配列で持っている
- 合法な手だけで状態遷移している
- ゴールかどうかは「配列が完成形と一致するか」で見ている
といった部分が、そのまま試験のアルゴリズムと重なっていました。
要するに、1 日で作ったスライドパズルアプリの中でやっていたことが、そのまま試験問題として出てきてしまった、というわけです。
1日開発で何が残ったか
ココパズル自体は、見た目だけ見ると小さな遊び道具にしか見えないと思います。
ただ、中身でやっていることはわりとプログラミング的な話です。
状態空間をどう表すか、どんな操作を許すか、探索の履歴をどう持つか。
それらを全部コードで書き下ろしていくと、結果的に「アルゴリズムを実装している」ことになります。
そして、たまたまそのタイミングで応用情報に似た問題が出て、実際に試験でそれを読むことになりました。
遊びで作ったものが、そのまま勉強になり、ついでに試験対策にもなっていた、というのは、なかなかおもしろい経験でした。
これからやりたいこと
今のココパズルは、「完成状態からランダムに崩して、履歴を逆再生する」だけの素直な実装です。
これでも遊ぶ分には困らないのですが、せっかく応用情報でガッツリ扱われたので、もう少しアルゴリズム寄りに寄せた機能も入れてみたいと思っています。
例えば、A*探索を入れて、本当に最短の手順を計算したり、再帰的に外側から揃えていく解き方をプログラムにしたりしたいです。
おわりに
というわけで、身内ノリで 1 日で作ったスライドパズルが、10 日後に本物の試験問題として出てきてしまった話でした。
真面目に「応用情報対策アプリを作ります!」と気合いを入れて作ったわけではないのに、結果的にそういう役割も果たしてしまったのが面白いところです。
明日の team411 Advent Calendar は、
むつみん さんの「WingetとScoopでDotFilesを整備するぞよ」です。
自分も Windows 環境を整えるときに winget と scoop にはだいぶお世話になっているので、どんな構成で使っているのか読むのが楽しみです。
問題文は IPA の公式サイト から参照できます。 ↩︎