第15講 3次魔方陣と4次魔方陣の作成
第6話 3次魔方陣と4次魔方陣の自動生成コード解説その3
解説
Private Sub CommandButton1_Click()
n = Cells(3, 8)
cn = 0
zhy
ms (0)
Cells(4, 12) = cn
End Sub
座標が完成した後、ms (0)によっていよいよ魔方陣の作成です。
Sub ms(g As Byte)
Dim i As Byte, j As Byte, k As Byte, a As Byte, b As Byte, w As Byte
a = x(g)
b = y(g)
For i = 0 To n * n - 1
mah(b, a) = i + 1
If g > 0 Then
For j = 0 To g - 1
If mah(b, a) = mah(y(j), x(j)) Then GoTo tobi
Next
End If
If a = n - 1 Then
w = 0
For j = 0 To n - 1
w = w + mah(b, j)
Next
If w <> Int(n * (n * n + 1) / 2) Then GoTo tobi
End If
If b = n - 1 Then
w = 0
For j = 0 To n - 1
w = w + mah(j, a)
Next
If w <> Int(n * (n * n + 1) / 2) Then GoTo tobi
End If
If (a = n - 1) And (b = n - 1) Then
w = 0
For j = 0 To n - 1
w = w + mah(j, j)
Next
If w <> Int(n * (n * n + 1) / 2) Then GoTo tobi
End If
If (a = 0) And (b = n - 1) Then
w = 0
For j = 0 To n - 1
w = w + mah(j, n - 1 - j)
Next
If w <> Int(n * (n * n + 1) / 2) Then GoTo tobi
End If
If g + 1 < n * n Then
ms (g + 1)
Else
For j = 0 To n - 1
For k = 0 To n - 1
Cells(6 + j + Int(cn / 10) * (n + 1), 1 + k + (cn Mod 10) * (n
+ 1)) = mah(j, k)
Next
Next
cn = cn + 1
End If
tobi:
Next
End Sub
個々で順列作成のときに注意したことを再度繰り返しておきます。
Sub ms(g As Byte)
Dim i As Byte, j As Byte, k As Byte, a As Byte, b As Byte, w As Byte
a = x(g)
b = y(g)
For i = 0 To n * n - 1
それはgとiの役割の違いです。gはセル番号であり、iはそのセルの内容です。
おなじみの比喩で言いますと、gはビール瓶のラベルであり、iはビール瓶に入っているビールです。
アドレスに比喩で言えば、gは住所であり、iはその住所に建っている建物です。
gとiの概念を明確に区別しないとプログラムは訳のわからないものになります。
私が、観察するところによると、数学の苦手な生徒は概念の区別、役割の違いが把握できない生徒です。
数学の苦手な生徒は、平気で次のようなことを書いてしまいます。
sinθ=60°
θは角の大きさであり、sinθは比の値を表すことが明確に区別できないのです。
角の大きさ(角度)と比の値は、関係を持っていますがまったく別の概念です。
汚い比喩で申し訳ないのですが、
これは口から入ってくる食べ物と肛門から出ていくウンコを区別していないのと同じです。
sinθというブラックボックスに角度を入れると、出口からは比の値が出てきます。
sinθ=60°のように出口から角度が出てくることはありません。
角度はブラックボックスsinθによって、比の値に加工され出口から出てくるのです。
口から入った食物が人の中で加工され、肛門からウンコとなって出てくるのに対応します。
ですから、sinθ=60°は食物とウンコの混同です。
数学についてもプログラムについても得意になりたければ、概念や役割を明確に区別しなければなりません。
gはビール瓶のラベルであり、iはビール瓶に入っているビールであることを踏まえてトレースをしていきます。
とても長いトレースになりますが、粘り強くお付き合いお願いします。
ms (0)に飛ぶ先はどこでしょうか。
a = x(g)
b = y(g)
For i = 0 To n * n - 1
mah(b, a) = i + 1
g=0のときは、前話でトレースしたようにx(0)=0、y(0)=0ですから、飛ぶ先は
0 | 1 | 2 | |
0 | 0 | 1 | 2 |
1 | 3 | 4 | 5 |
2 | 6 | 7 | 8 |
の
です。
i=0ですから、
mah(b, a) = i + 1
によって、
0 | 1 | 2 | |
0 | 0 | 1 | 2 |
1 | |||
1 | 3 | 4 | 5 |
2 | 6 | 7 | 8 |
となります。現在g=0ですから
If g > 0 Then
For j = 0 To g - 1
If mah(b, a) = mah(y(j), x(j)) Then GoTo tobi
Next
End If
If a = n - 1 Then
w = 0
For j = 0 To n - 1
w = w + mah(b, j)
Next
If w <> Int(n * (n * n + 1) / 2) Then GoTo tobi
End If
If b = n - 1 Then
w = 0
For j = 0 To n - 1
w = w + mah(j, a)
Next
If w <> Int(n * (n * n + 1) / 2) Then GoTo tobi
End If
If (a = n - 1) And (b = n - 1) Then
w = 0
For j = 0 To n - 1
w = w + mah(j, j)
Next
If w <> Int(n * (n * n + 1) / 2) Then GoTo tobi
End If
If (a = 0) And (b = n - 1) Then
w = 0
For j = 0 To n - 1
w = w + mah(j, n - 1 - j)
Next
If w <> Int(n * (n * n + 1) / 2) Then GoTo tobi
End If
はすべて該当せず、
If g + 1 < n * n Then
ms (g + 1)
Else
For j = 0 To n - 1
For k = 0 To n - 1
Cells(6 + j + Int(cn / 10) * (n + 1), 1 + k + (cn Mod 10) * (n
+ 1)) = mah(j, k)
Next
Next
cn = cn + 1
End If
のIf文が実行されます。g+1なので
x(1)=1、y(1)=0となりますので、今度飛ぶ次元世界は、
0 | 1 | 2 | |
0 | 0 | 1 | 2 |
1 | |||
1 | 3 | 4 | 5 |
2 | 6 | 7 | 8 |
です。
For i = 0 To n * n - 1
mah(b, a) = i + 1
によって、
0 | 1 | 2 | |
0 | 0 | 1 | 2 |
1 | 1 | ||
1 | 3 | 4 | 5 |
2 | 6 | 7 | 8 |
となります。
g=1ですから、今回は
If g > 0 Then
For j = 0 To g - 1
If mah(b, a) = mah(y(j), x(j)) Then GoTo tobi
Next
End If
のストレステストを受けます。
残念ながら、今回は
If mah(b, a) = mah(y(j), x(j)) Then GoTo tobiに抵触して、
tobi:
Next
すぐにNextによりi=1となり、
0 | 1 | 2 | |
0 | 0 | 1 | 2 |
1 | 2 | ||
1 | 3 | 4 | 5 |
2 | 6 | 7 | 8 |
今度は検査
If g > 0 Then
For j = 0 To g - 1
If mah(b, a) = mah(y(j), x(j)) Then GoTo tobi
Next
End If
をクリアします。2は1とのみ比べられるからです。
If a = n - 1 Then
w = 0
For j = 0 To n - 1
w = w + mah(b, j)
Next
If w <> Int(n * (n * n + 1) / 2) Then GoTo tobi
End If
If b = n - 1 Then
w = 0
For j = 0 To n - 1
w = w + mah(j, a)
Next
If w <> Int(n * (n * n + 1) / 2) Then GoTo tobi
End If
If (a = n - 1) And (b = n - 1) Then
w = 0
For j = 0 To n - 1
w = w + mah(j, j)
Next
If w <> Int(n * (n * n + 1) / 2) Then GoTo tobi
End If
If (a = 0) And (b = n - 1) Then
w = 0
For j = 0 To n - 1
w = w + mah(j, n - 1 - j)
Next
If w <> Int(n * (n * n + 1) / 2) Then GoTo tobi
End If
は該当せず、
If g + 1 < n * n Then
ms (g + 1)
Else
For j = 0 To n - 1
For k = 0 To n - 1
Cells(6 + j + Int(cn / 10) * (n + 1), 1 + k + (cn Mod 10) * (n
+ 1)) = mah(j, k)
Next
Next
cn = cn + 1
End If
のIf文によって、次の次元世界に跳躍します。
g=2とき、x(2)=2、y(2)=0となりますので、
0 | 1 | 2 | |
0 | 0 | 1 | 2 |
1 | 2 | ||
1 | 3 | 4 | 5 |
2 | 6 | 7 | 8 |
が今度の次元世界です。
For文によって、
0 | 1 | 2 | |
0 | 0 | 1 | 2 |
1 | 2 | 1 | |
1 | 3 | 4 | 5 |
2 | 6 | 7 | 8 |
となりますが、
試験
If g > 0 Then
For j = 0 To g - 1
If mah(b, a) = mah(y(j), x(j)) Then GoTo tobi
Next
End If
の一巡目でチェックされえてしまいます。
セル番号2とセル番号0が同じ1になっているからです。
したがって、tobi:に飛び、iはインクリメントされ
0 | 1 | 2 | |
0 | 0 | 1 | 2 |
1 | 2 | 2 | |
1 | 3 | 4 | 5 |
2 | 6 | 7 | 8 |
となりますが、今回はストレステストの2巡目において禁則に抵触します。
セル番号2とセル番号1が同じ2であるからです。
再びtobiに飛びiは2となり、mah(b, a) = i + 1から、
0 | 1 | 2 | |
0 | 0 | 1 | 2 |
1 | 2 | 3 | |
1 | 3 | 4 | 5 |
2 | 6 | 7 | 8 |
今回は、数字の重複検査
If g > 0 Then
For j = 0 To g - 1
If mah(b, a) = mah(y(j), x(j)) Then GoTo tobi
Next
End If
を一巡目も2巡目をクリアします。
しかし、3−1=2で合計チェック検査
If a = n - 1 Then
w = 0
For j = 0 To n - 1
w = w + mah(b, j)
Next
If w <> Int(n * (n * n + 1) / 2) Then GoTo tobi
End If
の対象になりますが、クリアできません。現時点の合計は残念ながら1+2+3=6で、3次魔方陣の行の合計3×(3×3+1)÷2=15に等しくないからです。
tobiに飛び、iは3となり、
0 | 1 | 2 | |
0 | 0 | 1 | 2 |
1 | 2 | 4 | |
1 | 3 | 4 | 5 |
2 | 6 | 7 | 8 |
今回も合計検査にチェックされてtobiへ行きます。
以下同様に繰り返して、
0 | 1 | 2 | |
0 | 0 | 1 | 2 |
1 | 2 | 9 | |
1 | 3 | 4 | 5 |
2 | 6 | 7 | 8 |
となっても合計は、12ににすぎず次元世界2は終焉を迎えます。
0 | 1 | 2 | |
0 | 0 | 1 | 2 |
1 | 3 | ||
1 | 3 | 4 | 5 |
2 | 6 | 7 | 8 |
以下
0 | 1 | 2 | |
0 | 0 | 1 | 2 |
1 | 3 | 1 | |
1 | 3 | 4 | 5 |
2 | 6 | 7 | 8 |
0 | 1 | 2 | |
0 | 0 | 1 | 2 |
1 | 3 | 2 | |
1 | 3 | 4 | 5 |
2 | 6 | 7 | 8 |
0 | 1 | 2 | |
0 | 0 | 1 | 2 |
1 | 3 | 3 | |
1 | 3 | 4 | 5 |
2 | 6 | 7 | 8 |
0 | 1 | 2 | |
0 | 0 | 1 | 2 |
1 | 3 | 4 | |
1 | 3 | 4 | 5 |
2 | 6 | 7 | 8 |
・・・・
0 | 1 | 2 | |
0 | 0 | 1 | 2 |
1 | 3 | 9 | |
1 | 3 | 4 | 5 |
2 | 6 | 7 | 8 |
まで来ても、合計は13にすぎず、再び次元世界2は消滅します。
結局
0 | 1 | 2 | |
0 | 0 | 1 | 2 |
1 | 5 | 9 | |
1 | 3 | 4 | 5 |
2 | 6 | 7 | 8 |
まで来て初めて横合計テスト
If a = n - 1 Then
w = 0
For j = 0 To n - 1
w = w + mah(b, j)
Next
If w <> Int(n * (n * n + 1) / 2) Then GoTo tobi
End If
を初めてクリアします。合計が15になったからです。
本日のトレースはここまでとします。以降は次話で。
第5話へ 第7話へ
VBA講義第1部へ
vc++講義へ
vb講義へ
VB講義基礎へ
初心者のための世界で一番わかりやすいVisual C++入門基礎講座へ
初心者のための世界で一番わかりやすいVisual Basic入門基礎講座へ
数学研究室に戻る