第15講 3次魔方陣と4次魔方陣の作成

第6話 3次魔方陣と4次魔方陣の自動生成コード解説その3
解説
Private Sub CommandButton1_Click()

  n = Cells(3, 8)
  cn = 0
  zhy
  ms (0)
  Cells(4, 12) = cn

End Sub

座標が完成した後、ms (0)によっていよいよ魔方陣の作成です。
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
個々で順列作成のときに注意したことを再度繰り返しておきます。
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
それは
の役割の違いです。はセル番号であり、はそのセルの内容です。
おなじみの比喩で言いますと、
はビール瓶のラベルであり、はビール瓶に入っているビールです。
アドレスに比喩で言えば、は住所であり、はその住所に建っている建物です。
の概念を明確に区別しないとプログラムは訳のわからないものになります。

私が、観察するところによると、数学の苦手な生徒は概念の区別、役割の違いが把握できない生徒です。
数学の苦手な生徒は、平気で次のようなことを書いてしまいます。
sinθ=60°
θは角の大きさであり、sinθは比の値を表すことが明確に区別できないのです。
角の大きさ(角度)と比の値は、関係を持っていますがまったく別の概念です。
汚い比喩で申し訳ないのですが、
これは口から入ってくる食べ物と肛門から出ていくウンコを区別していないのと同じです。
sinθというブラックボックスに角度を入れると、出口からは比の値が出てきます。
入門
sinθ=60°のように出口から角度が出てくることはありません。
角度はブラックボックスsinθによって、比の値に加工され出口から出てくるのです。
口から入った食物が人の中で加工され、肛門からウンコとなって出てくるのに対応します。
ですから、sinθ=60°は食物とウンコの混同です。
数学についてもプログラムについても得意になりたければ、概念や役割を明確に区別しなければなりません。

はビール瓶のラベルであり、はビール瓶に入っているビールであることを踏まえてトレースをしていきます。
とても長いトレースになりますが、粘り強くお付き合いお願いします。

ms (0)に飛ぶ先はどこでしょうか。

  a = x(g)
  b = y(g)

  For i = 0 To n * n - 1
    mah(b, a) = i + 1

g=0のときは、前話でトレースしたようにx()=、y()=ですから、飛ぶ先は

   0
0  0 1 2
     
1  3 4 5
     
2  6 7 8
     


 

です。









i=0ですから、
    mah(b, a) = i + 1
によって、

   0
0  0 1 2
   
1  3 4 5
     
2  6 7 8
     

となります。現在g=0ですから
    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
のIf文が実行されます。
g+1なので
x()=、y()=となりますので、今度飛ぶ次元世界は、

   0
0  0 1 2
   
1  3 4 5
     
2  6 7 8
     

です。
   For i = 0 To n * n - 1
    mah(b, a) = i + 1
によって、

   0
0  0 1 2
   
1  3 4 5
     
2  6 7 8
     

となります。
g=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 mah(b, a) = mah(y(j), x(j)) Then GoTo tobiに抵触して、
tobi:
  Next
すぐにNextにより
i=1となり、

   0
0  0 1 2
   
1  3 4 5
     
2  6 7 8
     

今度は検査
    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
をクリアします。2は1とのみ比べられるからです。
    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
のIf文によって、次の次元世界に跳躍します。
g=2とき、x()=、y()=となりますので、

   0
0  0 1 2
   
1  3 4 5
     
2  6 7 8
     


が今度の次元世界です。
For文によって、

   0
0  0 1 2
   
1  3 4 5
     
2  6 7 8
     



となりますが、
試験
    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
の一巡目でチェックされえてしまいます。
セル番号
とセル番号が同じ1になっているからです。
したがって、tobi:に飛び、iはインクリメントされ

   0
0  0 1 2
   
1  3 4 5
     
2  6 7 8
     



















となりますが、今回はストレステストの2巡目において禁則に抵触します。
セル番号とセル番号が同じ2であるからです。
再びtobiに飛びiは2となり、mah(b, a) = i + 1から

   0
0  0 1 2
   
1  3 4 5
     
2  6 7 8
     
















今回は、数字の重複検査
    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
を一巡目も2巡目をクリアします。
しかし、3−1=
で合計チェック検査
    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
の対象になりますが、クリアできません。現時点の合計は残念ながら1+2+3=6で、3次魔方陣の行の合計3×(3×3+1)÷2=15に等しくないからです。
tobiに飛び、iは3となり、

   0
0  0 1 2
   
1  3 4 5
     
2  6 7 8
     
















今回も合計検査にチェックされてtobiへ行きます。
以下同様に繰り返して、

   0
0  0 1 2
   
1  3 4 5
     
2  6 7 8
     
















となっても合計は、12ににすぎず次元世界
は終焉を迎えます。

   0
0  0 1 2
   
1  3 4 5
     
2  6 7 8
     


以下

   0
0  0 1 2
   
1  3 4 5
     
2  6 7 8
     


   0
0  0 1 2
   
1  3 4 5
     
2  6 7 8
     


   0
0  0 1 2
   
1  3 4 5
     
2  6 7 8
     


   0
0  0 1 2
   
1  3 4 5
     
2  6 7 8
     



















・・・・

   0
0  0 1 2
   
1  3 4 5
     
2  6 7 8
     



まで来ても、合計は13にすぎず、再び次元世界
は消滅します。
結局

   0
0  0 1 2
   
1  3 4 5
     
2  6 7 8
     


まで来て初めて横合計テスト
    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
を初めてクリアします。合計が15になったからです。








本日のトレースはここまでとします。以降は次話で。







第5話へ 第7話へ

004
  


VBA講義第1部へ
vc++講義へ
vb講義へ
VB講義基礎へ
初心者のための世界で一番わかりやすいVisual C++入門基礎講座へ
初心者のための世界で一番わかりやすいVisual Basic入門基礎講座へ

数学研究室に戻る