简体   繁体   中英

How to fix my sudoku solver based on backtracking

I tried to create a sudoku solver algorithm using python and based on backtracking but it always return nothing saying that the sudoku is incorrect.

Here is my code:

 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")

The problem is that the code inside this if function if validMove(i, j, k) == True: seems to never be executed. However I was unable to find any error in this function.

In addition, I don't really know whether I should indent, dedent or keep this line board[i][j] = 0 here.

Your block checker is wrong - if you input 2,2,9 it will not check the correct block but something misaligned.

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

Change it to

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

This wont change the overall error, but compensate for one error at least.


You recurse into solve() without ever changing the e -list of row/col currently checked - your solve() works on a local variable e - your checkEmpty() changes the global e , the changes are never reflected inside solve() .

Fix:

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

Even if you fix those 2 errors:

You need to be able to discard ealier finds- fe at start one space might be able to be filled by 9,1,3,4 - you check 1 first - bingo - put it in, but run into problems later for the spot in this block that was only ever able to hold 1. Now 1 is given away and you have no solution.

You need to calculate "all possible" numbers for all of your 0 first, then fill in those with only 1 possibility, removing that number from the corresponding row/column/block 0 possibilitie lists and continue until all are filled in.

Bottom line: solving it using the first choice available might end you in a local minimun that solves 10 of 12 leftover zeros, and then you are stuck.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM