我的程序被困在一个奇怪的冻结/无限循环中

时间:2016-07-16 14:51:23

标签: vb.net freeze sudoku

我正在VB.NET中编写一个Sudoku App。目前我正在为Sudoku益智生成器的实现工作。我写的那个有一个奇怪的问题,应用程序刚刚陷入停顿。起初我只是理性地假设我的代码中有一个无限循环。所以我添加了一个功能,如果do ... while循环连续运行超过50次,函数将重置。但那没有做任何事情!对于我的生活,我不能弄清楚我的程序发生了什么。如果有人能解释这个冻结,我会所以感激不尽。

这是我的功能/子/子程序:

Private Sub CreatePuzzle(ByVal Dificulty As Integer)
    Dim Rand As New Random()
    For Each Row As List(Of Box) In Rows
        Dim UsedNumbers As New List(Of Integer)
        Dim Column As Integer = 0
        For Each Cell As Box In Row
            Column = Cell.Column
            Dim I As Integer
            Do
                I = Math.Floor(Rand.NextDouble() * 9) + 1
            Loop While Arrays.Contains(UsedNumbers.ToArray(), I) Or _
                       Arrays.Contains(Box.GetValues(Columns(Column)), I) Or _
                       Arrays.Contains(Box.GetValues(Squares(Math.Floor(Column / 3D))), I)
            Cell.Val(I)
            UsedNumbers.Add(I)
            Debug.Print("Row: " & "ABCDEFGHI"(Cell.Row) & ", Column: " & _
                (Cell.Column + 1).ToString() & ", Square: " & Cell.Square.ToString() & _
                ", (Predicted) Square: " & Math.Floor(Column / 3D).ToString())
            Debug.Print("I: " & I.ToString())
            Debug.Print("")
        Next
    Next
End Sub

此外,以下是我用来表示Sudoku难题中的单元格的自定义Box类的实现:

Public Class Box
Private _Value As Integer = 0
Private _Row As Integer
Private _Column As Integer
Private _Square As Integer
Private Label As Label
Private _Name As String

Public ReadOnly Property Value As Integer
    Get
        Return _Value
    End Get
End Property

Public ReadOnly Property Row As Integer
    Get
        Return _Row
    End Get
End Property

Public ReadOnly Property Column As Integer
    Get
        Return _Column
    End Get
End Property

Public ReadOnly Property Square As Integer
    Get
        Return _Square
    End Get
End Property

Public ReadOnly Property Name As String
    Get
        Return Label.Name
    End Get
End Property

Public Sub New(ByRef Box As Label)
    Dim Values As String() = Box.Tag.ToString.Split(",")
    If Not Box.Text = "" Then
        _Value = Integer.Parse(Box.Text)
    End If
    _Row = Integer.Parse(Values(0))
    _Column = Integer.Parse(Values(1))
    _Square = Integer.Parse(Values(2))
    Label = Box
End Sub

Public Sub Val(ByVal Digit As Char, ByRef PreVal As Integer, ByRef PrevSelect As Label)
    Dim Value As Integer
    If Integer.TryParse(Digit, Value) AndAlso Not Value = 0 Then
        If Label.Text = "" Then
            PreVal = 0
        Else
            PreVal = Integer.Parse(PrevSelect.Text)
        End If
        PrevSelect = Label
        Label.Text = Digit
        _Value = Value
    End If
End Sub

Public Sub Val(ByVal Digit As Integer)
    If Digit = 0 Then
        Label.Text = ""
    Else
        Label.Text = Digit.ToString()
    End If
    _Value = Digit
End Sub

Public Shared Function GetValues(ByVal Boxes As List(Of Box)) As Integer()
    Dim Output(Boxes.Count - 1) As Integer
    For I As Integer = 0 To Output.GetUpperBound(0)
        Output(I) = Boxes(I).Value
    Next
    Return Output
End Function
End Class

编辑:这是Arrays.Contains()

的代码
Function Contains(ByVal HayStack() As Integer, ByVal Needle As Integer) As Boolean
    For I As Integer = 0 To HayStack.GetUpperBound(0)
        If HayStack(I) = Needle Then
            Return True
        End If
    Next
    Return False
End Function

如果您需要查看任何自定义实施,请发表评论。

2 个答案:

答案 0 :(得分:0)

好的......所以事实证明它不是一个无限循环,而是一个效率低下的算法,需要10分钟来创建拼图。

答案 1 :(得分:0)

我尝试创建一个数独谜题。使用该课程。

Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    Dim foo As New Puzzle()
    RichTextBox1.Text = foo.Display
    RichTextBox1.Refresh()
End Sub

班级

Public Class Puzzle
    Private Shared PRNG As New Random
    Private _thePuzzle As New List(Of List(Of Integer))
    Public thePuzzle As New List(Of List(Of Integer))

    Private base As List(Of Integer) = Enumerable.Range(1, 9).OrderBy(Function(x) PRNG.Next).ToList
    Public Sub New(Optional empties As Integer = 27)
        'creat base puzzle
        For x As Integer = 0 To 2 'first three rows
            Me._thePuzzle.Add(New List(Of Integer))
            Me.thePuzzle.Add(New List(Of Integer))
            Me._thePuzzle(x).AddRange(base)
            'blocks of three from front to rear
            base.AddRange(base.GetRange(0, 3))
            base.RemoveRange(0, 3)
        Next

        'DebugHelp(Me._thePuzzle)

        For x As Integer = 0 To 5 'next six rows
            base.Clear()
            base.AddRange(Me._thePuzzle(x))
            base.Add(base(0))
            base.RemoveAt(0)
            Me._thePuzzle.Add(New List(Of Integer))
            Me.thePuzzle.Add(New List(Of Integer))
            Me._thePuzzle(Me._thePuzzle.Count - 1).AddRange(base)
        Next

        'DebugHelp(Me._thePuzzle)

        '' shuffle
        Const shuffles As Integer = 3

        For sh As Integer = 1 To shuffles
            Me.Shuffle()
        Next

        'visible
        For r As Integer = 0 To Me._thePuzzle.Count - 1
            Me.thePuzzle(r).AddRange(Me._thePuzzle(r))
        Next

        DebugHelp(Me.thePuzzle)
        'set certain entries to zero
        Dim idxs As List(Of Integer) = Enumerable.Range(0, 81).ToList
        For x As Integer = 1 To empties
            Dim rmx As Integer = PRNG.Next(idxs.Count)
            Dim idx As Integer = idxs(rmx)
            idxs.RemoveAt(rmx)
            Dim r As Integer
            Dim c As Integer
            r = Math.DivRem(idx, 9, c)
            Me.thePuzzle(r)(c) = 0
            Threading.Thread.Sleep(0)
        Next

        ' DebugHelp(Me.thePuzzle)
    End Sub

    Public Function Display() As String
        Dim rv As New System.Text.StringBuilder
        Dim fmt As String = "{0,3}"
        For r As Integer = 0 To 8
            For c As Integer = 0 To 8
                If Me.thePuzzle(r)(c) = 0 Then
                    rv.AppendFormat(fmt, "□")
                Else
                    rv.AppendFormat(fmt, Me.thePuzzle(r)(c))
                End If
                If c Mod 3 = 2 AndAlso c <> 8 Then rv.AppendFormat(fmt, "|")
            Next
            rv.AppendLine()
            If r Mod 3 = 2 AndAlso r <> 8 Then
                rv.AppendLine("---------------------------------")
                'rv.AppendLine("_________________________________")
            End If
        Next
        Return rv.ToString
    End Function

    Private Sub Shuffle()
        Dim temp As Integer
        Dim agrp As Integer
        Dim IDT As Integer
        Dim IDF As Integer

        agrp = PRNG.Next(Me._thePuzzle.Count \ 3) * 3
        Do
            IDT = PRNG.Next(3) + agrp
            IDF = PRNG.Next(3) + agrp
        Loop While IDT = IDF

        'swap rows
        base.Clear()
        base.AddRange(Me._thePuzzle(IDT))
        Me._thePuzzle(IDT).Clear()
        Me._thePuzzle(IDT).AddRange(Me._thePuzzle(IDF))
        Me._thePuzzle(IDF).Clear()
        Me._thePuzzle(IDF).AddRange(base)

        'swap columns
        For rw As Integer = 0 To Me._thePuzzle.Count - 1
            temp = Me._thePuzzle(rw)(IDF)
            Me._thePuzzle(rw)(IDF) = Me._thePuzzle(rw)(IDT)
            Me._thePuzzle(rw)(IDT) = temp
        Next
    End Sub

    Private Sub DebugHelp(sl As List(Of List(Of Integer)))
        Debug.WriteLine("")
        For r As Integer = 0 To sl.Count - 1
            Debug.Write("'")
            For c As Integer = 0 To sl(r).Count - 1
                Debug.Write(sl(r)(c) & " ")
            Next
            Debug.WriteLine("")
        Next
    End Sub
End Class