Python: Solving the Eight Queens Problem by Random Walk


1 The Eight Queens Problem

There is an 8-by-8 chessboard, and now you have to put eight queens on the chessboard, satisfying: for each queen, there is no other queen in the row, column, or two diagonals where it is.
Insert picture description here
It is stipulated that the initial state is [Empty Board], and the action is [Only put a queen on the leftmost column without a queen at a time]. In this way, at most one queen can appear in the same column of the chessboard.


2 program code

2.1 Procedure 1

Program 1: functions.py. It includes two functions: attacked_queens_pairs, display_board, which respectively complete the functions of [Calculating the number of pairs of mutually attacking queens of the sequence corresponding to the chessboard] and [Printing out the chessboard corresponding to the sequence]. as follows:

import numpy as np

def attacked_queens_pairs(seqs, pos):
    """
    计算序列对应棋盘的【互相攻击的皇后对数n】
    因为主程序只在最左面未放置皇后的列上放一个皇后,因此只需检查放置了皇后的前几列
    参数pos的作用是限制只统计前pos列【互相攻击的皇后对数n】
    并且只需要检查当前棋盘的皇后在各自的行和两条对角线上是否有其他皇后
    """
    a = np.array([0] * 81)  # 创建一个有81个0的一维数组
    a = a.reshape(9, 9)  # 改为9*9二维数组。为方便后面使用,只用后八行和后八列的8*8部分,作为一个空白棋盘
    n = 0  # 互相攻击的皇后对数初始化为0

    for i in range(1, pos+1):
        a[seqs[i - 1]][i] = 1  # 根据序列的前pos个数,按从第1列到pos列的顺序,在空白棋盘对应位置放一个皇后,生成当前序列对应的棋盘

    for i in range(1, pos+1): # 只统计前pos列【互相攻击的皇后对数n】
        for k in list(range(1, i)) + list(range(i + 1, 9)):  # 检查每个皇后各自所在的行上是否有其他皇后
            if a[seqs[i - 1]][k] == 1:  # 有其他皇后
                n += 1
        t1 = t2 = seqs[i - 1]
        for j in range(i - 1, 0, -1):  # 看左半段的两条对角线
            if t1 != 1:
                t1 -= 1
                if a[t1][j] == 1:
                    n += 1  # 正对角线左半段上还有其他皇后

            if t2 != 8:
                t2 += 1
                if a[t2][j] == 1:
                    n += 1  # 次对角线左半段上还有其他皇后

        t1 = t2 = seqs[i - 1]
        for j in range(i + 1, 9):  # 看右半段的两条对角线
            if t1 != 1:
                t1 -= 1
                if a[t1][j] == 1:
                    n += 1  # 正对角线右半段上还有其他皇后

            if t2 != 8:
                t2 += 1
                if a[t2][j] == 1:
                    n += 1  # 次对角线右半段上还有其他皇后
    return int(n/2)  # 返回n/2,因为A攻击B也意味着B攻击A,因此返回n的一半

def display_board(seqs):
    """
     显示序列对应的棋盘
    """
    board = np.array([0] * 81)  # 创建一个有81个0的一维数组
    board = board.reshape(9, 9)  # 改变为9*9二维数组,为了后面方便使用,只用后八行和后八列的8*8部分,作为一个空白棋盘

    for i in range(1, 9):
        board[seqs[i - 1]][i] = 1  # 根据序列,从第一列到最后一列的顺序,在对应位置放一个皇后,生成当前序列对应的棋盘
    print('对应棋盘如下:')
    for i in board[1:]:
        for j in i[1:]:
            print(j, ' ', end="")  # 有了end="",print就不会换行
        print()  # 输出完一行后再换行,这里不能是print('\n'),否则会换两行
    print('攻击的皇后对数为' + str(attacked_queens_pairs(seqs,8)))

This program has no output, but two functions are defined for the main program to call.

2.2 Procedure 2

Program 2: main.py. The main program, by calling two functions of program 2, completes the whole process of random walk to solve the eight queens problem. as follows:

import random
from functions import attacked_queens_pairs, display_board

seqs = [0] * 8 # 初始化序列
flag = 0 # 失败标志

for i in range(8):
    nums = list(range(1, 9)) # 从nums中选择在当前列放置皇后的位置
    if flag == 1: # 失败则结束循环
        break
    while True:
        try:
            temp = random.choice(nums) # 随机挑选,即随机游走
            seqs[i] = temp # 暂时将皇后放在当前列的第temp行
            nums.remove(temp) # 从nums移除已产生的随机数
            if attacked_queens_pairs(seqs, i+1) == 0: # 将皇后放在当前列的第temp行后,若已放置皇后的前i+1列中无互相攻击的皇后,则进行下一列位置的选择
                break
        except IndexError:
            print('本次计算失败,请重新运行本程序!')
            flag = 1 # 已失败
            break

if flag == 0:
    print('已找到解序列:' + str(seqs))
    display_board(seqs)

One output is as follows:

已找到解序列:[7, 1, 3, 8, 6, 4, 2, 5]
对应棋盘如下:
0  1  0  0  0  0  0  0  
0  0  0  0  0  0  1  0  
0  0  1  0  0  0  0  0  
0  0  0  0  0  1  0  0  
0  0  0  0  0  0  0  1  
0  0  0  0  1  0  0  0  
1  0  0  0  0  0  0  0  
0  0  0  1  0  0  0  0  
攻击的皇后对数为0

Another output is as follows:

本次计算失败,请重新运行本程序!

There are two types of output listed above, the first is to find the understanding sequence, the second is not found. Because the algorithm is to randomly place the queen at any position in the current column, if there is no queen in the first few columns of the queen that has been placed, the next column position is selected, so the process may reach [no suitable position to put] The state has to be declared a failure and can only be re-explored by re-running the program.


3 reviews

The main program is short and easy to understand, but you may need to run it several times to get the solution. If the failure is not your cause, just run it again.


END

Guess you like

Origin blog.csdn.net/qq_40061206/article/details/111729406