我正在为家庭作业做一个数独谜题解算器,但遇到了一些困难。现在的代码已经超越了解决方案,虽然它确实可以轻松解决问题,而对于更难的谜题,它会因为没有明显原因而陷入困境。我将不胜感激任何帮助。 (check_cell确定放置是否有效。)
一些代码:
def solve_helper(self, row, col):
# Try placing a number in each column of current row
board = self.the_board
if board[row][col] != 0:
?????
elif board[row][col] == 0:
for i in range(1,10):
print("Setting value at i with ") + str (i) + (" located at " ) + str(row) + str(col)
self.set_cell(row, col, i)
self.guesses = self.guesses + 1
if self.check_cell(row, col):
if self.solve_helper(row, col): return True
else:
self.set_cell(row, col, 0)
else:
return self.mover(row,col)
return False
def mover(self, row, col):
if col + 1 != 9:
return self.solve_helper(row, (col+1))
elif row + 1 != 9:
print "Moving to row" + str(row + 1)
return self.solve_helper((row+1),0)
else:
print "SOLUTION FOUND"
return True
答案 0 :(得分:4)
你遇到的麻烦是你的一些递归调用没有正确地返回结果,所以你的解决方案一旦被发现,就会被遗忘在递归堆栈的几个层次上。这是您需要的第一个修复,将return
添加到mover
中的递归调用中:
def mover(self, row, col):
if col + 1 != 9:
return self.solve_helper(row, (col+1)) # added return
elif row + 1 != 9:
print "Moving to row" + str(row + 1)
return self.solve_helper((row+1),0) # here too
else:
print "SOLUTION FOUND"
return True
在solve_helper
函数的特殊情况下,您还需要类似的东西,跳过预先解析的单元格。函数的结尾应该是:
else:
return self.mover(row, col) # added return
return False
修改强>
好的,我在代码中发现了一些问题。其中两个是解算器的逻辑问题,一个是显示问题,除了在解决过程中看起来很奇怪之外不会引起任何实际问题。
问题:
solve_helper
调用自己,而不是调用mover
。这使得它在移动之前需要额外的函数调用(尽管我认为它实际上可能不会破坏解算器)。solve_helper
将一个单元格设置为9,但是后退到(在某些后来的单元格无法解析之后),则9在进一步回溯之前不会重置为零。第一个问题很容易解决。只需将solve_helper
来电更改为mover
来电。这实际上就是你在问题中提出的原始代码中的内容。直接调用solve_helper
实际上并没有得到错误的结果(因为solve_helper
将第二次跳过已填写的单元格),但它会为递归的每个级别添加一个不必要的额外函数调用。 / p>
第二个问题稍微复杂一点,这就是你被卡在某些电路板上的地方。你需要做的是将self.set_cell(row, col, 0)
的行移出它当前所在的else
块。事实上,如果你愿意的话,你实际上可以完全将它移出循环外(因为它)只有当你在当前单元格的任何值都没有工作的情况下进行回溯时才真正有必要。以下是我认为这是for循环的最佳排列(也是移动return False
语句):
for i in range(1,10):
print("Setting value ") + str (i) + (" at " ) + str(row) + ", " + str(col)
self.set_cell(row, col, i)
self.guesses = self.guesses + 1
if self.check_cell(row, col):
if self.mover(row, col):
return True
print "Backtracking"
self.set_cell(row, col, 0)
return False
最后,修复显示问题需要进行两项更改。首先,摆脱set_cell
中的条件。您想要始终更新显示。接下来,在update_textfield
中,将delete
调用移到if
块之外,以便它始终发生(将insert
保留在if
下)。这使得将单元格设置为零将擦除先前的值,但不会使其显示实际的0字符(它将不显示任何内容)。
我认为应该这样做。请注意,您使用的算法仍然很慢。解决a board I found on the internet in a quick Google search需要122482次猜测并且超过5分钟,但它最终确实有效。其他电路板(特别是那些在前几个开放空间中需要8s或9s的电路板)可能需要更长时间。