简体   繁体   中英

Python Sudoko Solver - Backtracking

I have to devise a program to solve NxN sudoku using backtracking, N can be 1,4,9,16.

I have managed to build a program that will solve 4x4 boards but for 9x9 boards and above I am stuck as to how to search for grids.

My code so far is below.

How would one approach searching the square(n) x square(n) grids?

def is_solved(board, n):
    # If board is not solved, return False.
    for x in range(n):  # vertical coordinate
        for y in range(n):  # horizontal coordinate
            if board[x][y] == 0:  # zero representing an empty cell
                return False
    return True  # else, the board is filled and solved, return True


def find_possibilities(board, i, j, n):
    # Finds all possible numbers of an entry
    possible_entries = {}

    # initialize a dictionary with possible numbers to fill board
    for num in range(1, n+1):
        possible_entries[num] = 0

    # horizontal
    for y in range(0, n):
        if not board[i][y] == 0:  # current position is not 0, not empty
            possible_entries[board[i][y]] = 1

    # vertical
    for x in range(0, n):
        if not board[x][j] == 0:
            possible_entries[board[x][j]] = 1

    for num in range(1, n+1):
        if possible_entries[num] == 0:
            possible_entries[num] = num
        else:
            possible_entries[num] = 0

    return possible_entries


def sudoku_solver(board):
    n = len(board)
    i = 0
    j = 0

    if is_solved(board, n):
        print(board)
        return True
    else:
        # find the first empty cell
        for x in range(0, n):
            for y in range(0, n):
                if board[x][y] == 0:
                    i = x
                    j = y
                    break

        # find all possibilities to fill board[i][j]
        possibilities = find_possibilities(board, i, j, n)

        for x in range(1, n + 1):
            if not possibilities[x] == 0:
                board[i][j] = possibilities[x]
                return sudoku_solver(board)
        # backtracking step
        board[i][j] = 0  # resets the cell to an empty cell


def solve_sudoku(board):
    if sudoku_solver(board):
        return True
    else:
        return False

It seems to me that you would want to add a third check through that covers the grid that the current cell is in. For any of the board sizes, we might assume that the grid would be the square root of the board size.

Then each cell would be in a grid that has a minimum column number of int(i / math.sqrt(n)) and a maximum of int(column_minimum + i % math.sqrt(n)) and minimum row numbers of int(j / math.sqrt(n)) and maximum of int(row_minimum + j % math.sqrt(n)) .

Iterating through rows and columns and processing in the same way as your row and column checks should allow that final check to be made.

This solution works:

# surrounding grid
gridsize = int(math.sqrt(n))
minrow = i -  int(i%gridsize)
maxrow = minrow + gridsize - 1
mincol = j - int(j%gridsize)
maxcol = mincol + gridsize - 1
for x in range(minrow, maxrow+1):
    for y in range(mincol, maxcol+1):
        if not board[x][y] == 1:
            possible_entries[board[x][y]] = 1 

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