【问题标题】:python sudoku puzzle? checking puzzle before and afterpython数独谜题?前后检查拼图
【发布时间】:2015-07-06 19:08:11
【问题描述】:

我为 Python 中非常简单的数独问题编写了一个数独求解器。它的工作原理是检查每个空方格,如果只有一个可能的数字是合法的,则将空方格替换为该数字。一旦它通过了整个拼图,如果仍然有超过 1 个空方格,它会再次调用新的拼图。我遇到问题的部分是我希望求解器在每次调用结束时检查谜题是否与调用开始时相同,如果它没有改变,这意味着所有剩余的空方块都有超过 1 个可能的值,因此求解器应返回 False 以指示求解器无法解决该特定难题。但是,当我尝试实现这一点时,Solver 只遍历了一次拼图并返回 False。这是我的代码:

def Solver(puzzle):

    oldpuzzle = puzzle
    count = 0

    for row in range(9):

        for col in range(9):
            if puzzle[row][col] == '0':
                possible, numpossible = getPossible(puzzle, row, col)

                if numpossible == 1:
                    puzzle[row][col] = possible[0]
        count += puzzle[row].count('0')

    if count > 0:
        if oldpuzzle == puzzle:
            return False
        else:
            Solver(puzzle)
    else:
        return True

getPossible() 函数返回一个可能值的列表和列表的长度。

这里是 main() 函数:

定义主():

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

if Solver(puzzle):
    print "Solved!"
    for row in puzzle:
        print ' '.join(row)
else:
    print "Failed!"

如何让程序正确比较 for 循环前后拼图的状态?

【问题讨论】:

  • 看起来getPossible() 可能会为numpossible 返回除1 以外的其他内容,这意味着puzzle 不会被修改。
  • 我不认为是这样,因为如果我在最后删除 if 语句并让 Solver 无限递归并且我每次都添加一个 print 语句,你可以看到它确实改变谜题。另外,我已经能够用这个程序解决一些简单的谜题,我只是遇到了更难的谜题

标签: python global-variables sudoku


【解决方案1】:

你的问题是那行:

oldpuzzle = puzzle

对puzzle 进行引用,称为oldpuzzel 不是副本,因此它们始终相同 - 您需要将puzzle 复制到@987654325 @ 与 copy.copy 或更多简单地设置一个标志:

def Solver(puzzle):
   Changed = False

在:

          if numpossible == 1:
               Changed = True

然后检查更改是否为False返回。

【讨论】:

  • 啊,我明白了,我在想可能是这样的,但我不确定如何检查。
【解决方案2】:

您将 puzzle 的引用设置为 oldpuzzle ,因此如果您对 puzzle 进行任何更改,它也会反映在 oldpuzzle 中。而puzzle 将始终等于oldpuzzle。

我认为您不需要将拼图设置为旧拼图(或者您需要在开始时保存完整的拼图)。

根据逻辑,0 单元格的数量永远不会增加,之前标记为非零的单元格永远不会被标记为0。

因此,您可以在开始时存储0s 的计数,然后在结束时检查0s 的计数是否已更改,如果更改则为好,否则返回 False。

示例代码-

def Solver(puzzle):

    oldcount = sum(1 for row in puzzle for cell in row if cell == '0')
    count = 0

    for row in range(9):

        for col in range(9):
            if puzzle[row][col] == '0':
                possible, numpossible = getPossible(puzzle, row, col)

                if numpossible == 1:
                    puzzle[row][col] = possible[0]
        count += puzzle[row].count('0')

    if count > 0:
        if oldcount == count:
            return False
        else:
            Solver(puzzle)
    else:
        return True

【讨论】:

    【解决方案3】:

    问题在于if oldpuzzle == puzzle 将始终为真,因为当oldpuzzle 被创建时,它不会成为拼图列表的副本,而是一个副本。这意味着如果您更改puzzle,那么oldpuzzle 也会更改。

    list1 = [1, 2, 3]
    list2 = list1
    list1[0] = 4
    print(list2)
    # this will print [4, 2, 3]
    

    使oldpuzzle 成为puzzle 的副本的一种方法是使用复制库。在这种情况下,需要制作puzzle 的深层副本,因为它是一个包含列表的列表。一种方法是使用deep copy function from the copy library。所以函数看起来像这样:

    from copy import deepcopy # at the top of the document
    
    def Solver(puzzle):
    
        oldpuzzle = deepcopy(puzzle)
        count = 0
    
        # ... and then the rest
    

    【讨论】:

      猜你喜欢
      • 2018-08-05
      • 1970-01-01
      • 1970-01-01
      • 2010-09-27
      • 1970-01-01
      • 2012-12-05
      • 1970-01-01
      相关资源
      最近更新 更多