第6講 数独を作ろう!
第5話 数独プログラムソース解説
では核心部分を再掲しましょう。
ia = i Mod n
ja = j Mod n
If ia > 0 Then
For l = 0 To ia - 1
For m = 0 To n - 1
If (j - ja + m) <> j And (i - ia + l) <>
i Then
If mah(i, j) = mah(i - ia + l, j - ja + m) Then
GoTo owari
End If
Next
Next
End If
n=3の場合を例に説明しましょう。
ia=i mod nはiを3で割った余りです。
ja=j mod nも同様にjを3で割った余りです。
条件(j - ja + m) <> j And (i - ia + l) <> iは何を意味するでしょうか。
それはmah(i, j) と mah(i - ia + l, j - ja + m)の比較は
それぞれが同じ行でも同じ列でもないときにのみ行いなさいという意味です。
なぜなら同じ行や列のときには同じ数字が入らないことは、
If j > 0 Then
For l = 0 To j - 1
If mah(i, l) = mah(i, j) Then GoTo owari
Next
End If
If i > 0 Then
For l = 0 To i - 1
If mah(l, j) = mah(i, j) Then GoTo owari
Next
End If
によって保証されているからです。
したがって、比較は行も列も異なっているときのみ行われます。
そして、比較してイコールならGoTo owariによって
If g + 1 < n * n * n * n Then
sakusei (g + 1)
Else
cn = cn + 1
hyouji
End If
の部分は実行されずNextによって、mah(i, j)には1つ大きくなった数字が入ります。
つまり、異なる行でかつ異なる列と比較して数字が異なるときにみ条件をクリアして
If g + 1 < n * n * n * n Then
sakusei (g + 1)
Else
cn = cn + 1
hyouji
End If
が実行され、gの次の世界に進みます。
具体例がないとわかりにくいと思いますので、
1 | 2 | 3 | * | 4 | 5 | 6 | * | 7 | 8 | 9 |
2 | ・ | ・ | * | ・ | ・ | ・ | * | ・ | ・ | ・ |
具体例を出して再度説明しましょう。
現在青の世界にいるとします。
するとi=1,j=0ですからiaはiを3で割った余りなので
ia=1で
If ia > 0 Then
For l = 0 To ia - 1
For m = 0 To n - 1
If (j - ja + m) <> j And (i - ia + l) <>
i Then
If mah(i, j) = mah(i - ia + l, j - ja + m) Then GoTo owari
End If
Next
Next
End If
が実行されます。
l=0,m=0のとき、
mah(i - ia + l, j - ja + m)はi=1,ia=1,j=0,ja=0なので、
mah(0, 0)です。mah(i, j)はmah(1, 0)なので同じ列であってはいけないという条件
(j - ja + m) <> j And (i - ia + l) <> i
を満たしませんから
If (j - ja + m) <> j And (i - ia + l) <>
i Then
If mah(i, j) = mah(i - ia + l, j - ja + m) Then GoTo owari
End If
は実行されずNextによってm=1となります。このとき、
mah(i - ia + l, j - ja + m)はmah(0, 1)です。mが1つ増えたのだから当然ですよね。
これは、mah(1, 0)と行も列も違いますから
If mah(i, j) = mah(i - ia + l, j - ja + m) Then GoTo owariが実行されます。
1 | 2 | 3 | * | 4 | 5 | 6 | * | 7 | 8 | 9 |
2 | ・ | ・ | * | ・ | ・ | ・ | * | ・ | ・ | ・ |
ところがmah(1, 0)=mah(0, 1)で GoTo owariが実行されNextによって、
mah(1, 0)は次の値3が入り
1 | 2 | 3 | * | 4 | 5 | 6 | * | 7 | 8 | 9 |
3 | ・ | ・ | * | ・ | ・ | ・ | * | ・ | ・ | ・ |
となります。そして、再び
For l = 0 To ia - 1
For m = 0 To n - 1
If (j - ja + m) <> j And (i - ia + l) <>
i Then
If mah(i, j) = mah(i - ia + l, j - ja + m) Then GoTo owari
End If
Next
Next
が実行され前回と同様にmah(1, 0)とmah(0, 1)の比較が行われます。
今回はmah(1, 0)=3,mah(0, 1)=2でIf mah(i, j) = mah(i - ia + l, j - ja + m) Then GoTo owari
はクリアしてm=2となります。
1 | 2 | 3 | * | 4 | 5 | 6 | * | 7 | 8 | 9 |
3 | ・ | ・ | * | ・ | ・ | ・ | * | ・ | ・ | ・ |
そしてmah(1, 0)とmah(0, 2)が比較されますが、残念ながら両方とも値は3ですから
GoTo owariが実行されNextによって、mah(1, 0)=4
1 | 2 | 3 | * | 4 | 5 | 6 | * | 7 | 8 | 9 |
4 | ・ | ・ | * | ・ | ・ | ・ | * | ・ | ・ | ・ |
そして今回も
For l = 0 To ia - 1
For m = 0 To n - 1
If (j - ja + m) <> j And (i - ia + l) <>
i Then
If mah(i, j) = mah(i - ia + l, j - ja + m) Then GoTo owari
End If
Next
Next
によって青mah(1, 0)とピンクmah(0, 1),mah(0, 2)
との比較が行われますが今回はいずれもクリアして
If g + 1 < n * n * n * n Then
sakusei (g + 1)
Else
cn = cn + 1
hyouji
End If
が実行され
1 | 2 | 3 | * | 4 | 5 | 6 | * | 7 | 8 | 9 |
4 | 1 | ・ | * | ・ | ・ | ・ | * | ・ | ・ | ・ |
となります。そして、
1 | 2 | 3 | * | 4 | 5 | 6 | * | 7 | 8 | 9 |
4 | 1 | ・ | * | ・ | ・ | ・ | * | ・ | ・ | ・ |
と比較され
1 | 2 | 3 | * | 4 | 5 | 6 | * | 7 | 8 | 9 |
4 | 3 | ・ | * | ・ | ・ | ・ | * | ・ | ・ | ・ |
となりますが
1 | 2 | 3 | * | 4 | 5 | 6 | * | 7 | 8 | 9 |
4 | 3 | ・ | * | ・ | ・ | ・ | * | ・ | ・ | ・ |
によって
1 | 2 | 3 | * | 4 | 5 | 6 | * | 7 | 8 | 9 |
4 | 5 | ・ | * | ・ | ・ | ・ | * | ・ | ・ | ・ |
となり条件をクリアし
1 | 2 | 3 | * | 4 | 5 | 6 | * | 7 | 8 | 9 |
4 | 5 | 1 | * | ・ | ・ | ・ | * | ・ | ・ | ・ |
同様に繰り返して
1 | 2 | 3 | * | 4 | 5 | 6 | * | 7 | 8 | 9 |
4 | 5 | 6 | * | ・ | ・ | ・ | * | ・ | ・ | ・ |
なったとき初めて条件をクリアして
1 | 2 | 3 | * | 4 | 5 | 6 | * | 7 | 8 | 9 |
4 | 5 | 6 | * | 1 | ・ | ・ | * | ・ | ・ | ・ |
となります。
とにかく薄水色の部分に同じ数字が入っていないことを確認してください。
1 | 2 | 3 | * | 4 | 5 | 6 | * | 7 | 8 | 9 |
4 | 5 | 6 | * | 7 | 8 | 9 | * | 1 | 2 | 3 |
7 | 8 | 9 | * | 1 | 2 | 3 | * | 4 | 5 | 6 |
のときmah(i - ia + l, j - ja + m)は薄ピンクの範囲を動き
青はどの数字とも一致しない6が選ばれています。
もちろん
If j > 0 Then
For l = 0 To j - 1
If mah(i, l) = mah(i, j) Then GoTo owari
Next
End If
If i > 0 Then
For l = 0 To i - 1
If mah(l, j) = mah(i, j) Then GoTo owari
Next
End If
がありますから黄色の数字とも異なるものになります。
結局以上の動きで一ブロック(小さな正方形)の中には同じ数字が並ばなくなり、
数独ができあがる訳です。
どうかご自分でi,j,l,mを動かしトレースして、
同じブロックには同じ数字が並ばないようになっていることをご確認頂ければと思います。
ではみなさん数独最後の課題です。
数独解答例を改良して
1 | 2 | 3 | * | 4 | 5 | 6 | * | 7 | 8 | 9 |
4 | 5 | 6 | * | 7 | 8 | 9 | * | 1 | 2 | 3 |
7 | 8 | 9 | * | 1 | 2 | 3 | * | 4 | 5 | 6 |
* | * | * | * | * | * | * | * | * | * | * |
2 | 1 | 4 | * | 3 | 6 | 5 | * | 8 | 9 | 7 |
3 | 6 | 5 | * | 8 | 9 | 7 | * | 2 | 1 | 4 |
8 | 9 | 7 | * | 2 | 1 | 4 | * | 3 | 6 | 5 |
* | * | * | * | * | * | * | * | * | * | * |
5 | 3 | 1 | * | 6 | 4 | 2 | * | 9 | 7 | 8 |
6 | 4 | 2 | * | 9 | 7 | 8 | * | 5 | 3 | 1 |
9 | 7 | 8 | * | 5 | 3 | 1 | * | 6 | 4 | 2 |
のように小ブロックがわかるように間に*を入れるプログラムを考えましょう。
いじるのはhyouji()の部分だけです。皆さんがんばりましょう。
第4話へ 第6話へ
VB入門講義応用編トップへ
VB入門講義トップへ