Excel 在VBA中将单元格地址添加到动态数组

Excel 在VBA中将单元格地址添加到动态数组,excel,vba,loops,recursion,sudoku,Excel,Vba,Loops,Recursion,Sudoku,我有一个脚本,其中我循环通过一个9x9数组,如果一个单元格包含一个0,它将更改该数字,以便该数字在行、列和其中的一个3x3正方形中是唯一的。每次发现并更改一个这样的单元格时,我都想将该单元格位置添加到数组中,这样,如果替换0的数字不是最佳的,我就可以轻松地返回到更改过的单元格并尝试新的数字。我该怎么做 下面是我迄今为止编写的代码,我用三个撇号(“”)表示我的“伪代码” 这进一步解释了我想要它做什么 Check函数根据我提到的条件(数独规则)确定1到9之间的数字是否可以放在当前单元格中 它处理递归

我有一个脚本,其中我循环通过一个9x9数组,如果一个单元格包含一个0,它将更改该数字,以便该数字在行、列和其中的一个3x3正方形中是唯一的。每次发现并更改一个这样的单元格时,我都想将该单元格位置添加到数组中,这样,如果替换0的数字不是最佳的,我就可以轻松地返回到更改过的单元格并尝试新的数字。我该怎么做

下面是我迄今为止编写的代码,我用三个撇号(“”)表示我的“伪代码” 这进一步解释了我想要它做什么

Check函数根据我提到的条件(数独规则)确定1到9之间的数字是否可以放在当前单元格中

它处理递归,所以如果需要更清楚地解释,请告诉我

Sub Solve()

Dim x As Integer, y As Integer, row As Integer, col As Integer, rw As Integer, cl As Integer, a As Worksheet, puzzle As Range, n As Integer, num As Integer
Dim startcol As Integer, startrow As Integer, check1 As Boolean, check2 As Boolean, check3 As Boolean, r As Integer, c As Integer, x1 As Double, y1 As Double, z As Boolean
Dim fillednums(1 To 9, 1 To 9) As String

Set a = ThisWorkbook.Worksheets("Puzzle")
Set puzzle = a.Range(Cells(4, 4), Cells(12, 12))


startcol = 4
startrow = 4

For row = startrow To startrow + 8
    For col = startcol To startcol + 8
        If a.Cells(row, col).Value = 0 Then
            For num = 1 To 9
                If Check(col, row, num) = True Then
                a.Cells(row, col).Value = num
                    '''Add cell address to array
                Call Solve
                ElseIf num = 9 And a.Cells(row, col).Value = 0 Then
                    '''Go back one index of the array (fillednums) and use check() function for numbers greater than the one in the cell and up to 9
                    '''If that still doesnt work, go back to cell before this one that was changed and check again (recursively)
                    '''Call Solve() again to try new number
                'a.Cells(row, col).Value = 0
                End If
            Next num
        End If
    Next col
Next row
            
            
End Sub 

对于递归,可以从拼图中的第一个空单元格开始。对于每个可能的值,将下一个空闲单元传递给子单元以检查解决方案。这个过程一直持续到找到解决方案为止(假设问题是有效的)

主Solve函数必须返回True或False,以便父函数知道是否找到了解决方案

Function GetNextCell(cc)  ' get next free cell in puzzle
   GetNextCell = Cells(cc.Row, cc.Column+1) ' move next column
   If (GetNextCell.Column = 13) Then  ' go to next row
      GetNextCell = Cells(cc.Row+1, 4)
   End If
   If GetNextCell.Row = 13 Then ' off the grid
      GetNextCell = Nothing  ' no more cells
   End If
   If GetNextCell <> Nothing And GetNextCell.Value <> "" Then
      GetNextCell GetNextCell(GetNextCell) ' skip filled cells
   End If    

Function Solve(cc) as Boolean    
    ' we only care about our single cell
    For num = 1 to 9 ' all possible values for this cell
        cc.Value = num
        If Check(cc.column, cc.row, num) Then  ' so far so good
            NextCell = GetNextCell(cc)  ' get next cell for child to process
            if NextCell = Nothing Then  ' no more cells and current values work
                    Solve = True  ' puzzle solved
                    Exit Function
            Else  ' call child with next cell
                If Solve(NextCell) Then  ' did child solve puzzle ?
                    Solve = True  ' puzzle solved
                    Exit Function
                End If
                ' Child could not find solution based on current values
            End If
        End If
    Next
    
  cc.Value = ""    ' No solution found at this point, must revert back to parent to try next value
  Solve = False  ' no solution found    
End Function

Solve(GetNextCell(Cells(4,3)))  ' first empty cell in block, must return true
函数GetNextCell(cc)'获取拼图中的下一个空闲单元
GetNextCell=单元格(cc.Row,cc.Column+1)'移动下一列
如果(GetNextCell.Column=13),则“转到下一行”
GetNextCell=单元格(抄送行+1,4)
如果结束
如果GetNextCell.Row=13,则“脱离网格”
GetNextCell=Nothing'没有更多单元格
如果结束
如果GetNextCell为Nothing且GetNextCell.Value为“”,则
GetNextCell GetNextCell(GetNextCell)'跳过填充的单元格
如果结束
函数求解(cc)为布尔型
“我们只关心我们的单个细胞
对于num=1到9',此单元格的所有可能值
cc.Value=num
如果选中(cc.column、cc.row、num),则“到目前为止一切正常”
NextCell=GetNextCell(cc)'获取子进程的下一个单元格
如果NextCell=Nothing,则“不再有单元格和当前值工作”
解答=真“难题已解决”
退出功能
Else用下一个单元格呼叫孩子
如果解决(NextCell),那么“孩子解决了这个难题吗?”?
解答=真“难题已解决”
退出功能
如果结束
'子项找不到基于当前值的解决方案
如果结束
如果结束
下一个
cc.Value=“”此时未找到解决方案,必须还原回父级以尝试下一个值
Solve=False“未找到解决方案”
端函数
Solve(GetNextCell(Cells(4,3)))块中的第一个空单元格必须返回true

在递归中,您需要将当前板传递到下一级。在这里,您尝试为所有级别使用单个excel网格,这充其量也很困难(如果不是不可能的话)。您需要将电路板状态保存在内存中,然后将更新后的状态传递到下一个级别:
调用Solve(CurrentBoard)
如果只进行一次更改,则新电路板将传递到更深的级别。这会一直持续到电路板正确或更新失败,在这种情况下,它会返回一个级别以尝试不同的数字\位置。我考虑了更多…你可以使用单个网格来保存所有级别。就像我建议的那样?