第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

piygf
を実現するプログラム例
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

白い数字と座標(表の)と座標(表の)が関連づけを行って下さい。
どうやった関連づけられますか。
個々の場合での関連づけではなく、
汎用的=普遍的(いかなるnに対してもということ)に関連づけるには?





第3話へ 第5話へ
004

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入門へ
本サイトトップへ