第16講 全セルリスト構造解析(全体リスト構造解析)によって数独(ナンプレ)を解く
第7話 全セルリスト構造解析のプログラム例

プログラム全文
Dim mah(8, 8) As Byte, lst(8, 8, 8) As Byte, mx(8, 8) As Byte, h(8, 8, 8) As Byte

Private Sub CommandButton1_Click()
  
  Dim i As Byte, j As Byte
  dainyuu
  syokika
  For i = 0 To 8
    For j = 0 To 8
      If mah(i, j) = 0 Then
        Call cellkaiseki1(i, j)
        Call cellkaiseki2(i, j)
      End If
    Next
  Next
  hyouji

End Sub

Sub dainyuu()
  
  Dim i As Byte, j As Byte
  For i = 0 To 8
    For j = 0 To 8
      If Cells(4 + i, 2 + j) = "" Then mah(i, j) = 0 Else mah(i, j) = Cells(4 + i, 2 + j)
    Next
  Next
  
End Sub

Sub hyouji()
  
  Dim i As Byte, j As Byte, k As Byte
  For i = 0 To 8
    For j = 0 To 8
      Cells(14 + i, 2 + j) = mah(i, j)
    Next
  Next
  
  For i = 0 To 8
    For j = 0 To 8
      Cells(24 + 5 * i, 1 + 10 * j) = "セル"
      Cells(24 + 5 * i, 2 + 10 * j) = i
      Cells(24 + 5 * i, 3 + 10 * j) = j
      Cells(24 + 5 * i, 4 + 10 * j) = "のリスト"
      For k = 0 To 8
        Cells(25 + 5 * i, 1 + 10 * j + k) = lst(i, j, k)
      Next
      Cells(26 + 5 * i, 1 + 10 * j) = "セル"
      Cells(26 + 5 * i, 2 + 10 * j) = i
      Cells(26 + 5 * i, 3 + 10 * j) = j
      Cells(26 + 5 * i, 4 + 10 * j) = "のリスト数"
      Cells(27 + 5 * i, 1 + 10 * j) = mx(i, j)
      
    Next
  Next

  
  
End Sub

Sub syokika()

  Dim i As Byte, ja As Byte, k As Byte
  
  For i = 0 To 8
    For j = 0 To 8
      For k = 0 To 8
        h(i, j, k) = 1
        lst(i, j, k) = k + 1
      Next
    Next
  Next
  
End Sub

Sub cellkaiseki1(i As Byte, j As Byte)
  
  Dim k As Byte, l As Byte
  
  For k = 0 To 8
    If mah(i, k) > 0 Then h(i, j, mah(i, k) - 1) = 0
  Next
  
  For k = 0 To 8
    If mah(k, j) > 0 Then h(i, j, mah(k, j) - 1) = 0
  Next
  
  For k = 0 To 2
    For l = 0 To 2
      If 3 * Int(i / 3) + k <> i And 3 * Int(j / 3) + l <> j Then
        If mah(3 * Int(i / 3) + k, 3 * Int(j / 3) + l) > 0 Then h(i, j, mah(3 * Int(i / 3) + k, 3 * Int(j / 3) + l) - 1) = 0
      End If
    Next
  Next  (2014/12/07訂正)


End Sub

Sub cellkaiseki2(i As Byte, j As Byte)
  
  Dim k As Byte, w As Byte
  
  w = 0
  For k = 0 To 8
    If h(i, j, k) = 1 Then
      lst(i, j, w) = k + 1
      w = w + 1
    End If
  Next
  mx(i, j) = w
  For k = 0 To 8
    If h(i, j, k) = 0 Then
      lst(i, j, w) = k + 1
      w = w + 1
    End If
  Next
  
End Sub


Private Sub CommandButton2_Click()
  
  Rows("14:200").Select
  Selection.ClearContents
  Range("M5", "V9").Select
  Selection.ClearContents
  Cells(2, 1).Select

End Sub

参考ファイル5

さて、全セルのリスト構造解析が済みましたので、
これに基づいていよいよ数独をコンピュータに解かせます。
ただし、プログラムを複雑にしすぎないため、
プログラムがセルに数字を入れることによってリスト構造が変化することは、
考慮に入れないことにします。
プログラムがセルに数字を入れたことによるリスト構造変化を組み込むのは、
次の講の課題とします。

第13講 プロシージャの再帰的使用による数独解答自動生成
 第5話 数独解答自動生成ソフトコード例
を参考に考えて頂きたいと思いますが、
いきなりだと難しいと思いますのでヒントとして、
プログラムの1部のコードを載せておきます。
Dim mah(8, 8) As Byte, lst(8, 8, 8) As Byte, mx(8, 8) As Byte, h(8, 8, 8) As Byte,
cn As Byte


Private Sub CommandButton1_Click()
  
  Dim i As Byte, j As Byte
, hajime As Variant, owari As Variant
  
  
hajime = Timer
  dainyuu
  syokika
  For i = 0 To 8
    For j = 0 To 8
      If mah(i, j) = 0 Then
        Call cellkaiseki1(i, j)
        Call cellkaiseki2(i, j)
      End If
    Next
  Next
  
f (0)
  
owari = Timer
  Cells(7, 13) = "解くのにかかった時間は"
  Cells(8, 13) = owari - hajime
  Cells(9, 13) = "秒です。"

End Sub


Sub hyouji()
  
  Dim i As Byte, j As Byte, k As Byte
  
  For i = 0 To 8
    For j = 0 To 8
      Cells(14 + i, 2 + j) = mah(i, j)
    Next
  Next
  
End Sub


Sub syokika()

  Dim i As Byte, ja As Byte, k As Byte
  
  
cn = 0
  For i = 0 To 8
    For j = 0 To 8
      For k = 0 To 8
        h(i, j, k) = 1
        lst(i, j, k) = k + 1
      Next
    Next
  Next
  
End Sub


Sub f(g As Byte)
  
  Dim i As Byte, j As Byte, k As Byte
  Dim y As Byte, x As Byte, h As Byte
  
  y = Int(g / 9)
  x = g Mod 9
  
  If mah(y, x) > 0 Then
    If g + 1 < 81 Then
      f (g + 1)
      If cn = 1 Then Exit Sub
    Else
      cn = cn + 1
      hyouji
    End If
  End If
  h = 0
  If mah(y, x) = 0 Then
    For i = 0 To mx(y, x) - 1
      mah(y, x) = lst(y, x, i)
      h = 1
      For j = 0 To 8
        If j <> x Then
          If mah(y, x) = mah(y, j) Then GoTo tobi
        End If
      Next
              ・
              ・
              ・
      If g + 1 < 81 Then
        f (g + 1)
        If cn = 1 Then Exit Sub
      Else
        cn = cn + 1
        hyouji
      End If
tobi:
    Next
  End If
  If h = 1 Then mah(y, x) = 0
  
End Sub


実行画面
解答図







第6話へ 第8話へ



トップ

初心者のためのc++ vc++ c言語 入門 基礎から応用までへ
初心者のための excel 2007 2010 2013 vba マクロ 入門 基礎から応用まで
初心者のための世界で一番わかりやすいVisual C++入門基礎講座
初心者のための世界で一番わかりやすいVisual Basic入門基礎講座へ
vb講義トップへ
VB講義基礎へ
専門用語なしのC++入門へ
専門用語なしのJava入門へ
専門用語なしのVBA入門

数独のページ
魔方陣のページ
数学研究室に戻る
本サイトトップへ