Python数独回溯问题解决了!但没有回答

Python数独回溯问题解决了!但没有回答,python,sudoku,Python,Sudoku,我已经正确地做了一个数独回溯解算器。但现在我需要得到解决方案,但出于某种原因,我一直得到原始的数独网格。数独问题有一个独特的解决方案 answer = [] count = 0 def solution(sudoku): global answer global count for y in range(9): for x in range(9): if sudoku[y][x] == 0: # Found an empty gri

我已经正确地做了一个数独回溯解算器。但现在我需要得到解决方案,但出于某种原因,我一直得到原始的数独网格。数独问题有一个独特的解决方案

answer = []
count = 0
def solution(sudoku):
    global answer
    global count
    for y in range(9):
        for x in range(9):
            if sudoku[y][x] == 0: # Found an empty grid
                for n in range(1, 10):
                    if isPossible(x, y, n, sudoku):
                        sudoku[y][x] = n
                        solution(sudoku) # Recursion here
                        sudoku[y][x] = 0 # If no solution then reset the grid and go back
                solved = False
                return sudoku
    print("hi look at me")
    if count == 0:
        answer = list(sudoku)
        print(answer)
        count += 1
    return sudoku

hi = solution(board)
print(answer)
print(hi)

在这个解决方案中,answer=list(sudoku)将把解决方案放在我的全局变量中。还请注意,我使用list()来确保当sudoku参数更改时,全局答案不会更改。我已确保这只发生一次。我理解这种回溯将导致原来的数独板,因为一旦解决了问题,该算法将设置数独[y][x]=0,从而有效地将解决方案归零。但是唯一的解决方案已经存储在answer中,当我尝试在函数之外打印answer时,我会得到原始的未解决的数独板。 那么为什么函数中的“答案”得到了正确的解决方案,而函数外部的“答案”给了我原始的电路板呢?answer=list(数独)只出现一次,list()给了我一个新的list对象,所以即使数独改变了,答案也不会改变,所以改变后怎么能改变呢?经过几个小时的调试,我真的被卡住了。如何将解决方案引入函数之外的内容

完整代码以防万一

board = [
    [0, 0, 0, 2, 6, 0, 7, 0, 1],
    [6, 8, 0, 0, 7, 0, 0, 9, 0],
    [1, 9, 0, 0, 0, 4, 5, 0, 0],
    [8, 2, 0, 1, 0, 0, 0, 4, 0],
    [0, 0, 4, 6, 0, 2, 9, 0, 0],
    [0, 5, 0, 0, 0, 3, 0, 2, 8],
    [0, 0, 9, 3, 0, 0, 0, 7, 4],
    [0, 4, 0, 0, 5, 0, 0, 3, 6],
    [7, 0, 3, 0, 1, 8, 0, 0, 0]
]

def isPossible(x, y, n, sudoku):
    if n in sudoku[y]: # Check if in row
        return False
    for i in range(0, 9):
        if n == sudoku[i][x]: # Check if in column
            return False
    y //= 3
    x //= 3
    for i in range(y*3, y*3 + 3): # Check if in squares
        for j in range(x*3, x*3 + 3):
            if n == sudoku[i][j]:
                return False
    return True

answer = []
count = 0
def solution(sudoku):
    global answer
    global count
    for y in range(9):
        for x in range(9):
            if sudoku[y][x] == 0: # Found an empty grid
                for n in range(1, 10):
                    if isPossible(x, y, n, sudoku):
                        sudoku[y][x] = n
                        solution(sudoku) # Recursion here
                        sudoku[y][x] = 0 # If no solution then reset the grid and go back
                return sudoku
    print("hi look at me")
    if count == 0:
        answer = list(sudoku)
        print(answer)
        count += 1
    return sudoku

hi = solution(board)
print(answer)
print(hi)

问题是你只是做了一个肤浅的董事会副本,所以它会随着更新而不断变化

浅拷贝:

answer = list(sudoku)
一种选择是使用:

在代码中将列表替换为deepcopy后,global将保留答案

今后的问题可能是:

  • 如何在不使用全局变量的情况下重写此代码,因为对于简单代码不鼓励使用全局变量
  • 这段代码真的是回溯还是彻底搜索

  • 问题是您有一个嵌套的列表结构,
    list(sudoku)
    只生成一个浅拷贝。内部列表仍然是被后续代码修改的对象。如果需要深度复制,可能需要使用
    copy
    模块的
    deepcopy
    功能:

    answer = copy.deepcopy(sudoku)
    
    虽然这可以解决您在成功解决方案上的回溯涂鸦的直接问题,但这并不能改变这样一个事实,即您的解算器将在您已经找到一个解决方案后继续尝试寻找更多的解决方案。为了避免这种情况,您可能需要更改代码,以便在成功与否时,返回的值会发出信号。如果只返回已解决的电路板,或者如果未找到,则返回
    None
    ,可以使用该选项在找到解决方案后立即结束搜索。作为奖励,您不再需要使用任何全局变量

    下面是它应该是什么样子:

    def solution(sudoku):                          # no more global variables needed
        for y in range(9):
            for x in range(9):
                if sudoku[y][x] == 0:
                    for n in range(1, 10):
                        if isPossible(x, y, n, sudoku):
                            sudoku[y][x] = n
                            result = solution(sudoku)
                            if result is not None: # check if the recursion was successful or not
                                return result      # and stop searching if it was!
                            sudoku[y][x] = 0
                    return None                    # signal failure
        return sudoku                              # signal success by returning the board
    
    def solution(sudoku):                          # no more global variables needed
        for y in range(9):
            for x in range(9):
                if sudoku[y][x] == 0:
                    for n in range(1, 10):
                        if isPossible(x, y, n, sudoku):
                            sudoku[y][x] = n
                            result = solution(sudoku)
                            if result is not None: # check if the recursion was successful or not
                                return result      # and stop searching if it was!
                            sudoku[y][x] = 0
                    return None                    # signal failure
        return sudoku                              # signal success by returning the board