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

          For i3 = 0 To 8
            If i1 <> i3 And mah(i3, i2) > 0 Then dhs(i1, i2, mah(i3, i2) - 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 ** ** ** ** **

*4
**
**
**
5
**
**
**
**

4と5のところを動いていきます。

**

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

**

が除かれるはIf i1 <> i3 And mah(i3, i2) > 0 Then dhs(i1, i2, mah(i3, i2) - 1) = 1
によります。
          For i3 = 0 To 8
            If i2 <> i3 And mah(i1, i3) > 0 Then dhs(i1, i2, mah(i1, i3) - 1) = 1
          Next

のときにすでに

i3
dhs(3,5,i3)

になっているので今回の動きでdhs(3,5,4)=1が加わり、

i3
dhs(3,5,i3)

となります。
そして、次に一番難解な
          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

の部分に到達しました。同じ例()で考えてみましょう。

** ** ** ** ** *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 ** ** ** ** **

今回は

1 **
** 8

の1,8の部分を動いていきます。
非常に理解困難な場所だと思いますので、一つ一つトレースしていきます。

現在i1=3i2=5なので、i1s = Int(i1 / 3)はInt(3/3)=Int(1)=1になり、
i2s = Int(i2 / 3)もInt(5/3)=Int(1)=1です。
          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 = 0i4 = 0ですから
3 * i1s + i3 = 3*1+0 =3
3 * i2s + i4 = 3*1+0 = 3
3 * i1s + i3 <> i1 And 3 * i2s + i4 <> i2の条件ののところをクリアできません。
現在i1=3であったからです。
よって、For文によりi3 = 0i4 = 1となります。すると、
3 * i1s + i3 = 3*1+0 =3
3 * i2s + i4 = 3*1+1 =4
となりますが、これも3 * i1s + i3 <> i1 And 3 * i2s + i4 <> i2に抵触します。
同様にi3 = 0i4 = 2も条件に反し、i4の1回目のループが終わます。
要するにi3 = 0のときは

** ** ** ** ** *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 ** ** ** **

の行に対応しますが、ここでは処理は行われないようしているのです。なぜなら、この行についてはすでに
          For i3 = 0 To 8
            If i2 <> i3 And mah(i1, i3) > 0 Then dhs(i1, i2, mah(i1, i3) - 1) = 1
          Next

ですでに処理されているからです。
2重チェックしても問題はありませんが、スピード優先のため2重チェックしないようにしているのです。

そして、i3の2回目のループが始まりi3 = 1i4 = 0となり、
3 * i1s + i3 = 3*1+1 =4
3 * i2s + i4 = 3*1+0 =3
となりはじめて条件3 * i1s + i3 <> i1 And 3 * i2s + i4 <> i2をクリアします。
そして、mah(3 * i1s + i3, 3 * i2s + i4)=mah(4, 3)=1より条件
mah(3 * i1s + i3, 3 * i2s + i4) > 0もクリアして、If分がはじめて実行されます。
そして、dhs(i1, i2, mah(3 * i1s + i3, 3 * i2s + i4) - 1) = dhs(3, 5,1 - 1) = dhs(i1, i2, mah(4, 3) - 1) = = dhs(3, 5,0) = 1
となるのです。つまり、

**

の入っているブロック

** 4 **
1 ** 5
** 8 **

には、

*1

の1(=0+1)が入っていることが認識されたのです。
次のi3 = 1i4 = 1だと
3 * i1s + i3 = 3*1+1 =4
3 * i2s + i4 = 3*1+1 =4

** 4 **
1 ** 5
** 8 **

1の右隣で空欄なので条件mah(3 * i1s + i3, 3 * i2s + i4) > 0
をクリアできず、If文は実行されません。

i3 = 1i4 = 2だと
3 * i1s + i3 = 3*1+1 =4
3 * i2s + i4 = 3*1+2 =5
条件で3 * i2s + i4 <> i2(i2はでした。)をクリせず、If文は実行されません。

i4の2回目のループが終わり、
i3 = 2i4 = 0
これは1の下(すなわち8の左隣)で空欄ですからmah(3 * i1s + i3, 3 * i2s + i4) > 0
をクリアできず
i3 = 2i4 = 1となり
3 * i1s + i3 = 3*1+2 =5
3 * i2s + i4 = 3*1+1 =4より

*8

の欄に対応してmah(3 * i1s + i3, 3 * i2s + i4)=mah(5, 4)=8
となりIf文が実行されdhs(i1, i2, mah(3 * i1s + i3, 3 * i2s + i4) - 1) = dhs(5, 4,8 - 1) = dhs(i1, i2, mah(5, 4) - 1) == dhs(3, 5,8) = 1
となり

**

の入っているブロック

** 4 **
1 ** 5
** 8 **

には、

*8

の8(=8+1)が入っていることが認識されます。

最後のi3 = 2i4 = 2は8の右隣で、3 * i2s + i4 <> i2
をクリアせず実行されません。
i4 = 2

*4
**
**
**
5
**
**
**
**

に対応するわけですが、ここの部分についても条件3 * i2s + i4 <> i2によって処理を行わないようにしています。
          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

では

1 **
** 8

の1と8のところだけを動いていくことがおわかり頂けたでしょうか。


第5話へ 第7話へ
VB入門講義応用編トップへ

VB入門講義トップへ