第2講 再帰的呼び出しで魔方陣を作ろう!
第3話 プログラム本体(再帰的呼び出しプロシージャ)は?

再帰的呼び出しによる順列の作成のSub jyunretusakusei(g As Integer)
のgに相当するのが、

 0  1  2  3
 0  1  2  3
 4  5  6  7
 8  9 10 11
12 13 14 15

の白の番号です。
魔方陣を再帰的に作り出すSubプロシージャを
Sub sakusei(g as integer)
と名付けると、
メインプロシージャから最初呼び出すときは、sakusei(0)
でなければなりません。
順列のときは、位置番号を1から始めましたが今回から0としているからです。
さて、問題は
Sub sakusei(g as integer)
     ・
     ・
     ・
End Sub
の中身をどうするかです。
数字の入れ方は順列のときと同じですが、
黄色の位置に来たときに、
行合計、列合計、対角線合計などが
同じ合計になっているか確認しなければなりません。
その合計値はn×(n×n+1)÷2の計算で求められます。
というのは、n次魔方陣の場合1からn×nまでの数字が入り、
そのすべての数字の合計は
1+2+3+・・・+n×n=n×n×(n×n+1)÷2
で、それを行数のnで割ったものが各行などの合計値になるからです。
黄色はさらに

 0  1  2  3
 0  1  2  3
 4  5  6  7
 8  9 10 11
12 13 14 15

の4種類に分かれます。
3、7、8は行合計(横合計)
12は列合計(縦合計)と対角線合計
13、14は列合計
15は行合計、列合計、対角線合計
がそれぞれn×(n×n+1)÷2
になっていることを確認しなければなりません。
以上より例えば、次のようなソース例が考えられます。

Sub sakusei(g As Integer)

  Dim i As Integer, j As Integer, k As Integer
   Dim l As Integer, hh As Integer, wa As Integer
  j = g Mod n
  i = Int(g / n)

  For k = 1 To n * n
    mah(i, j) = k
    hh = 0
    If tyouhukuhantei(k - 1) = 1 Then GoTo owari
    tyouhukuhantei(k - 1) = 1
    hh = 1
    If j = n - 1 Then
      wa = 0
      For l = 0 To n - 1
        wa = wa + mah(i, l)
      Next
      If wa <> Int(n * (n * n + 1) / 2) Then GoTo owari
    End If

    
If i = n - 1 Then
      wa = 0
      For l = 0 To n - 1
        wa = wa + mah(l, j)
      Next
      If wa <> Int(n * (n * n + 1) / 2) Then GoTo owari
    End If

    If i = n - 1 And j = 0 Then
      wa = 0
      For l = 0 To n - 1
        wa = wa + mah(l, n - 1 - l)
      Next
      If wa <> Int(n * (n * n + 1) / 2) Then GoTo owari
    End If

    If i = n - 1 And j = n - 1 Then
      wa = 0
      For l = 0 To n - 1
        wa = wa + mah(l, l)
      Next
      If wa <> Int(n * (n * n + 1) / 2) Then GoTo owari
    End If

    If g + 1 < n * n Then
      sakusei (g + 1)
    Else
      cn = cn + 1
      hyouji
    End If
owari:
    If hh = 1 Then tyouhukuhantei(k - 1) = 0
  Next
  mah(i, j) = 0

End Sub

GoTo owariはowari:に飛ぶ命令です。
かつてのBASICの頃、GoTo文はスパゲティプログラムの元凶とされ、
今ではすっかり悪者扱いですが、
使い方によっては便利なものです。
飛ぶ場所を1箇所に決めておけば、
スパゲティにはなりません。
ですが、構造化プログラミングを意識し、
使用は最小限にすべきことは言うまでもありません。

以上のようにして魔方陣プログラム1ができあがります。
次講ではこのできがいいとは言えないプログラムの改善に取り組み、
1万倍以上の高速化に取り組みます。
その前に、プログラムについて疑問な点があると思いますので、
第4話でそれを解消していきましょう。

第2講第2話へ 第2項第4話へ 第3講第1話へ


VB入門講義応用編トップへ

VB入門講義トップへ