最終講 卒業研究と卒業試験

第4話 課題3 9次ラテン方陣にブロックの条件を加える

解答例
Public Class Form1
   '変数の宣言と初期化
   Dim a(9, 9) As Integer, x(81) As Integer, y(81) As Integer, s As Integer
   Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
     Dim hj, ow As DateTime, sa As TimeSpan
     hj = Now
     s = 0
  
   DataGridView1.Rows.Clear()
     h()
     f(0)
     DataGridView1.Rows.Add() '1行追加
     DataGridView1(7, 10 * s).Value() = "順"
     DataGridView1(8, 10 * s).Value() = "列"
     DataGridView1(9, 10 * s).Value() = "方"
     DataGridView1(10, 10 * s).Value() = "陣"
     DataGridView1(11, 10 * s).Value() = "総"
     DataGridView1(12, 10 * s).Value() = "数"
     DataGridView1(13, 10 * s).Value() = s '総数表示
     ow = Now
     sa = ow - hj
     DataGridView1.Rows.Add() '1行追加
     DataGridView1(9, 10 * s + 1).Value() = "計"
     DataGridView1(10, 10 * s + 1).Value() = "測"
     DataGridView1(11, 10 * s + 1).Value() = "時"
     DataGridView1(12, 10 * s + 1).Value() = "間"
     DataGridView1(13, 10 * s + 1).Value() = sa.TotalSeconds '計測時間表示
   End Sub

   Sub h()
     For i = 0 To 80
       x(i) = i Mod 9
       y(i) = Int(i / 9)
     Next
   End Sub

   Sub f(ByVal g As Integer)
     If s = 100 Then Exit Sub
     Dim h,
xs, ys As Integer
     For i = 0 To 8
       a(y(g), x(g)) = i + 1
       h = 1
       If x(g) > 0 Then
         For j = 0 To x(g) - 1
           If a(y(g), x(g)) = a(y(g), j) Then
             h = 0
             Exit For
           End If
         Next
       End If
       If h = 1 Then
         If y(g) > 0 Then
           For j = 0 To y(g) - 1
             If a(y(g), x(g)) = a(j, x(g)) Then
               h = 0
               Exit For
             End If
           Next
         End If
       End If
       If h = 1 Then
         If g > 0 Then
           xs = Int(x(g) / 3)
           ys = Int(y(g) / 3)
           For j = 0 To y(g) - 3 * ys
             For k = 0 To 2
               If y(g) = j Then If x(g) = k Then Exit For
               If y(g) <> 3 * ys + j And x(g) <> 3 * xs + k Then
                 If a(y(g), x(g)) = a(3 * ys + j, 3 * xs + k) Then
                   h = 0
                   Exit For
                 End If
               End If
             Next
             If h = 0 Then Exit For
           Next
         End If
       End If

       If h = 1 Then
          If g + 1 < 81 Then
            f(g + 1)
          Else
            For j = 0 To 8
              DataGridView1.Rows.Add() '1行追加
              For k = 0 To 8
                DataGridView1(k, j + 10 * s).Value = a(j, k)
              Next
            Next
            DataGridView1.Rows.Add() '1行追加
    
        s = s + 1
            If s = 100 Then Exit Sub
          End If
       End If
     Next
   End Sub

End Class
実行例

解説
       If h = 1 Then
         If g > 0 Then
           xs = Int(x(g) / 3)
           ys = Int(y(g) / 3)
           For j = 0 To y(g) - 3 * ys
             For k = 0 To 2
               If y(g) = j Then If x(g) = k Then Exit For
               If y(g) <> 3 * ys + j And x(g) <> 3 * xs + k Then
                 If a(y(g), x(g)) = a(3 * ys + j, 3 * xs + k) Then
                   h = 0
                   Exit For
                 End If
               End If
             Next
             If h = 0 Then Exit For
           Next
         End If
       End If

が加えた部分です。
           xs = Int(x(g) / 3)
           ys = Int(y(g) / 3)

では何をしているんでしょうか。実はブロック番号を計算しています。

1 2 3
0 0 1 2 3 4 5 6 7 8
9 10 11 12 13 14 15 16 17
18 19 20 21 22 23 24 25 26
1 27 28 29 30 31 32 33 34 35
36 37 38 39 40 41 42 43 44
45 46 47 48 49 50 51 52 53
2 54 55 56 57 58 59 60 61 62
63 64 65 66 67 68 69 70 71
72 73 74 75 76 77 78 79 80

例えば、セル番号49は、ブロック番号(02)に対応します。
セル番号の49とき、
           For j = 0 To y(g) - 3 * ys
             For k = 0 To 2
               If y(g) = j Then If x(g) = k Then Exit For
               If y(g) <> 3 * ys + j And x(g) <> 3 * xs + k Then
                 If a(y(g), x(g)) = a(3 * ys + j, 3 * xs + k) Then
                   h = 0
                   Exit For
                 End If
               End If
             Next
             If h = 0 Then Exit For
           Next
では、セル番号49とセル番号30,32,39,41の内容が比較されます。
セル番号31,40,48
     For i = 0 To 8
       a(y(g), x(g)) = i + 1
       h = 1
       If x(g) > 0 Then
         For j = 0 To x(g) - 1
           If a(y(g), x(g)) = a(y(g), j) Then
             h = 0
             Exit For
           End If
         Next
       End If
       If h = 1 Then
         If y(g) > 0 Then
           For j = 0 To y(g) - 1
             If a(y(g), x(g)) = a(j, x(g)) Then
               h = 0
               Exit For
             End If
           Next
         End If
       End If
において重複チェックが済んでいまし、セル番号0から順に入れてきてセル番号49までしか数字が入っていませんから、
セル番号
50にはまだ数字が入っていないので比較の必要がないわけです。

30 31 32
39 40 41
48 49 50

If y(g) = j Then If x(g) = k Then Exit Forセル番号50を検査対象から外すためにあります。
セル番号49に達したら検査を終了するようになっています。
y(g) <> 3 * ys + j And x(g) <> 3 * xs + kは、同行と同列を検査対象から外すためにあります。
31,40,48は一度検査されているのでテストの必要はないわけです。
では、For j = 0 To y(g) - 3 * ysj = 0 To y(g) - 3 * ysの意味は何でしょうか。
例えば、セル番号39なら

30 31 32
39 40 41
48 49 50


最後の行は検査する必要はありません。
セル番号39までしか数字が入っていないからです。






では皆さん、
課題4
課題3で完成させたソフトに

ブロックの区切り*入れましょう。

課題5
課題4にさらにランダムを入れて自然な数独にしましょう。

に挑戦して、卒業研究課題は終了です。
後は、卒業試験を残すのみとなります。




第3話へ 第5話へ

006

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

数学研究室に戻る