こんにちは!
エルフィールドでエンジニアとして働いている、H.Tです。

ナンバープレイスをテーマにしたプログラム作成シリーズの第3回です。

前回のプログラムでは、マスの順番に数字を埋めていく方式を採用しましたが、完成できないケースが多く発生しました。


そこで今回は、発想を逆転して、「マスを決めて数字を入れる」→「数字を決めて、それを入れられるマスを探す」

という方向に切り替えます。
実際にナンプレを解くときも、数字ごとに空き場所を絞るやり方は有効ですよね。



設計の考え方

前回まではマスの状態を特に管理していませんでしたが、今回は以下のような独自属性(フラグ)をTDタグに追加し、
状態を明示的に管理することにします。

属性名意味
done数字が入力済みなら1、未入力なら0
is1is9各数字がそのマスに入れられないなら1、入れられるなら0



■ プログラムの抜粋

● 数字1~9の配列

● 表の初期化(属性付与)


■ 主な関数と処理内容

● 数字を入れたときに他のマスを制約する関数

● 確定マス(1種類しか入れられない)をチェックして埋める関数


● 実際に数字を入れて状態を更新する関数




数字(1〜9)を先に決めて、各3×3ブロックに対して、その数字を入れられるマスを探してランダムに配置します。

■全体コード


これを実行すると・・・


出来ていない!!さらに・・・


結果は……失敗!!!

なんと、「2」の時点で詰んでしまうパターンが出てきました。
確率に任せた配置方法では、どうしても詰みが避けられない状況が生まれます。




■ 気づきと今後の展望


今回のチャレンジでは、

  • 発想を切り替えてマスの選び方を工夫した
  • 状態を属性で明示的に管理する方法に取り組んだ

という新しいアプローチを試しましたが、結果的にはまだ「完全な盤面を作る」には至りませんでした。

「もう答えだけ見せてほしい!」

と思ったあなた、大丈夫です。筆者もそう思っています(笑)でも今回はもう少しだけ寄り道をさせてください。
このシリーズの目的はあくまでも試行錯誤のプロセスを共有することです。

次回こそ、「どうすれば詰まらない盤面が作れるか?」という核心に迫っていきたいと思います!




■ 次回予告

・確実に埋まる盤面を作るにはどうすればいいのか?
・今回のような「先行入力+制約チェック」方式は改良の余地があるのか?
・いよいよ本格的な探索アルゴリズム導入か…?


というあたりをテーマに、次回はさらに深掘りしていきます。

それでは、また次回!👋