python八皇后代码 八皇后python递归_python

上图展示了一个8*8的国际象棋棋盘,八皇后问题就是指在该棋盘上放8个皇后,使得任意两个皇后不在同一行也不在同一列,还不在同一斜线(与水平线呈45。角)或反斜线(与水平线呈135。角)上。换句话说,就是避免任意两个皇后之间对杀,因为国际象棋中皇后可以任意横走、竖走、斜走,且不受长度限制。

按照递归三步曲可以解决这个问题。首先明确输入参数是index和points,前者表示当前要考虑的是第几个皇后(从0开始数),后者是一个列表(list),包含了之前的所有皇后的坐标。当前皇后的位置要避免与她们发生冲突。递归函数的返回值是一个bool值,以表明当前皇后是否有位置安放。

由于棋盘上每一行必定有一个皇后(否则必有一行含有至少两个皇后),所以,约定第i个皇后的行坐标就是ii = 012, ..., 7。我们的目标是确定每个皇后的列坐标。

递归边界显然是index=8,因为此时意味着所有皇后都已经安排就位,且列坐标都已经保存在points列表中了,所以直接返回True即可。

递归假设是当index参数变成index+1时,函数总能计算出该皇后能否安放成功。注意,本题index的初值是0,边界是8,所以应该使用index+1而不是通常的index-1作递归假设。

由于当前皇后的列坐标只有8个选择(即0~7),所以,可以依次尝试每一个可能的列坐标,如果该位置与所以points中的坐标都不冲突,则当前位置加入到points中,再用index+1和points进行递归调用。注意,如果递归调用返回的结果是False,意味着当前位置虽然与之前的皇后不冲突,但是与之后的皇后有冲突,所以应该尝试下一个可能位置。这里最重要的一件事是,在做新的尝试之前要把当前位置从points中删除。代码如下:

求解八皇后问题的Python程序


def solve_queens(index, points):
    if index == 8:
        return True

    for j in range(8):
        if ok(index, j, points): # 如果当前坐标与之前的皇后不冲突
            points.append(j)      # 插入列坐标
            if solve_queens(index+1, points): # 如果递归调用成功
                return True
            del points[-1]        # 删除刚插入的坐标数据
    return False

def ok(row, col, points): 
    # 判断坐标(row, col)是否与points里的坐标冲突
    for r, c in enumerate(points):
        if row == r or c == col or abs(row - r) == abs(col - c):
            return False
    return True

if __name__ == '__main__':
    points = []
    if solve_queens(0, points):
        # 打印8*8的棋盘
        for i, j in enumerate(points):
            print('- ' * j + '* ' + '- ' * (7 - j))
    else:
        print('无解')

程序运行的结果是:


* - - - - - - - 
- - - - * - - - 
- - - - - - - * 
- - - - - * - - 
- - * - - - - - 
- - - - - - * - 
- * - - - - - - 
- - - * - - - -