Python递归局部变量vs全局变量问题:数独求解器参数化改造失败求助
解决数独求解器的回溯终止问题
我来帮你搞定这个数独求解器的问题!你遇到的核心问题是递归回溯时没有在找到解后及时终止,导致已经填好的数字被后续的回溯步骤重新置为0,最终返回了未求解的初始状态。咱们一步步修改代码来解决这个问题:
第一步:移除全局变量,让函数更纯粹
原来的form_grid依赖全局变量grid,这不仅容易引发副作用,也不符合你想要接受局部参数的需求。咱们把它改成直接返回生成的数独网格:
def form_grid(puzzle_string): print('The Sudoku Problem') grid = [] for i in range(0, len(puzzle_string), 9): row = puzzle_string[i:i+9] temp = [int(block) for block in row] grid.append(temp) printGrid(grid) # 同步修改printGrid,让它接受grid参数 return grid
同时调整printGrid函数,让它依赖传入的参数而非全局变量:
def printGrid(grid): for row in grid: print(row)
第二步:修复递归终止逻辑
你的solve函数最大的问题是:不管递归调用是否找到解,都会执行grid[row][col] = 0的回溯操作。正确的逻辑应该是:
- 如果当前空格填入某个数字后,递归调用成功找到了解,就直接返回这个解,不再回溯
- 当遍历完所有空格(说明数独已解完),直接返回当前网格作为解
修改后的solve函数如下:
def possible(grid,row,col,digit): for i in range(0,9): if grid[row][i] == digit: return False for i in range(0,9): if grid[i][col] == digit: return False square_row = (row//3)*3 square_col = (col//3)*3 for i in range(0,3): for j in range(0,3): if grid[square_row+i][square_col+j] == digit: return False return True def solve(grid): for row in range(9): for col in range(9): if grid[row][col] == 0: for digit in range(1, 10): if possible(grid, row, col, digit): grid[row][col] = digit # 递归求解后检查是否得到有效解 result = solve(grid) if result is not None: return result # 找到解直接返回,跳过回溯 grid[row][col] = 0 # 仅当当前路径无解时才回溯 # 所有数字都尝试过仍无解,返回None标记当前路径失败 return None # 所有空格填满,返回最终解 return grid
第三步:调整主调用逻辑
原来的调用方式需要适配修改后的函数,我们先生成网格,再求解,最后打印结果:
puzzle_string = "004300209005009001070060043006002087190007400050083000600000105003508690042910300" sudoku_grid = form_grid(puzzle_string) solved_grid = solve(sudoku_grid) print("\nThe Solved Sudoku:") printGrid(solved_grid)
为什么这样修改有效?
- 当递归调用返回非
None值时,说明找到了可行解,我们直接向上传递这个解,避免后续回溯步骤破坏已填好的数字 - 移除全局变量后,函数逻辑更清晰,所有操作都依赖传入的参数,消除了全局状态带来的意外修改
- 明确的终止条件让递归在找到解后立即停止,不会继续执行无效的回溯操作
现在运行代码,就能得到正确的数独解啦!
内容的提问来源于stack exchange,提问作者gaming4 mining
相关产品推荐
相关产品推荐

