第19講 対角線法による魔方陣自動生成ソフトの高速化
第4話 番号入力
0 | 9 | 10 | 11 | 5 |
12 | 1 | 13 | 6 | 14 |
15 | 16 | 2 | 17 | 18 |
19 | 7 | 20 | 3 | 21 |
8 | 22 | 23 | 24 | 4 |
を実現するプログラム例
Dim a(10, 10) As Byte, n As Byte, cn As Long, y(100) As Byte, x(100) As Byte
Private Sub CommandButton1_Click()
CommandButton2_Click
cn = 0
n = Cells(4, 2)
Call zy
' Call f(0) 'n次魔方陣作成プロシージャ
End Sub
Sub zy()
Dim i As Byte, j As Byte, k As Byte
Dim b(10, 10) As Byte
For i = 0 To n - 1
For j = 0 To n - 1
b(i, j) = n * n + 1
Next
Next
For i = 0 To n - 1
b(i, i) = i
Next
k = n
For i = 0 To n - 1
If b(i, n - 1 - i) = n * n + 1 Then
b(i, n - 1 - i) = k
k = k + 1
End If
Next
For i = 0 To n - 1
For j = 0 To n - 1
If b(i, j) = n * n + 1 Then
b(i, j) = k
k = k + 1
End If
Next
Next
For i = 0 To n - 1
For j = 0 To n - 1
Cells(6 + i, 2 + j) = b(i, j)
Next
Next
End Sub
Sub f(g As Byte)
Dim i As Byte, j As Byte, w As Byte
For i = 1 To n * n
If g > 0 Then
For j = 0 To g - 1
If i = a(y(j), x(j)) Then GoTo tobi
Next
End If
a(y(g), x(g)) = i
' If x = n - 1 Then
' w = 0
' For j = 0 To n - 1
' w = w + a(y, j)
' Next
' If w <> Int(n * (n * n + 1) / 2) Then GoTo tobi
' End If
' If y = n - 1 Then
' w = 0
' For j = 0 To n - 1
' w = w + a(j, x)
' Next
' If w <> Int(n * (n * n + 1) / 2) Then GoTo tobi
' End If
' If x = 0 And y = n - 1 Then
' w = 0
' For j = 0 To n - 1
' w = w + a(j, n - 1 - j)
' Next
' If w <> Int(n * (n * n + 1) / 2) Then GoTo tobi
' End If
' If x = n - 1 And y = n - 1 Then
' w = 0
' For j = 0 To n - 1
' w = w + a(j, j)
' Next
' If w <> Int(n * (n * n + 1) / 2) Then GoTo tobi
' End If
If g + 1 < n * n Then
Call f(g + 1)
If cn = 1 Then Exit Sub
Else
Call h
If cn = 1 Then Exit Sub
End If
tobi:
Next
End Sub
Sub h()
Dim i As Byte, j As Byte, s As Byte, am As Byte, w As Byte
For i = 0 To n * n - 1
s = Int(i / n)
am = i Mod n
Cells(6 + s + (n + 1) * Int(cn / 5), 2 + am + (n + 1) * (cn Mod 5)) = a(s, am)
Next
cn = cn + 1
tobi:
End Sub
Private Sub CommandButton2_Click()
Rows("5:20000").Select
Selection.ClearContents
Cells(1, 1).Select
End Sub
参考ダウンロード添付ファイル
For i = 0 To n - 1
For j = 0 To n - 1
b(i, j) = n * n + 1
Next
Next
によって初期化している理由は、
対角線などのすでに入っている数字を、
上書きしないようにするためです。
n = 5 のときは、n * n + 1は26です。
これは5次魔方陣ではあり得ない数字です。
5次魔方陣は、1から25までの数字を埋めるというルールだからです。
あり得ない数字を入れておいて、
26 | 26 | 26 | 26 | 26 |
26 | 26 | 26 | 26 | 26 |
26 | 26 | 26 | 26 | 26 |
26 | 26 | 26 | 26 | 26 |
26 | 26 | 26 | 26 | 26 |
から
For i = 0 To n - 1
b(i, i) = i
Next
によって
0 | 26 | 26 | 26 | 26 |
26 | 1 | 26 | 26 | 26 |
26 | 26 | 2 | 26 | 26 |
26 | 26 | 26 | 3 | 26 |
26 | 26 | 26 | 26 | 4 |
と入力され、さらに、
k = n
For i = 0 To n - 1
If b(i, n - 1 - i) = n * n + 1 Then
b(i, n - 1 - i) = k
k = k + 1
End If
Next
0 | 26 | 26 | 26 | 5 |
26 | 1 | 26 | 6 | 26 |
26 | 26 | 2 | 26 | 26 |
26 | 26 | 26 | 3 | 26 |
26 | 26 | 26 | 26 | 4 |
によって、逆対角線のところを入力していくわけですが、
対角線の交差しているところに達したとき、
If b(i, n - 1 - i) = n * n + 1 Then
ですから、26のときだけ書き換えるようになっていますので、
2は書き換えられずに済むわけです。
同様に、
For i = 0 To n - 1
For j = 0 To n - 1
If b(i, j) = n * n + 1 Then
b(i, j) = k
k = k + 1
End If
Next
Next
0 | 9 | 10 | 11 | 5 |
12 | 1 | 26 | 6 | 26 |
26 | 26 | 2 | 26 | 26 |
26 | 7 | 26 | 3 | 26 |
8 | 26 | 26 | 26 | 4 |
の場面でも、
If b(i, j) = n * n + 1 Then
が威力を発揮して1は上書きされずに済むわけです。
以上を続けていって、
0 | 9 | 10 | 11 | 5 |
12 | 1 | 13 | 6 | 14 |
15 | 16 | 2 | 17 | 18 |
19 | 7 | 20 | 3 | 21 |
8 | 22 | 23 | 24 | 4 |
が実現します。
さて、いよいよ核心部分です。
0 | 1 | 2 | 3 | 4 | |
0 | 0 | 9 | 10 | 11 | 5 |
1 | 12 | 1 | 13 | 6 | 14 |
2 | 15 | 16 | 2 | 17 | 18 |
3 | 19 | 7 | 20 | 3 | 21 |
4 | 8 | 22 | 23 | 24 | 4 |
白い数字とy座標(表の赤)とx座標(表の青)が関連づけを行って下さい。
どうやった関連づけられますか。
個々の場合での関連づけではなく、
汎用的=普遍的(いかなるnに対してもということ)に関連づけるには?
eclipse c++ 入門
魔方陣 数独で学ぶ VBA 入門
数独のシンプルな解き方・簡単な解法の研究
vc++講義へ
excel 2013 2010 2007 vba入門へ
VB講義基礎へ
初心者のための世界で一番わかりやすいVisual C++入門基礎講座へ
初心者のための世界で一番わかりやすいVisual Basic入門基礎講座へ
専門用語なしの C言語 C++ 入門(Visual C++ 2010で学ぶ C言語 C++ 入門)
専門用語なしの excel vba マクロ 入門 2013 2010 2007 対応講義 第1部
eclipse java 入門へ
excel 2016 vba 入門へ
小学生からエンジニアまでのRuby入門へ
本サイトトップへ