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

第5話 課題4 ブロック線を加える 課題5 ランダムを入れて自然な数独にする

解答例
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,
l, m 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
            l = 0
            For j = 0 To 8
              DataGridView1.Rows.Add() '1行追加
              If j Mod 3 = 0 Then
                DataGridView1.Rows.Add() '1行追加
                For k = 0 To 12
                  DataGridView1(k, j + l + 14 * s).Value = "*"
                Next
                l = l + 1
             End If
             m = 0
             For k = 0 To 8
               If k Mod 3 = 0 Then
                 DataGridView1(k + m, j + l + 14 * s).Value = "*"
                 m = m + 1
               End If
               DataGridView1(k + m, j + l + 14 * s).Value = a(j, k)
             Next
             DataGridView1(12, j + l + 14 * s).Value = "*"
           Next
           DataGridView1.Rows.Add() '1行追加
           For k = 0 To 12
             DataGridView1(k, 9 + l + 14 * s).Value = "*"
           Next
           DataGridView1.Rows.Add() '1行追加
           s = s + 1
           If s = 100 Then Exit Sub

         End If
       End If
     Next
   End Sub

End Class
実行例

解説
            l = 0
            For j = 0 To 8
              DataGridView1.Rows.Add() '1行追加
              If j Mod 3 = 0 Then
                DataGridView1.Rows.Add() '1行追加
                For k = 0 To 12
                  DataGridView1(k, j + l + 14 * s).Value = "*"
                Next
                l = l + 1
             End If

jが3の倍数になる度に
                DataGridView1.Rows.Add() '1行追加
                For k = 0 To 12
                  DataGridView1(k, j + l + 14 * s).Value = "*"
                Next
によって、を加えています。
                l = l + 1
の分の1行分をずらすためにあります。
               DataGridView1(k + m, j + l + 14 * s).Value = a(j, k)
が入る度に1行増えていくわけですが、
lでそれに対応させています。
             m = 0
             For k = 0 To 8
               If k Mod 3 = 0 Then
                 DataGridView1(k + m, j + l + 14 * s).Value = "*"
                 m = m + 1
               End If
               DataGridView1(k + m, j + l + 14 * s).Value = a(j, k)
             Next

においては、
            l = 0
            For j = 0 To 8
              DataGridView1.Rows.Add() '1行追加
              If j Mod 3 = 0 Then
                DataGridView1.Rows.Add() '1行追加
                For k = 0 To 12
                  DataGridView1(k, j + l + 14 * s).Value = "*"
                Next
                l = l + 1
             End If

が行版だったのに対して、列版となっています。つまり、を入れているのです。
発想は行のときと同じです。kが3の倍数となる度にを入れているのです。
行版との違いは、
行版においてはFor文によって一気にを入れているのに対して、
列版ではを一つ一つ入れています。
           DataGridView1.Rows.Add() '1行追加
           For k = 0 To 12
             DataGridView1(k, 9 + l + 14 * s).Value = "*"
           Next

では、最後の行を入れています。
次のDataGridView1.Rows.Add() '1行追加では空白行
を作っています。


課題5のランダムを組み込むことは簡単です。
   Sub f(ByVal g As Integer)
     If s = 100 Then Exit Sub
     Dim h, xs, ys, l, m,
kk, kkk As Integer
     
kk = Int(9 * Rnd())
     For i = 0 To 8
       
kkk = (kk + i) Mod 9 + 1
       a(y(g), x(g)) =
kkk
            ・

            ・
            ・

のように
を加えるないし変更すればよいのです。
実行例

解説
kk = Int(9 * Rnd())によって、kkには9未満の整数がランダムに入ります。
rand()によって、ランダムな整数が発生させて、それを9で割った余りにしているからです。
kkk = (kk + i) Mod 9 + 1によってkkkはどのように動いていくのでしょうか。
例えば,kk=5であったとすると、iが0から8まで変化していくとき、
kkk= ( 5 + 0) Mod 9+ 1=6
kkk= ( 5 + 1) Mod 9+ 1=7
kkk= ( 5 + 2) Mod 9+ 1=8
kkk= ( 5 + 3) Mod 9+ 1=9
kkk= ( 5 + 4) Mod 9+ 1=1
kkk= ( 5 + 5) Mod 9+ 1=2
kkk= ( 5 + 6) Mod 9+ 1=3
kkk= ( 5 + 7) Mod 9+ 1=4
kkk= ( 5 + 8) Mod 9+ 1=5
と動いていきます。結局、1から9まで網羅されていますが、
始まりが6からとなっているのです。
要するにkk = Int(9 * Rnd())によって始まりを変えることによって自然な数独としているのです。

これで自然な数独を作るという課題が実現できました。

いよいよ卒業試験を残すのみです。
さあ、卒業試験を受けて合格できたら卒業です。
がんばりましょう。




第4話へ 第6話へ

006

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

数学研究室に戻る