如何根据回溯修复我的数独求解器

时间:2018-05-06 10:13:55

标签: python python-3.x recursion backtracking

我尝试使用python并基于回溯创建一个数独求解器算法,但它总是没有返回任何说数据不正确。

这是我的代码:

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

e = [0, 0]

def checkEmpty():
    for i in range(0, 9):
        for j in range(0, 9):
            if board[i][j] == 0:
                e[0] = i
                e[1] = j
                return True
    return False

def vLine(i, test):
    for j in range(9):
        if board[i][j] == test:
            return True
    return False

def vColumn(j, test):
    for i in range(9):
        if board[i][j] == test:
            return True
    return False

def vBlock(i, j, test):
    for I in range(3):
        for J in range(3):
            if(board[i+I][j + J] == test):
                return True
    return False

def validMove(i, j, test):
    if vColumn(j, test) == False and vBlock(i, j, test) == False and vLine(i, test) == False:
        return True
    else:
        return False

def solve():
    e = [0, 0]
    if checkEmpty() == False:
        return True
    i = e[0]
    j = e[1]
    for k in range(1, 10):
        if validMove(i, j, k) == True:
            board[i][j] = k
            if solve() == True:
                return True
            board[i][j] = 0
    return False

if solve():
    print("solved!")
else:
    print("No solution exists")

问题是这个if函数if validMove(i, j, k) == True:中的代码似乎永远不会被执行。 但是我无法在此功能中找到任何错误。

此外,我真的不知道我是否应该缩进,表达或保留此行board[i][j] = 0

1 个答案:

答案 0 :(得分:1)

您的块检查错误 - 如果您输入2,2,9,它将不会检查正确的块但是未对齐的内容。

def vBlock(i, j, test):
    for I in range(3):
        for J in range(3):
            if(board[i+I][j + J] == test):   # checks 2-5. 2-5 row&col
                return True
    return False

将其更改为

def vBlock(i, j, test):
    for I in range(3):
        for J in range(3):
            if(board[i//3+I][j//3 + J] == test): # this way it cecks the blocks correctly 
                # if you input 2,2,9 it checks 2//3+range == 0+0-3 
                return True
    return False

这不会改变整体错误,但至少会补偿一个错误。

您递归到solve()而不更改e - 当前选中的行/列表 - 您的solve()适用于本地变量{{1您的e更改全局 checkEmpty(),更改永远不会反映在e中。

修正:

solve()

即使您修复了这两个错误:

你需要能够丢弃更早的发现 - 例如。在开始时,一个空间可能可以被9,1,3,4填充 - 你首先检查1 - 宾果游戏 - 把它放进去,但是后来遇到的问题是这个区块中只能持有1的位置。现在1已经发出,你没有解决方案。

你需要计算所有可能的"首先填写所有def checkEmpty(): global e # explicitly use the global e for i in range(0, 9): for j in range(0, 9): if board[i][j] == 0: e[0] = i e[1] = j return True return False def solve(): global e # explicitly use the global e if checkEmpty() == False: return True i = e[0] j = e[1] print(e) for k in range(1, 10): if validMove(i, j, k) == True: board[i][j] = k if solve() == True: return True board[i][j] = 0 return False 的数字,然后填写只有一种可能性的数字,从相应的行/列/块0可能性列表中删除该数字并继续,直到所有数字都填入。

底线:使用可用的第一选择来解决它可能会以局部最小值结束,解决12个剩余零中的10个,然后你就被卡住了。