第10講 数独の問題を解くプログラムVer0
第5話 「If mah(i1, i2) = 0 Then ・・・ End Ifでは何がなされているの?」その2

0 1 2 3 4 5 6 7 8
0 *0 *1 *2 *3 *4 *4 *5 *8 *8
1 4 9 11 12 13 14 15 6 17
2 8 19 1 21 2 23 4 25 26
3 6 28 29 30 4 32 33 34 35
4 36 37 2 1 40 5 8 43 44
5 45 46 47 48 8 50 51 52 9
6 54 55 8 57 5 59 3 61 7
7 63 7 65 66 67 68 69 4 6
8 72 4 9 2 76 77 78 79 80

まとめると、

61

に対応するdhs(6,7,i3)の値は

i3
dhs(6,7,i3)

数字0は×、1は○を表しているので、0を×に、1を○に置き換え、
実際に入れる値は配列の添え字と一つずれるのでi3i3+1に変更すると、

i3+1
dhs(6,7,i3) × × ×

これはmah(67)に対応する

61

の入っている列または行またはブロックには、3,4,5,6,7,8がすでに入っていることを意味します。つまり、mah(67)に対応するセルには

i3+1
*候補リスト × × × × × ×

○の数字しか入れられないことになります。

以上からdhs(i1, i2, i3)の役割は、mah(i1, i2)に対応するセルに入れることができる数字の候補リストを見いだすことにあるのです。
○と×を反対にすればそれがわかるのです。

以上の説明と対応させて、
        If mah(i1, i2) = 0 Then
          For i3 = 0 To 8
            dhs(i1, i2, i3) = 0
          Next

          For i3 = 0 To 8
            If i2 <> i3 And mah(i1, i3) > 0 Then dhs(i1, i2, mah(i1, i3) - 1) = 1
          Next
          
For i3 = 0 To 8
            If i1 <> i3 And mah(i3, i2) > 0 Then dhs(i1, i2, mah(i3, i2) - 1) = 1
          Next

          i1s = Int(i1 / 3)
          i2s = Int(i2 / 3)
          For i3 = 0 To 2
            For i4 = 0 To 2
              If 3 * i1s + i3 <> i1 And 3 * i2s + i4 <> i2  *(実際にはここで改行はなし)
              And mah(3 * i1s + i3, 3 * i2s + i4) > 0 Then dhs(i1, i2, mah(3 * i1s + i3, 3 * i2s + i4) - 1) = 1
            Next
          Next

          
For i3 = 0 To 8
            If dhs(i1, i2, i3) = 0 Then
              w = cnn(i1, i2)
              dhs1(i1, i2, w) = i3 + 1
              cnn(i1, i2) = cnn(i1, i2) + 1
            End If
          Next

        End If
の濃い緑以外の部分を読んでください。
          For i3 = 0 To 8
            dhs(i1, i2, i3) = 0
          Next

では、初期化をしています。つまり、すべてのdhs(i1,i2,i3)の値を0にしています。
)を例に取るとこの処理によって

i3
dhs(3,5,i3)

となります。

次の
          For i3 = 0 To 8
            If i2 <> i3 And mah(i1, i3) > 0 Then dhs(i1, i2, mah(i1, i3) - 1) = 1
          Next

ではどんな処理をしているかを、同じく()を例に取って考えてみましょう。

** ** ** ** ** *4 *5 *8 **
4 9 ** ** ** ** ** 6 **
8 ** 1 ** 2 ** 4 ** **
6 ** ** ** 4 ** ** ** **
** ** 2 1 ** 5 8 ** **
** ** ** ** 8 ** ** ** 9
** ** 8 ** 5 ** 3 ** 7
** 7 ** ** ** ** ** 4 6
** 4 9 2 ** ** ** ** **

*6 ** ** ** *4 ** ** ** **

の6,4の部分を動いていきます。

**

が除かれる理由は、If i2 <> i3 And mah(i1, i3) > 0 Then dhs(i1, i2, mah(i1, i3) - 1) = 1
にあります。また、

**

が除かれる理由は、If i2 <> i3 And mah(i1, i3) > 0 Then dhs(i1, i2, mah(i1, i3) - 1) = 1
ピンクにあります。

現在を例にしているので
i1=3
i2=5となっていることを考慮に入れて、i2 <> i3 And mah(i1, i3) > 0
の条件を満たしながらi3を0から8までトレースしてみましょう。
i3=0のとき、i2 <> i35<>0ですからこの条件を明らかにクリアしています。
また、mah(i1, i3)=mah(3, 0)=6で条件mah(i1, i3) > 0もクリアして、If文が実行され、
dhs(i1, i2, mah(i1, i3) - 1) = dhs(3, 5, mah(3, 0) - 1) = dhs(3, 5, 6 - 1) = dhs(3, 5, 5) = 1
となります。
次の i3=1のとき、i2 <> i35<>1ですからこの条件をクリアしていますが、
mah(i1, i3)=mah(3, 1)=0(空欄は0となるようにdainyuuのところで処理されていました。)
で条件mah(i1, i3) > 0をクリアできずIf文は実行されません。
i3=2,3でも条件mah(i1, i3) > 0をクリアできずIf文は実行されません。
i3=4では両方の条件i2 <> i3mah(i1, i3) > 0をクリアして、
dhs(i1, i2, mah(i1, i3) - 1) = dhs(3, 5, mah(3, 4) - 1) = dhs(3, 5, 4 - 1) = dhs(3, 5, 3) = 1
i3=5では、i2 <> i35<>5でこの条件をクリアせず、If文は実行されません。
i3=6,7,8でも条件mah(i1, i3) > 0をクリアできずIf文は実行されません。

結局dhs(3, 5, 5) dhs(3, 5, 3)だけが0から1に書き換わり

i3
dhs(3,5,i3)

となります。0は×を、1は○を、実際の数字はi3と1つずれてi3+1でしたから、これは

i3+1
dhs(3,5,i3) × × × × × × ×

を意味します。もっとも、dhs(3,5,i3)は後の
          For i3 = 0 To 8
            If i1 <> i3 And mah(i3, i2) > 0 Then dhs(i1, i2, mah(i3, i2) - 1) = 1
          Next

          i1s = Int(i1 / 3)
          i2s = Int(i2 / 3)
          For i3 = 0 To 2
            For i4 = 0 To 2
              If 3 * i1s + i3 <> i1 And 3 * i2s + i4 <> i2  *(実際にはここで改行はなし)
              And mah(3 * i1s + i3, 3 * i2s + i4) > 0 Then dhs(i1, i2, mah(3 * i1s + i3, 3 * i2s + i4) - 1) = 1
            Next
          Next

によって、さらに書き換えられ最終的に

i3
dhs(3,5,i3)

すなわち

i3+1
dhs(3,5,i3) × × × ×
i3+1
*候補リスト × × × × ×

となりますが。


第4話へ 第6話へ
VB入門講義応用編トップへ

VB入門講義トップへ