回溯法求解八皇后问题
文件名 | 定位 | 作用 |
main.py | 主模块 | 程序入口,利用回溯法求解八皇后问题 |
draw.py | 绘图模块 | 将8皇后问题结果可视化 |
main.py:主模块
# -*- coding:utf-8 -*-
# 冲突检查
# 在定义state时,采用state来标志每个皇后的位置,
# 其中索引用来表示横坐标,基对应的值表示纵坐标,
# 例如: state[0]=3,表示该皇后位于第1行的第4列上
def conflict(state, next_y):
next_x = len(state)
for i in range(next_x):
# 如果下一个皇后的位置与当前的皇后位置相邻(包括上下,左右)或在同一对角线上,
# 则说明有冲突,需要重新摆放
if abs(state[i] - next_y) in (0, next_x - i):
return True
return False
# 生成器
# 产生每一个皇后的位置,
# 并用递归来查找下一个皇后的位置。
def queens(num, state=()):
for pos in range(num):
if not conflict(state, pos):
# 产生当前皇后的位置信息
if len(state) == num - 1:
yield (pos,)
# 把当前皇后的位置信息,添加到状态列表里,
# 并传递给下一皇后。
else:
for result in queens(num, state + (pos,)):
yield (pos,) + result
if __name__ == "__main__":
s = int(input('请输入s:'))
output = list(queens(s))
n = len(output)
print('%d皇后问题,共有%d个解决方案' % (s, n))
print('解决方案为:')
for i in output:
print(i)
draw.py:绘图模块
# -*- coding:utf-8 -*-
import matplotlib.pyplot as plt
def show(solution):
n = len(solution)
# 设置x范围
plt.xlim(0, n)
# 设置y范围
plt.ylim(0, n)
# 画棋盘
for j in range(n):
for k in range(n):
if (j + k) % 2 == 0:
# 画灰色方块
plt.scatter(j + 0.5, k + 0.5, marker='s', s=1000, c='#d18b47')
else:
# 画橙色方块
plt.scatter(j + 0.5, k + 0.5, marker='s', s=1000, c='#ffce9e')
# 画皇后
i = 0
for pos in solution:
plt.scatter(pos + 0.5, i + 0.5, marker='^', s=500, c='#ffffff')
i += 1
# 关闭坐标轴
plt.axis('off')
plt.show()
if __name__ == '__main__':
from main import queens
import random
output = list(queens(8))
one_solution = random.choice(output)
print('绘图:')
print(one_solution)
show(one_solution)
main.py运行结果:
draw.py运行结果:
draw.py绘图结果:
- 上图为8皇后问题解决方案(5, 0, 4, 1, 7, 2, 6, 3)的绘图结果;
- 灰色和橙色组成了八皇后的棋盘;
- 皇后用白色正三角形表示。