我做了一个数独求解器,如果任何给定的单元格只有一个选项来填充它给定的行/列/组,它就可以工作。 但是如果选项高于1,那么这个求解器不起作用,所以我试图制作一个递归求解器,它为每个单元格中的每个可能的选项轮流,我尝试了几种方法来分支选择,但我可以'找到一种方法让它回到状态并采取下一个选项。我的程序似乎总是走同样的道路。
我的代码如下:
首先找到每个单元格的每个可能的移动
然后按最少的选项对它们进行排序。
如果给定单元格中有长度为1的选项,则填充并重新启动,
如果没有,它将遍历选项
理想情况下,它会一直持续到疲惫状态,然后回到最后选择的选项并接受另一个选项。但它没有这样做,它正在重演。
经过一番研究后,我发现我尝试做的事情叫做深度优先搜索,
我找到了this DFS的实现,但是我无法在我的程序中实现它。
这是我的尝试:
def best_moves():
# get_possible_moves() returns a list of all the available moves for every cell
# sorting it and taking the first element will get the one
# that has the least amount options
return [move for move in sorted(board.get_possible_moves())[0]]
def get_next_nodes(move):
board.make_this_move(move)
return best_moves()
def dfs(graph, start):
visited, stack = set(), [start]
while stack:
vertex = stack.pop()
if vertex not in visited:
visited.add(vertex)
nodes = []
for move in graph[vertex]:
nodes.extend(get_next_nodes(move))
nodes = [node for node in nodes if node not in visited]
stack.extend(nodes)
return visited
b = Board(puzzle_hard)
b.create_board()
graph = {'root':best_moves()}
dfs(graph,'root')
它给出了:
Traceback (most recent call last):
File "C:\Users\user\Documents\python\sudoku\sudoku_solver.py", line 171, in <module>
dfs(graph,'root')
File "C:\Users\user\Documents\python\sudoku\sudoku_solver.py", line 162, in dfs
for move in graph[vertex]:
KeyError: <__main__.PossibleMove instance at 0x0223DB48>
PossibleMove是我为处理给定单元格的可能移动而创建的类。 我可以尝试将其添加到图表中,但为了做到这一点,我需要再次搜索它,我不能这样做,因为我在DFS的中间。
如何预先在图中没有所有节点的情况下实现DSF。
答案 0 :(得分:0)
几天后,我设法让它发挥作用。
遵循this article中的一些指南(主要是将拼图用作图表节点的字符串)
这个程序的关键要素是游戏状态,董事会在移动之前,我试图使用非常复杂的方法存储游戏状态,但所有这些都需要一些我不知道的知识(然而)。在这种方法中,我现在将游戏状态变为字符串: 例如:
53..7....6..195....98....6.8...6...34..8.3..17...2...6.6....28....419..5....8..79
与:
相同[[5, 3, 4, 6, 7, 8, 9, 1, 2],
[6, 7, 2, 1, 9, 5, 3, 4, 8],
[1, 9, 8, 3, 4, 2, 5, 6, 7],
[8, 5, 9, 7, 6, 1, 4, 2, 3],
[4, 2, 6, 8, 5, 3, 7, 9, 1],
[7, 1, 3, 9, 2, 4, 8, 5, 6],
[9, 6, 1, 5, 3, 7, 2, 8, 4],
[2, 8, 7, 4, 1, 9, 6, 3, 5],
[3, 4, 5, 2, 8, 6, 1, 7, 9]]
每当我遇到一条存储游戏状态的路径时,请尝试此路径,如果找到另一条路径,我会将其添加到之前的状态。
因此,将来它会将集合中的那些添加为新节点,并找到它们可能的路径。
更简单的例子是:
'123456..'
可能导致:
'123456789'
'123456798'
所以图表表示为:
graph = {'123456..':set(['123456789','123456798'])}
代码是:
def possible_moves(puzzle):
puzzle = string_to_puzzle((puzzle) # convert the puzzle to a better format(array of 9x9)
moves = get_next_moves(puzzle) # get the possible moves for the puzzle
results = set()
if moves: # if no moves mean, the puzzle is filled or the choices were wrong
for move in moves:
this_puzzle = copy(puzzle)
this_puzzle[move.row][move.column] = move.value
results.add(puzzle_to_string(this_puzzle)) # convert it back to string and add it to possible moves.
return results
def dfs(graph, start):
visited, stack = set(), [start]
while stack:
vertex = stack.pop()
if win(vertex): # check if the current node is the winner
return string_to_array(vertex) # returns the puzzle compleded in a 9x9 array
if vertex not in visited:
visited.add(vertex)
graph[vertex] = possible_moves(vertex) # finds the next game states for the vertex
stack.extend(graph[vertex] - visited)
return "no possible solution"