第2講 試行錯誤法でヒント数0数独の解答を作る(1)
第10話 n次魔方陣の生成

002
を実現させるプログラム例

Dim n As Byte, x(15) As Byte, cn As Integer 'nは魔方陣の次数、x(15)は魔方陣を収納する
Private Sub CommandButton1_Click()
  CommandButton2_Click
  n = Cells(3, 2)
  cn = 0
  f (0) 'n次魔方陣作成プロシージャ
End Sub
Sub f(g As Byte)
  Dim i As Byte, j As Byte, k As Byte, h As Byte, a As Integer, s As Integer, w As Byte
  a = cn Mod 10
  s = Int(cn / 10) '以上の2行は生成された魔方陣を適切位置に表示するためのもの。
  For i = 0 To n * n - 1
    x(g) = i + 1
    h = 1
    If g > 0 Then '過去との重複を検査して重複がある場合にはhを0として以下の処理を行わせない。
      For j = 0 To g - 1
        If x(j) = x(g) Then
          h = 0
          Exit For
        End If
      Next
    End If
    If h = 1 And g Mod n = n - 1 Then '横合計検査、合計が1からn*nの合計÷nに等しくない場合にはhを0として以下の処理を行わせない。
      w = 0
      For j = 0 To n - 1
        w = w + x(g - j)
      Next
      If w <> Int(n * (n * n + 1) / 2) Then
        h = 0
      End If
    End If
    If h = 1 And Int(g / n) = n - 1 Then '縦合計検査、合計が1からn*nの合計÷nに等しくない場合にはhを0として以下の処理を行わせない。
      w = 0
      For j = 0 To n - 1
        w = w + x(g - n * j)
      Next
      If w <> Int(n * (n * n + 1) / 2) Then
        h = 0
      End If
    End If
    
If h = 1 And Int(g / n) = n - 1 And (g Mod n) = 0 Then '対角線合計検査、合計が1からn*nの合計÷nに等しくない場合にはhを0として以下の処理を行わせない。
      w = 0
      For j = 0 To n - 1
        w = w + x(g - (n - 1) * j)
      Next
      If w <> Int(n * (n * n + 1) / 2) Then
        h = 0
      End If
    End If
    If h = 1 And Int(g / n) = n - 1 And (g Mod n) = n - 1 Then '逆対角線合計検査、合計が1からn*nの合計÷nに等しくない場合にはhを0として以下の処理を行わせない。
      w = 0
      For j = 0 To n - 1
        w = w + x(g - (n + 1) * j)
      Next
      If w <> Int(n * (n * n + 1) / 2) Then
        h = 0
      End If
    End If

    If h = 1 Then '重複検査・横合計検査・縦合計検査・対角線合計検査をパスした場合に次のセル(箱)番号の世界に飛ぶ。
      If g + 1 < n * n Then 'ただし、セル(箱)番号がn * n - 1以下のとき
        f (g + 1)
      Else 'セル(箱)番号がn * n - 1のとき、魔方陣が完成しているので、表示して魔方陣総数をカウント
        For j = 0 To n * n - 1
          Cells(4 + Int(j / n) + (n + 1) * s, 1 + (j Mod n) + (n + 1) * a) = x(j)
        Next
        cn = cn + 1
      End If
    End If
  Next
End Sub
Private Sub CommandButton2_Click()
  Rows("4:200").Select
  Selection.ClearContents
  Cells(1, 1).Select
End Sub

参考ダウンロード添付ファイル

x(15)を1次元にしてしまったために、
横合計・縦合計・対角線合計を求めるタイミングが難しくなってしまいました。
本当はx(3, 3)の2次元配列にしておけば、
簡単だったのです。
そこで、2次元配列に変更してn次魔方陣を生成させますが、
講の話は10話以内するのが本サイトの方針ですので、
講を改めて第3講第1話の課題とします。




第9話へ 第3講第1話へ


トップへ