大家好!本文为大家提供了一种基于搜索求N皇后问题所有解的个数的方法,并用PyQt5实现了一个简单的交互界面。
import sys
import random
import time
from PyQt5.QtWidgets import QApplication,QWidget,QPushButton,QHBoxLayout,QVBoxLayout,QMessageBox,QMainWindow,QCheckBox,QLabel,QLineEdit,QComboBox,QDesktopWidget
from PyQt5.QtGui import QPainter, QColor, QPen
from PyQt5.QtCore import Qt
class Window(QWidget):
def __init__(self):
super().__init__()
self.initUI()
self.Num_Queens=4
self.If_Draw=1
self.Draw_Flag=0
self.all_results=dict()
self.one_result=[]
def initUI(self):
#选择皇后数量
self.label_numberbox=QLabel('皇后数量:' , self)
NumberBox=QComboBox(self)
NumberBox.addItem('4')
NumberBox.addItem('6')
NumberBox.addItem('8')
NumberBox.addItem('10')
NumberBox.addItem('12')
NumberBox.addItem('14')
NumberBox.addItem('16')
self.label_numberbox.move(440,20)
self.label_numberbox.resize(60,20)
NumberBox.move(500,20)
NumberBox.resize(40,20)
NumberBox.activated.connect(self.Input_Num_Queens)
#是否绘图
self.label_ifdraw=QLabel('是否绘图:',self)
Ifdraw=QComboBox(self)
Ifdraw.addItem('是')
Ifdraw.addItem('否')
self.label_ifdraw.move(440,60)
self.label_ifdraw.resize(60, 20)
Ifdraw.move(500,60)
Ifdraw.resize(40, 20)
Ifdraw.activated.connect(self.Input_If_Draw)
#耗时
self.label_time1=QLabel('搜索耗时:',self)
self.label_time2 = QLabel(self)
self.label_time1.move(440, 100)
self.label_time2.move(500, 100)
#开始与停止搜索
StartButton=QPushButton('开始搜索',self)
StopButton=QPushButton('停止搜索',self)
StartButton.clicked.connect(self.Start)
StopButton.clicked.connect(self.Stop)
StartButton.move(420,140)
StopButton.move(510,140)
# 随机输出一种解
OutputButton = QPushButton('随机输出一种解', self)
OutputButton.pressed.connect(self.Output_Solution)
OutputButton.move(420,180)
OutputButton.resize(165,20)
self.setGeometry(150,150,600,410)
self.setWindowTitle('N-皇后问题')
self.show()
def paintEvent(self, e):
if self.Draw_Flag == 0:
self.Draw_Board()
else:
self.Draw_Chess()
def Input_Num_Queens(self,Num):
self.Num_Queens=(Num+2)*2
self.If_Draw = 1
self.Draw_Flag = 0
self.all_results = dict()
self.one_result = []
self.label_time2.setText('')
self.update()
def Input_If_Draw(self,Num):
self.If_Draw=1 if Num==0 else 0
def Start(self):
self.Draw_Flag = 1
def Get_All_Results(num):
all_results = []
current_board = []
Get_All_Results_Impl(current_board,all_results)
return all_results
def Get_All_Results_Impl(current_board, all_results):
NextX = len(current_board)
for NextY in range(self.Num_Queens):
Conflict = False
#遍历下一行可摆的位置
for i in range(NextX):
if NextY == current_board[i] or NextY == current_board[i] + NextX - i or NextY == current_board[i] - NextX + i:
Conflict = True
break
#判断是否与之前的棋子冲突
if Conflict == False:
new_board = current_board.copy()
new_board.append(NextY)
if len(new_board) == self.Num_Queens:
all_results.append(new_board.copy())
if self.If_Draw == 1:
self.one_result=new_board.copy()
self.repaint()
else:
Get_All_Results_Impl(new_board, all_results)
time_begin=time.time()
self.all_results=Get_All_Results(self.Num_Queens)
time_end=time.time()
Time_cost = round(time_end - time_begin , 5)
Time_cost = str(Time_cost)
self.label_time2.setText((Time_cost)+'s')
self.label_time2.adjustSize()
Num_results=len(self.all_results)
self.Draw_Flag = 0
QMessageBox.information(self, '结果', '共有'+str(Num_results)+'种解')
def Stop(self):
self.close()
def Draw_Board(self):
qp = QPainter()
qp.begin(self)
pen = QPen(Qt.black, 2, Qt.SolidLine)
qp.setPen(pen)
qp.drawLine(5, 5, 405, 5)
qp.drawLine(5, 5, 5, 405)
qp.drawLine(5, 405, 405, 405)
qp.drawLine(405, 5, 405, 405)
delta=int(400/self.Num_Queens)
k=1
A=1
for i in range(self.Num_Queens):
for j in range(self.Num_Queens):
if k % 2 == A % 2:
qp.setBrush(QColor(128,128,128))
qp.drawRect(int(5 + i * delta), int(5 + j * delta), delta, delta)
else:
qp.setBrush(QColor(255, 255, 255))
qp.drawRect(int(5 + i * delta), int(5 + j * delta), delta, delta)
k+=1
A+=1
qp.end()
def Draw_Chess(self):
delta=int(400/self.Num_Queens)
qp=QPainter()
qp.begin(self)
pen = QPen(Qt.black, 2, Qt.SolidLine)
qp.setPen(pen)
qp.drawLine(5, 5, 405, 5)
qp.drawLine(5, 5, 5, 405)
qp.drawLine(5, 405, 405, 405)
qp.drawLine(405, 5, 405, 405)
k = 1
A = 1
for i in range(self.Num_Queens):
for j in range(self.Num_Queens):
if k % 2 == A % 2:
qp.setBrush(QColor(128, 128, 128))
qp.drawRect(int(5 + i * delta), int(5 + j * delta), delta, delta)
else:
qp.setBrush(QColor(255, 255, 255))
qp.drawRect(int(5 + i * delta), int(5 + j * delta), delta, delta)
k += 1
A += 1
qp.setBrush(QColor(255,0,0))
for i in range(self.Num_Queens):
x=5+delta*i
y=5+delta*(self.one_result[i])
A=int(x+0.1*delta)
B=int(y+0.1*delta)
C=int(0.8*delta)
D=int(0.8*delta)
qp.drawEllipse(A,B,C,D)
qp.end()
def Output_Solution(self):
if len(self.all_results)==0:
QMessageBox.information(self, '提示', '尚未开始搜索')
else:
self.Draw_Flag = 1
t = int(len(self.all_results)*random.random())
self.one_result = self.all_results[t]
self.repaint()
def closeEvent(self, event):
reply = QMessageBox.question(self, '提示',
"确定退出?", QMessageBox.Yes |
QMessageBox.No, QMessageBox.No)
if reply == QMessageBox.Yes:
event.accept()
else:
event.ignore()
if __name__ == '__main__':
app = QApplication(sys.argv)
w = Window()
sys.exit(app.exec_())