简体   繁体   English

Python Sudoko求解器-回溯

[英]Python Sudoko Solver - Backtracking

I have to devise a program to solve NxN sudoku using backtracking, N can be 1,4,9,16. 我必须设计一个使用回溯法解决NxN数独的程序,N可以是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. 我设法建立了一个解决4x4电路板的程序,但对于9x9电路板及以上,我对于如何搜索网格仍然很困惑。

My code so far is below. 到目前为止,我的代码如下。

How would one approach searching the square(n) x square(n) grids? 一种方法如何搜索平方(n)x平方(n)网格?

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)) . 然后,每个单元格将位于一个网格中,该网格的最小列数为int(i / math.sqrt(n)) ,最大列数为int(column_minimum + i % math.sqrt(n)) ,最小列数为int(j / math.sqrt(n))和最大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 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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