第9講 サブプロシージャの再帰的使用

第12話 魔方陣生成ソフトのコード解説その2
oiu
ht
コード主要部分再掲
Sub f(g As Integer)

  Dim i As Integer, j As Integer
  
  For i = 1 To n * n
    If g > 0 Then
      For j = 0 To g - 1
        If i = a(j) Then GoTo tobi
      Next
    End If
    a(g) = i
    
    If g Mod n = n - 1 Then
      w = 0
      For j = 0 To n - 1
        w = w + a(n * Int(g / n) + j)
      Next
      If w <> Int(n * (n * n + 1) / 2) Then GoTo tobi
    End If
    
    If Int(g / n) = n - 1 Then
      w = 0
      For j = 0 To n - 1
        w = w + a(n * j + (g Mod n))
      Next
      If w <> Int(n * (n * n + 1) / 2) Then GoTo tobi
    End If
    
    If g = n * n - 1 Then
      w = 0
      For j = 0 To n - 1
        w = w + a(n * j + j)
      Next
      If w <> Int(n * (n * n + 1) / 2) Then GoTo tobi
    End If
    
    If g = n * (n - 1) Then
      w = 0
      For j = 0 To n - 1
        w = w + a(n * j + n - 1 - 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)
    Else
      Call h
    End If
tobi:
  Next
  
End Sub

解説の続き

1行1行追いながらの解説に入る前に、
何話かをかけて、各If文の業務内容を確認しておきます。
以下の記述は、
n = 3 すなわち、3次魔方陣の自動生成を行うという前提
で行います。
最初のIf文
    If g > 0 Then
      For j = 0 To g - 1
        If i = a(j) Then GoTo tobi
      Next
    End If
では何をしているかと申しますと、
数字の重複チェックを行っています。
魔方陣は、すべて異なる整数を入れなければならないからです。
もし重複がある場合には
        If i = a(j) Then GoTo tobi
によって、tobiに飛びNextによりiは1つ進むようになっています。

    If g Mod n = n - 1 Then
      w = 0
      For j = 0 To n - 1
        w = w + a(n * Int(g / n) + j)
      Next
      If w <> Int(n * (n * n + 1) / 2) Then GoTo tobi
    End If
の任務は何でしょうか。
If文の条件 g Mod n = n - 1 が何を意味しているのか理解できれば、
どんな仕事をしているのかが、分かります。

0 1 2
3 4 5
6 7 8

条件 g Mod n = n - 1 を満たすのは、2,5,8の場合のみです。
n - 1 = 3 - 1 = 2
g Mod n = 2 Mod 3 = 2
g Mod n = 5 Mod 3 = 2
g Mod n = 8 Mod 3 = 2
ですよね。
それに対して、
g Mod n = 0 Mod 3 = 0
g Mod n = 1 Mod 3 = 1
g Mod n = 3 Mod 3 = 0
g Mod n = 4 Mod 3 = 1
g Mod n = 6 Mod 3 = 0
g Mod n = 7 Mod 3 = 1
0,1,3,4,6,7は条件を満たしません。

      w = 0
      For j = 0 To n - 1
        w = w + a(n * Int(g / n) + j)
      Next
の4行では何をしているでしょうか。
g = 2 の場合
 j = 0 のとき、
  w = w + a(n * Int(g / n) + j) = w + a(3 * Int(2 / 3) + 0) = w + a(0)
 j = 1 のとき、
  w = w + a(n * Int(g / n) + j) = w + a(3 * Int(2 / 3) + 1) = w + a(1)
 j = 2 のとき、
  w = w + a(n * Int(g / n) + j) = w + a(3 * Int(2 / 3) + 2) = w + a(2)

0 1 2
3 4 5
6 7 8

 以上から、1行目の合計が行われていることが分かります。

g = 5 の場合
 j = 0 のとき、
  w = w + a(n * Int(g / n) + j) = w + a(3 * Int(5 / 3) + 0) = w + a(3)
 j = 1 のとき、
  w = w + a(n * Int(g / n) + j) = w + a(3 * Int(5 / 3) + 1) = w + a(4)
 j = 2 のとき、
  w = w + a(n * Int(g / n) + j) = w + a(3 * Int(2 / 3) + 2) = w + a(5)

0 1 2
3 4 5
6 7 8

 以上から、2行目の合計が行われていることが分かります。

g = 8 の場合
 j = 0 のとき、
  w = w + a(n * Int(g / n) + j) = w + a(3 * Int(8 / 3) + 0) = w + a(6)
 j = 1 のとき、
  w = w + a(n * Int(g / n) + j) = w + a(3 * Int(8 / 3) + 1) = w + a(7)
 j = 2 のとき、
  w = w + a(n * Int(g / n) + j) = w + a(3 * Int(8 / 3) + 2) = w + a(8)

0 1 2
3 4 5
6 7 8

 以上から、3行目の合計が行われていることが分かります。


ですから、
    If g Mod n = n - 1 Then
      w = 0
      For j = 0 To n - 1
        w = w + a(n * Int(g / n) + j)
      Next
      If w <> Int(n * (n * n + 1) / 2) Then GoTo tobi
    End If
では行(横)合計が魔方陣の条件を満たしているかを調べているわけです。



第11話へ 第13話へ
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 入門へ第2部へ
小学生からエンジニアまでのRuby入門へ
本サイトトップへ