第15講 3次魔方陣と4次魔方陣の作成
第4話 3次魔方陣と4次魔方陣の自動生成コード解説その1
コード再掲
Dim mah(4, 4) As Byte, x(16) As Byte, y(16) As Byte
Dim n As Byte, cn As Integer
Private Sub CommandButton1_Click()
n = Cells(3, 8)
cn = 0
zhy
ms (0)
Cells(4, 12) = cn
End Sub
Sub zhy()
Dim i As Byte
For i = 0 To n * n - 1
x(i) = i Mod n
y(i) = Int(i / n)
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
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
Private Sub CommandButton2_Click()
Rows("6:2000").Select
Selection.ClearContents
Cells(4, 12).Select
Selection.ClearContents
Cells(1, 1).Select
End Sub
では、コード解説を5話程度に渡って述べていきます。
非常に息の長い解説になりますので、粘り強くついてきていただければと思います。
基本は、第11講 Subプロシージャの再帰的使用の学習第3話 Subプロシージャ版順列作成
で行った順列作成と同じです。違いは、1次元の順列を2次元に並び直している点です。
また、順列の場合は重複がないかどうかのチェック以外ありませんでしたが、
魔方陣の場合は、
2 | 7 | 6 |
9 | 5 | 1 |
4 | 3 | 8 |
対角線や各列・各行の終わりにおいて、合計がn×(n×n+1)/2になっているかどうかをチェックします。
色違いになっているのは、ピンクは各行・各列の合計だけでなく、対角線の合計もチェックしなければならないからです。
n×(n×n+1)/2は何かというと、
方陣の中のすべての数字の和1+2+3+4+・・・+n×n=n×n×(n×n+1)/2をnで割ったものです。
nは行数や列数に中で結局は各行・各列の合計ということになります。
3次魔方陣を例にとれば、
3×3×(3×3+1)/2=45を3で割ったもので、3×(3×3+1)/2=15です。
例えば、
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
は
2 | 7 | 6 |
9 | 5 | 1 |
4 | 3 | 8 |
各行の最後の列に達したとき、行合計が15になっているかをチェックしています。
同様に、
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
は
2 | 7 | 6 |
9 | 5 | 1 |
4 | 3 | 8 |
各列の最後の行に到達したときに、列合計が15になっているかをチェックしています。
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
は
2 | 7 | 6 |
9 | 5 | 1 |
4 | 3 | 8 |
対角線の最後に到達したとき、対角線の合計が15になるかを検査しています。
最後、
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
は
2 | 7 | 6 |
9 | 5 | 1 |
4 | 3 | 8 |
逆対角線の末項に来たとき、逆対角線の最後合計が15になっているかを調べています。
第3話へ 第5話へ
VBA講義第1部へ
vc++講義へ
vb講義へ
VB講義基礎へ
初心者のための世界で一番わかりやすいVisual C++入門基礎講座へ
初心者のための世界で一番わかりやすいVisual Basic入門基礎講座へ
数学研究室に戻る