Python中的N-Queens程序

Posted

技术标签:

【中文标题】Python中的N-Queens程序【英文标题】:N-Queens program in Python 【发布时间】:2020-04-07 16:58:11 【问题描述】:

N 皇后是在 N×N 棋盘上放置 N 个棋后的问题,这样两个皇后就不会互相攻击。我之前已经解决了这个程序,但正在尝试重新编写我的代码以反映我用来制作数独求解器的代码。我似乎找不到逻辑错误,但是当我运行代码时,什么也没有打印。我的程序附在下面,如果有人能找到我的错误,那将非常有帮助!

import numpy as np

def main():
    global n
    n = input("Enter N")
    n = int(n)
    global board
    board = np.zeros((n,n), dtype=int)
    solve_board()

def solve_board():

    for row in range(n):
        for col in range(n):
            if board[row][col] == 0: #no queen
                if (is_valid (board,row,col,n)):
                    board[row][col] = 1 #Assigning 1 for queen
                    solve_board()
                    board[row][col] = 0
            return False


    print('-'*n)
    for row in board:
        for col in row:
            if col == 1:
                print ("Q", end = " ")
            else:
                print (".", end = " ")


def is_valid(board,i,j,n):

    if 1 in board[i]: #Checking row
        return False

    for row in range(0,i): #Checking column
        if (board[row][j]==1):
            return False
    x,y = i,j

    while (x>=0 and y>=0): #left diagonal
         if (board[x][y]==1):
             return False
         x-=1
         y-=1

    x,y = i,j
    while (x>=0 and y<n): #right diagonal
         if (board[x][y]==1):
             return False
         x-=1
         y+=1
    return True

if __name__ == "__main__":
    main()

这就是我之前解决此代码的方法,并按照以下方式更改了solve_board。

def solve_board(row):

    if(row == n):
        print('-'*n)
        for row in board:
            for col in row:
                if col == 1:
                    print ("Q", end = " ")
                else:
                    print (".", end = " ")
            print("")


    else:
        for col in range(n):
            if (is_valid (board,row,col,n)):
                board[row][col]=1
                solve_board(row+1)
                board[row][col] = 0
        return False

这是我当前代码的灵感来源,我设计的一个数独求解器,我使用了 2 个嵌套的 for 循环;一个用于行,一个用于列。基于此,我将原始 n-queens 代码中的 solve_board(row) 更改为没有参数的当前函数。此数独代码完美运行。

def solve_board():

        global board
        for rowno in range(9):
            #print ("row",rowno)
            for colno in range(9):
                #print("col",colno)
                if board[rowno][colno] == 0:
                    for i in range(1,10):
                        #print(i)
                        if (is_valid(board,rowno,colno,i)):
                            board[rowno][colno]=i
                            solve_board()
                            board[rowno][colno]=0
                    return False

        print (np.matrix(board))

我认为问题可能在于,在 N-Queens 问题中,棋盘没有填满,即仍然有 0,而对于数独来说,整个棋盘都填满了,因此当 ''if board[row] [col] == 0'' 被证明为 false 退出循环并打印。在 N-Queens 问题中,由于零总是存在的,因此它成为一个问题。

【问题讨论】:

return False statemnet in solve_board() 方法会导致问题,如果条件失败,程序将因return 语句而停止执行 如果我删除返回 False,那么它不会跟随 n 并返回一个长的、不正确的模式。你有什么建议吗?如何更改退货声明? 如果条件失败,您要执行的语句从下一个row或下一个column开始 如果条件失败,并且值被重置(board[row][col] = 0),它应该尽可能尝试同一行中的下一列,否则如果行尾移动到下一行,这就是我将列嵌套在行中的原因。我的回答有意义吗?非常感谢。 如果您可以查看我的最新编辑,可能会更清楚吗?谢谢! 【参考方案1】:

试试这个

import numpy as np

def main():
    global n
    n = input("Enter N: ")
    n = int(n)
    global board
    board = np.zeros((n,n), dtype=int)
    solve_board()

def print_board():
    print('-'*n)
    for row in board:
        for col in row:
            if col == 1:
                print ("Q", end = " ")
            else:
                print (".", end = " ")
        print()


def is_valid(board,i,j,n):

    if 1 in board[i]: #Checking row
        return False

    for row in range(0, n): #Checking column
        if (board[row][j]==1):
            return False

    for k in range(0,n):
        for l in range(0,n):
            if (k+l==i+j) or (k-l==i-j):
                if board[k][l]==1:
                    return False
    return True

def solve_board():
    for row in range(n):
        for col in range(n):
            if board[row][col] == 0: #no queen
                if (is_valid (board,row,col,n)):
                    board[row][col] = 1 #Assigning 1 for queen
                    if np.count_nonzero(board) == n:
                      print_board()
                      return True
                    solve_board()
                    board[row][col] = 0
            else:
                  return False

if __name__ == "__main__":
    main()

【讨论】:

我尝试这样做无济于事,因为代码的目的是回溯并删除递归调用,而 board[row][col] = 0 消除了这一点。还有其他方法吗?我之前在 for 循环中成功完成了递归,我将编辑我的查询并添加该 sn-p。也许如果你看到了,它会更容易?谢谢。 虽然我真的很感谢你的回答(但是它仍然没有给我想要的输出),但我不只是想解决这个问题,我已经在另一个 nqueen 程序中做到了附在上面,我想了解为什么我的递归和回溯在这个程序中不起作用。您的解决方案不使用递归或回溯,如果您能帮助我而不是简单的解决方案,我会很高兴。谢谢!

以上是关于Python中的N-Queens程序的主要内容,如果未能解决你的问题,请参考以下文章

leetcode--51. N-Queens

N-Queens 谜题,但包含所有棋子

解决 n-queen 谜题

Python中的N-Queens程序

LeetCode in Python 51. N-Queens

解决N-Queens问题......我们能走多远?