office  数独の問題作成
 


  
要VBA/サンプル有
TOPExcel/Word/PowerPoint
○考え方
office 数独ゲームのルールは、碁盤目状の9x9=81マスの中に1〜9のランダムな数字が虫食い状に入れてあり、その虫食い空白のマスに、あるルールに基づいて数字を入れていくゲームです。

数独問題を創る場合、最初に答えを全マスにあてはめ、そこから虫食いに消してゆくことになります(虫食いのやり方にもコツがあるようですがココでは触れません)

数独ゲームのルールは次の二つの条件を満足することです。

(イ)任意のマスに入れる数字は、そのマスの縦の列9マスと横の列9マスのどちらにも重複する数字がないこと。
(ロ)任意のマスに入れる数字は、そのマスが属する3x3のマスの中にも重複する数字がないこと。

 これをEXCELで実現する方法はいくつかあると思いますが、ここではVBAのRnd関数をひたすらループしながら乱数をセルに入れていく方法と、上の(イ)(ロ)の条件の満足をCOUNTIFワークシート関数で検査していく方法の組み合わせて処理する方法を紹介します。

○ポイントはVBAのRnd関数とCOUNTIFワークシート関数
(1) 任意のシートに数独マスを描く
  (この例では B2:J10 の範囲とします)

(2) 縦横の重複検査関数(下記)を任意のセルに記入する
  =COUNTIF(B$2:B$10,B2)*COUNTIF($B2:$J2,B2)
  (この例では B13 に記入します)

(3) (2)の式を入力位置から下へ9マスコピーする

(4) (3)の後、9マス選択状態のまま、右へ9マスコピーする(図1)
  (この時点で縦横重複検査結果群が81個できます)
office
(図1)縦横の重複検査関数コピー

(5) 9マスの重複検査関数(下記)を任意のセルに記入する
  =COUNTIF($B$2:$D$4,B2)
  (この例では M2 に記入します)
  =COUNTIF($B$5:$D$7,B5)
  (この例では M5 に記入します)
  =COUNTIF($B$8:$D$10,B8)
  (この例では M8 に記入します)
  =COUNTIF($E$2:$G$4,E2)
  (この例では P2 に記入します)
  =COUNTIF($E$5:$G$7,E5)
  (この例では P5 に記入します)
  =COUNTIF($E$8:$G$10,E8)
  (この例では P8 に記入します)
  =COUNTIF($H$2:$J$4,H2)
  (この例では S2 に記入します)
  =COUNTIF($H$5:$J$7,H5)
  (この例では S5 に記入します)
  =COUNTIF($H$8:$J$10,H8)
  (この例では S8 に記入します)

(6) (5)の式をそれぞれ入力位置から下へ3マスコピーする

(7) (6)の後、3マス選択状態のまま、それぞれ右へ3マスコピーする(図2)
  (この時点で各々の9マス内複検査結果群が9個×9個できます)
office
(図2)9マスの重複検査関数コピー

(8) 成功判定の関数(下記)を任意のセルに記入する
  =PRODUCT(B13:J21,M2:U10)
  (この例では M13 に記入します)

(9) VBEを開いて数独作成コードを記入。コード例は下記


○基本構成
 まずVBA側で乱数を発生させ、さしあたりセルに入力します。ワークシートには、入力値が上のイ)ロ)のそれぞれが満たされているかを COUNTIF関数でチェックし、入力値が縦横重複検査と9マス重複検査のいずれもパスした場合は、各々のセルに共に"1"が返されるので、その積が"1"にったかどうかを、再度VBAで判断し、1以外の場合は、再度乱数発生を繰り返します。

 乱数から発生させる9個の数値は重複してはいけないので、たとえば9個目の抽選は、残りの1個を抽選する確率が1/9になり抽選失敗の回数が増えます。そこで、一応30回をループの上限としておきます。30回もループすれば、1〜9の任意の数値が1回はでてくると思われるからです。

 縦横の重複検査にはパスしても、後の9マス重複検査で、それ以上進めない手詰まりになる場合が殆どなので、その時は全部をクリアして最初からやり直します。

○関連情報・その他の方法
EXCEL2000の場合はこちら
・実際に作動させた結果、だいたい5回に1回は成功するようです。また時間ですが、パソコンのスペックにもよりますが、コアi5 750 の2.67GHzで約3秒以内です。

○サンプル
サンプルファイルはこちら(要解凍) 18KB

○注意
必ずしも1回のトライで成功しません。5回に1回程度の割合で成功するので、成功するまで繰り返し実行してください。