SolokusというパズルゲームをHaskellで解いてみた。
Solokusは気軽に遊べるパズルゲーム
Solokusはスマホ用のパズルゲームで、複数の正方形が組み合わさったピースを正方形の中に敷き詰めるとステージクリア。 たぶんBlokusから発想を得ていて、同じ色のピースは角を接するように配置する必要がある。
これが結構楽しい。 なにがいいかって、あまり難しすぎないので気軽にプレイできて、適当に試行錯誤して解くことができる。 あまり先読みとか理詰めで考えずにプレーできる(逆にあまりそういう風には解けない)。
同じようなピースを詰めるパズルのペントミノとかは自由度がありすぎて、適当に詰めていくと終盤どうにもはまらなくなって解けないことが多いんだけど、Solokusは4色がそれぞれ4隅からと決まっていて、また角を接して置かないといけないという制約があるので、試行錯誤できる程よい難易度になっている。 4x4または5x5と盤面もそれほど広くなく、また前半のステージではピースの回転や反転がない、などととっつきやすくなっている。
Haskellでパズルを解く
ちょっと話題は変わって、先日「Haskellによる関数プログラミングの思考法」という翻訳本が発売されたということらしく、その原作本というものがあったのでちらっと読んでみた。 その中に数独を解く章があって、それを読んでたらパズルを解いてみたい気持ちになった。
ということでSolokusソルバを作ってみた。
何のひねりもない力技で、置けるパターンを総当りで探す、という方法。 今のところSolokusの問題は盤面がそんなに広くなく、またピースが4色に分かれているので組み合わせがそれほど膨大にならない、という前提があるのでとっかかりとしてはそれでいいかなと。
凝ったことをやってないのでアレだけど、Solokusのルールは置ける候補地(斜めに同色がある)の列挙、置けるかどうかの判定(ピースが重ならない、同色と辺を接してない)のどちらも対象のマスだけ調べればいいルールだけで簡単なので、なかなかいい遊びになった。
雑感
Haskellでパズルを総当りで解く場合、途中まで進行した盤面が複数あって、それぞれに次の手を反映させた次の盤面を複数返す関数をconcatMap
で適用してフラットにして、それをすべての手についてfoldr
で最後まで行う、というのがイディオムかなぁとなんとなく思った。