VBAでナンプレを作る。Rnd関数で問題作成

投稿者:

ナンプレ(数独)

ナンプレとは、ナンバープレース、数独とも呼ばれる数字パズルですね。
数独という呼び方は、「数字は独身に限る」の略なんだそうです。

ExcelVBAでナンプレをつくる

ナンプレの問題を作るには、縦・横・ブロックに重複しない数字を当てはめていく必要があります。

以下のロジックで考えていきます。

  1. 9×9配列を用意する
  2. ランダムな1~9の数字を取得する
    1. 乱数から整数を生成する
    2. 一度使った数字を避ける(重複)
  3. 列,行,3×3ブロックで重複した数字かチェックする
    1. 「絶対に当てはまらない数字」の場合
  4. 配列に格納する
  5. Excelに張り付ける

1.9×9配列を用意する

まずは盤面数字を格納する9×9(81マス)の配列を準備します。

Dim num(8, 8) As Integer

(8, 8) の配列を宣言すればOKですね。
(0~8, 0~8)の位置に数字を入れる動作を81回動かします。
num(i, ,j)として考えていきましょう。

2.ランダムな1~9の整数を取得する

2.1 乱数から整数を生成する

Rnd関数とInt関数の組み合わせでランダム数字を発生させることができます。
Rnd : 0~1未満の数字をランダムに発生させる
Int: 数字を丸めて整数を取得する

「Rnd*9」は 最大でも「 0.999…9 * 9」=「8.999…1」 となるのでInt関数で小数点以下を切り捨てられると8以上の数字にはなりません。
上記だと0~8が格納されます。

重複を避ける方法として、次項では配列arr(0~8)から1~9の整数を選びます。
生成するランダムの整数は、この配列のindex番号として使います。

2.2 一度使った数字を避ける(重複)

1~9の数字を配列arr()に配置しておき、一度使った数字が出ないようにします。
配列を減らしながら処理するため、ランダムで生成されるindex番号の最大値も減らす必要があります。

次の手順で配列を減らします。
また、UBound(),LBound()関数でランダムindex番号の範囲を指定します。

①使用した配列indexに最後尾の整数を入れる
②最後尾の配列を削除

3.列・行・3×3ブロックで重複した数字をチェックする

ナンプレのルールに沿った処理です。
マスの縦・横・3×3ブロック内に同じ数字が存在してはいけません。

現在位置(i, j)と入力候補数字rnd_numから、重複チェックの結果をTrue/Falseで返すFunction関数を作っておきます。
Falseが返ってくる場合は、数字を再度生成する必要があります。
Gotoしましょう。

列のチェックと行のチェックはほぼ同じになりますね。

現在位置を正しく捉えないと、異なる範囲をチェックしてしまいます。
位置(i, j)を3で割った商をブロック位置として見ていきます。

例えばi=7,j=4の時、変数の中身はこんな風になっています。
arr(0),arr(1)の値が次の候補値ですが、ランダムIndexが0で生成された時は
行のチェックで1が重複してFalseが発生するはずです。

3.1 「絶対に入らない数字」の場合

ここまでの処理では、入力可能な数字選べたら次に進むようになっていますが、
後半の処理(右下側)になるほどチェックが厳しくなります。
残りの数字が全て当てはまらない場合は、ループを繰り返すことになります。

数字は9種類しかないため、10回目の処理に入ったら今いる列の入力をリトライさせます。

全容

説明する項目ごとにコードを記載しましたが、全容はこんな感じです。
あとは17個以上残して、空欄にすれば問題の出来上がりです。
消すところはまた作ります。

次の展望は
・問題を完成させる
・問題を解く
・Pythonで同じ処理を作る
 →比較

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

CAPTCHA