python實(shí)現(xiàn)人機(jī)五子棋
本文實(shí)例為大家分享了python實(shí)現(xiàn)人機(jī)五子棋的具體代碼,供大家參考,具體內(nèi)容如下
圖形界面引用PyQt5,還有socket通信。可以局域網(wǎng)對(duì)戰(zhàn),可以人機(jī)對(duì)戰(zhàn),應(yīng)該存在一些小的bug,但是還沒有找出來。希望讀者可以找到
下面附幾張運(yùn)行的截圖:



五子棋.py代碼:
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
import sys
import MyButton
import DoublePlayerGame
import SinglePlayerGame
from NetConfig import *
import NetPlayerGame
class Mainwindow(QWidget):
def __init__(self,parent = None):
super().__init__(parent)
self.resize(760,650)
self.setWindowTitle("我的五子棋")
#設(shè)置窗口圖標(biāo)
self.setWindowIcon(QIcon("source/icon.ico"))
#設(shè)置背景圖片
p = QPalette(self.palette())#獲得當(dāng)前的調(diào)色板
brush = QBrush(QImage("source/五子棋界面.png"))
p.setBrush(QPalette.Background,brush)#設(shè)置調(diào)色版
self.setPalette(p)#給窗口設(shè)置調(diào)色板
self.singlePlayerBtn = MyButton.MyButton('source/人機(jī)對(duì)戰(zhàn)_hover.png',
'source/人機(jī)對(duì)戰(zhàn)_normal.png',
'source/人機(jī)對(duì)戰(zhàn)_press.png',
parent=self)
self.singlePlayerBtn.move(300,300)
self.dancelePlayerBtn = MyButton.MyButton('source/雙人對(duì)戰(zhàn)_hover.png',
'source/雙人對(duì)戰(zhàn)_normal.png',
'source/雙人對(duì)戰(zhàn)_press.png',
parent=self)
self.dancelePlayerBtn.move(300,400)
#self.dancelePlayerBtn.clicked.connect(DoublePlayerGame)
self.drawlePlayerBtn = MyButton.MyButton('source/聯(lián)機(jī)對(duì)戰(zhàn)_hover.png',
'source/聯(lián)機(jī)對(duì)戰(zhàn)_normal.png',
'source/聯(lián)機(jī)對(duì)戰(zhàn)_press.png',
parent=self)
self.drawlePlayerBtn.move(300,500)
#綁定開始雙人游戲信號(hào)和槽函數(shù)
self.dancelePlayerBtn.clicked.connect(self.startDoubliGame)
self.singlePlayerBtn.clicked.connect(self.startSingleGame)
self.drawlePlayerBtn.clicked.connect(self.startNetGame)
def startDoubliGame(self):
print("in")
#構(gòu)建雙人對(duì)戰(zhàn)界面
self.doublePlayerGame = DoublePlayerGame.DoublePlayGame()
#綁定返回界面
self.doublePlayerGame.backSignal.connect(self.showStartGame)
self.doublePlayerGame.show()#顯示游戲界面
self.close()
def startSingleGame(self):
self.SingleGame = SinglePlayerGame.SinglePlayerGame()
self.SingleGame.backSignal.connect(self.showStartGame2)
self.SingleGame.show()
self.close()
def startNetGame(self):
self.netConfig = NetConfigWidget()
self.netConfig.exit_signal.connect(self.show)
self.netConfig.show()
self.netConfig.config_signal.connect(self.receiveNetConfig)
self.close()
def receiveNetConfig(self,nettype,name,ip,port):
'''
接收網(wǎng)絡(luò)配置信息
'''
print("net config:",nettype,name,ip,port)
if nettype == "client":
net_object = NetClient(name,ip,port)
elif nettype == "server":
net_object = NetServer(name,ip,port)
else:
return
self.netPlayerGame = NetPlayerGame.NetPlayerGame(net_object=net_object)
self.netPlayerGame.backSignal.connect(self.show)
self.close()
self.netPlayerGame.show()
self.netConfig.hide()
'''lbl = QLabel(self)
pix = QPixmap("source/人機(jī)大戰(zhàn)_norma.")'''
#顯示開始界面
def showStartGame(self):
self.show()
self.doublePlayerGame.close()
def showStartGame2(self):
self.show()
self.SingleGame.close()
if __name__ == "__main__":
import cgitb
cgitb.enable("text")
a = QApplication(sys.argv)
m = Mainwindow()
m.show()
sys.exit(a.exec_())
doubleplayergame.py代碼:
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
from PyQt5 import *
import sys
class Chessman(QLabel):
def __init__(self, color = "black",parent = None):
super().__init__(parent)
self.color = color
self.pic = None
if self.color == "black":
self.pic = QPixmap("source/黑子.png")
else:
self.pic = QPixmap("source/白子.png")
self.setPixmap(self.pic)
self.setFixedSize(self.pic.size())#設(shè)置棋子大小
self.show()
self.x = 0
self.y = 0
def move(self,a0:QtCore.QPoint):
super().move(a0.x()-15,a0.y()-15)
def setIndex(self,x,y):
self.x = x
self.y = y
import MyButton
class DoublePlayGame(QWidget):
backSignal = pyqtSignal()#返回信號(hào)
def __init__(self,parent = None):
super().__init__(parent=parent)
#左上角chessboard[0][0]
#右上角chessboard[0][18]
#左下角chessboard[18][0]
#右下角chessboard[18][18]
#chessboard[行下標(biāo)][列下標(biāo)]
self.chessboard = [[None for i in range(19)] for i in range(19)]
#落子棋子顏色
self.turnChessColor = "black"
self.history = []
self.history2 = []
self.is_over = False
#配置背景圖
p = QPalette(self.palette())#獲得當(dāng)前的調(diào)色板
brush = QBrush(QImage("source/游戲界面.png"))
p.setBrush(QPalette.Background,brush)#設(shè)置調(diào)色版
self.setPalette(p)#給窗口設(shè)置調(diào)色板
#設(shè)置標(biāo)題
#self.resize(760,650)
self.setWindowTitle("雙人聯(lián)機(jī)")
#設(shè)置窗口圖標(biāo)
self.setWindowIcon(QIcon("source/icon.ico"))
#設(shè)置窗口大小
self.setFixedSize(QImage("source/游戲界面.png").size())
self.backBtn = MyButton.MyButton('source/返回按鈕_hover.png',
'source/返回按鈕_normal.png',
'source/返回按鈕_press.png',
parent=self)
self.backBtn.move(650,50)
self.startBtn = MyButton.MyButton('source/開始按鈕_hover.png',
'source/開始按鈕_normal.png',
'source/開始按鈕_press.png',
parent=self)
self.startBtn.move(650,300)
self.returnBtn = MyButton.MyButton('source/悔棋按鈕_hover.png',
'source/悔棋按鈕_normal.png',
'source/悔棋按鈕_press.png',
parent=self)
self.returnBtn.move(650,400)
self.loseBtn = MyButton.MyButton('source/認(rèn)輸按鈕_hover.png',
'source/認(rèn)輸按鈕_normal.png',
'source/認(rèn)輸按鈕_press.png',
parent=self)
self.loseBtn.move(650,500)
#綁定返回按鈕
self.backBtn.clicked.connect(self.goBack)
self.startBtn.clicked.connect(self.restar)
self.loseBtn.clicked.connect(self.lose)
self.returnBtn.clicked.connect(self.huiback)
self.gameStatu = []
self.focusPoint = QLabel(self)
self.focusPoint.setPixmap(QPixmap("source/標(biāo)識(shí).png"))
def goBack(self):
self.backSignal.emit()
self.close()
def closeEvent(self, a0: QtGui.QCloseEvent):
self.backSignal.emit()
def mouseReleaseEvent(self, a0: QtGui.QMouseEvent):
if self.gameStatu == False:
return None
print(a0.pos())
print("x:",a0.x())
print("y:",a0.y())
pos,chess_index = self.reversePos(a0)
if pos is None:
return
if self.chessboard[chess_index[1]][chess_index[0]] != None:
return
self.chess = Chessman(color=self.turnChessColor,parent=self)
self.chess.setIndex(chess_index[0], chess_index[1])
self.chess.move(pos)
self.chess.show()#顯示棋子
self.history.append(self.chess)
self.history2.append(self.focusPoint)
self.focusPoint.move(QPoint(pos.x()-15,pos.y()-15))
self.focusPoint.show()
self.focusPoint.raise_()
print("棋盤交點(diǎn)位置:",chess_index)
#放入棋盤
self.chessboard[chess_index[1]][chess_index[0]] = self.chess
if self.turnChessColor=="black":
self.turnChessColor="white"
else:
self.turnChessColor="black"
self.lbl = None
result = self.isWin(self.chess)
if result != None:
print(result + '贏了')
self.showResult(result)
#自動(dòng)落子
#self.autoDown()
#坐標(biāo)轉(zhuǎn)換
def reversePos(self, a0: QtCore.QPoint):
if a0.x() <= 50 - 15 or a0.x() >= 590 +15 or a0.y() <= 50 - 15 or a0.y() >= 590+15 :
return None, None
self.x = (a0.x()-35)//30
self.y = (a0.y()-35)//30
x = 50+30*self.x
y = 50+30*self.y
return QPoint(x, y),(self.x, self.y)
def isWin(self,chessman):
print("in iswin,lastChessman:",chessman.color,chessman.x,chessman.y)
#水平方向y相同,chessboard[chessman.y][i]
count = 1
#左邊
i = chessman.x - 1
while i>=0:
if self.chessboard[chessman.y][i] == None or self.chessboard[chessman.y][i].color != chessman.color:
break
count += 1
i -= 1
#右邊
i = chessman.x + 1
while i<=18:
if self.chessboard[chessman.y][i] == None or self.chessboard[chessman.y][i].color != chessman.color:
break
count += 1
i += 1
if count >=5:
return chessman.color
count = 1
j = chessman.y - 1
while j >= 0:
if self.chessboard[j][chessman.x] == None or self.chessboard[j][chessman.x].color != chessman.color:
break
count += 1
j -= 1
j = chessman.y + 1
while j <= 18:
if self.chessboard[j][chessman.x] == None or self.chessboard[j][chessman.x].color != chessman.color:
break
count += 1
j += 1
if count >=5:
return chessman.color
count = 1
j,i = chessman.y - 1,chessman.x + 1
while j >= 0 and i <= 18:
if self.chessboard[j][i] == None or self.chessboard[j][i].color != chessman.color:
break
count += 1
j -= 1
i += 1
j,i = chessman.y + 1,chessman.x - 1
while i >= 0 and j <= 18:
if self.chessboard[j][i] == None or self.chessboard[j][i].color != chessman.color:
break
count += 1
i -= 1
j += 1
if count >=5:
return chessman.color
count = 1
j,i = chessman.y-1,chessman.x-1
while j>=0 and i>=0:
if self.chessboard[j][i] == None or self.chessboard[j][i].color != chessman.color:
break
count += 1
j -= 1
i -= 1
j,i = chessman.y+1,chessman.x+1
while j<=18 and i<=18:
if self.chessboard[j][i] == None or self.chessboard[j][i].color != chessman.color:
break
count += 1
j += 1
i += 1
if count >=5:
return chessman.color
return None
def showResult(self,isWin = None):
self.gameStatu = False
if isWin == "white":
self.lbl = QLabel(self)
self.lbl.setPixmap(QPixmap("source/白棋勝利.png"))
self.lbl.move(150,150)
self.lbl.show()
elif isWin == "black":
self.lbl = QLabel(self)
self.lbl.setPixmap(QPixmap("source/黑棋勝利.png"))
self.lbl.move(150,150)
self.lbl.show()
else:
return
def restar(self):
for i in range(19):
for j in range(19):
if self.chessboard[i][j] != None:
self.chessboard[i][j].close()
self.chessboard[i][j] = None
self.focusPoint.close()
else:
pass
if self.lbl != None:
self.lbl.close()
self.gameStatu = True
def lose(self):
if self.gameStatu == False:
return
if self.turnChessColor == "black":
self.lbl = QLabel(self)
self.lbl.setPixmap(QPixmap("source/白棋勝利.png"))
self.lbl.move(150,150)
self.lbl.show()
elif self.turnChessColor == "white":
self.lbl = QLabel(self)
self.lbl.setPixmap(QPixmap("source/黑棋勝利.png"))
self.lbl.move(150,150)
self.lbl.show()
else:
return
def huiback(self):
if self.gameStatu == False:
return
m = self.history.pop()
a = self.history2.pop()
self.chessboard[m.y][m.x] = None
m.close()
a.close()
if self.turnChessColor=="black":
self.turnChessColor="white"
else:
self.turnChessColor="black"
if __name__ == "__main__":
import cgitb
cgitb.enable("text")
a = QApplication(sys.argv)
m = DoublePlayGame()
m.show()
sys.exit(a.exec_())
pass
NetConfig.py代碼:
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5 import *
import socket
import threading
class NetConfigWidget(QWidget):
config_signal = pyqtSignal([str,str,str,str])
exit_signal = pyqtSignal()
def __init__(self,parent = None):
super().__init__(parent = parent)
self.initUI()
def initUI(self):
self.setWindowTitle("網(wǎng)絡(luò)配置")
self.name_label = QLabel("姓名:",self)
self.name_input = QLineEdit("玩家1",self)
self.ip_label = QLabel("IP:",self)
self.ip_input = QLineEdit("127.0.0.1",self)
self.port_label = QLabel("Prot:",self)
self.port_input = QLineEdit("10086",self)
self.client_button = QPushButton("鏈接主機(jī)",self)
self.server_button = QPushButton("我是主機(jī)",self)
gridLayout = QGridLayout()
gridLayout.addWidget(self.name_label,0,0)
gridLayout.addWidget(self.name_input,0,1)
gridLayout.addWidget(self.ip_label,1,0)
gridLayout.addWidget(self.ip_input,1,1)
gridLayout.addWidget(self.port_label,2,0)
gridLayout.addWidget(self.port_input,2,1)
gridLayout.addWidget(self.client_button,3,0)
gridLayout.addWidget(self.server_button,3,1)
self.setLayout(gridLayout)
self.client_button.clicked.connect(self.client_btn_signal)
self.server_button.clicked.connect(self.server_btn_signal)
def server_btn_signal(self):
self.config_signal.emit("server",self.name_input.text(),self.ip_input.text(),self.port_input.text())
def client_btn_signal(self):
self.config_signal.emit("client",self.name_input.text(),self.ip_input.text(),self.port_input.text())
def closeEvent(self,a0:QtGui.QCloseEvent):
self.close()
self.exit_signal.emit()
class NetClient(QObject):
msg_signal = pyqtSignal([str])
def __init__(self,name,ip,port):
super().__init__()
self.name = name
self.ip = ip
self.port = port
self.socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
def buildConnect(self):
'''建立鏈接'''
self.socket.connect((self.ip,int(self.port)))
threading.Thread(target=self.recv).start()
pass
def send(self,data):
'''發(fā)送數(shù)據(jù)
data(發(fā)送的數(shù)據(jù))字符串類型'''
self.socket.send(data.encode())
pass
def recv(self):
'''接收數(shù)據(jù)'''
while True:
try:
data = self.socket.recv(4096).decode()
self.msg_signal.emit(data)
except:
pass
class NetServer(QObject):
msg_signal = pyqtSignal([str])
def __init__(self,name,ip,port):
super().__init__()
self.name = name
self.ip = ip
self.port = port
self.socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
self.cli_socket = None
def buildConnect(self):
self.socket.bind(("",int(self.port)))
self.socket.listen(1)
threading.Thread(target=self.__acceptConnect).start()
def __acceptConnect(self):
try:
self.cli_socket,cli_addr = self.socket.accept()
except:
pass
while True:
try:
data = self.cli_socket.recv(4096).decode()
self.msg_signal.emit(data)
except Exception as e:
print(e)
def send(self,data):
if self.cli_socket == None:
return
self.cli_socket.send(data.encode())
if __name__ == "__main__":
import sys
import cgitb
cgitb.enable("text")
a = QApplication(sys.argv)
m = NetConfigWidget()
m.show()
sys.exit(a.exec_())
pass
NetplayerGame.py代碼:
from DoublePlayerGame import *
import json
from NetConfig import *
from PyQt5.QtMultimedia import QSound
class NetPlayerGame(DoublePlayGame):
def __init__(self,net_object, parent = None):
super().__init__(parent = parent)
self.net_object = net_object
self.net_object.buildConnect()#建立網(wǎng)絡(luò)鏈接
self.net_object.msg_signal.connect(self.parseData)
self.m_color = None#玩家棋子顏色
self.cuicuBtn = MyButton.MyButton('source/催促按鈕_hover.png',
'source/催促按鈕_normal.png',
'source/催促按鈕_press.png',
parent=self)
self.cuicuBtn.move(650,600)
self.cuicuBtn.clicked.connect(self.cuicu)
def cuicu(self):
QSound.play('source/cuicu.wav')
msg = {}
msg['msg_type'] = 'cuicu'
self.net_object.send(json.dumps(msg))
pass
def goBack(self):
self.backSignal.emit()
self.close()
self.net_object.socket.close()
def downChessman(self,point,color):
'''
自動(dòng)落子
:return:
'''
#point = self.getPoint()
# 注意:x,y坐標(biāo)對(duì)應(yīng)
chess_index = (point.y(), point.x()) # 棋子在棋盤中的下標(biāo)
pos = QPoint(50+point.x()*30, 50+point.y()*30) # 棋子在棋盤中的坐標(biāo)
self.chessman = Chessman(color=color, parent=self)
self.chessman.setIndex(chess_index[0], chess_index[1])
self.chessman.move(pos)
self.chessman.show() # 顯示棋子
# 顯示標(biāo)識(shí)
self.focusPoint.move(QPoint(pos.x() - 15, pos.y() - 15))
self.focusPoint.show()
self.focusPoint.raise_()
self.chessboard[chess_index[0]][chess_index[1]] = self.chessman
# 歷史記錄
self.history.append((chess_index[0], chess_index[1], self.chessman.color))
# 改變落子顏色
if self.turnChessColor == 'black':
self.turnChessColor = 'white'
else:
self.turnChessColor = 'black'
# 判斷輸贏
result = self.isWin(self.chessman)
if result != None:
print(result + '贏了')
self.showResult(result)
pass
'''
{
"msg_type":"positon",
"x":"10",
"y":"15",
"color":"black"
}
'''
#解析網(wǎng)路數(shù)據(jù)
def parseData(self,data):
print("pardata:",data)
try:
msg = json.loads(data)
except Exception as e:
print(e)
#msg = json.loads(data)
print("msg:",msg)
if msg["msg_type"] == "position":
self.downChessman(QPoint(int(msg["x"]),int(msg["y"])),msg["color"])
pass
elif msg["msg_type"] == "restart":
result = QMessageBox.information(None,'五子棋_提示消息','請求開始游戲',QMessageBox.Yes |QMessageBox.No)
if result == QMessageBox.Yes:
self.restartGame()#白子
self.m_color = 'white'
msg = {}
msg['msg_type'] = "response"
msg['action_type'] = 'restart'
msg['action_result'] = 'yes'
self.net_object.send(json.dumps(msg))
else:
msg = {}
msg['msg_type'] = "response"
msg['action_type'] = 'restart'
msg['action_result'] = 'no'
self.net_object.send(json.dumps(msg))
elif msg['msg_type'] == 'response':
if msg['action_type'] == 'restart':
if msg['action_result'] == 'yes':
self.restartGame()
self.m_color = 'balck'
else:
QMessageBox.information(self,'五子棋_提示消息','對(duì)方拒絕游戲')
elif msg['action_type'] == 'huiqi':
if msg['action_result'] == 'Yes':
self.huiqigame()
else:
QMessageBox.information(self,'五子棋_提示消息','對(duì)方拒絕悔棋',QMessageBox.Yes |QMessageBox.No)
elif msg['msg_type'] == 'huiqi':
result = QMessageBox.information(self,'五子棋_提示消息','對(duì)方請求悔棋',QMessageBox.Yes |QMessageBox.No)
if result == QMessageBox.Yes:
msg = {}
msg['msg_type'] = "response"
msg['action_type'] = 'huiqi'
msg['action_result'] = 'Yes'
self.net_object.send(json.dumps(msg))
self.huiqigame()
else:
msg = {}
msg['msg_type'] = "response"
msg['action_type'] = 'huiqi'
msg['action_result'] = 'No'
self.net_object.send(json.dumps(msg))
elif msg['msg_type'] == 'lose':
show.showResult(self.m_color)
elif msg['msg_type'] == 'cuicu':
QSound.play('source/cuicu.wav')
QMessageBox.window(self,'0')
def restartGame(self):
for i in range(19):
for j in range(19):
if self.chessboard[i][j] != None:
self.chessboard[i][j].close()
self.chessboard[i][j] = None
self.focusPoint.close()
else:
pass
self.lbl = None
if self.lbl != None:
self.lbl.close()
self.gameStatu = True
self.focusPoint.hide()
self.turnChessColor="black"
def mouseReleaseEvent(self, a0: QtGui.QMouseEvent):
if self.m_color != self.turnChessColor:
return
if self.gameStatu == False:
return None
pos,chess_index = self.reversePos(a0)
if pos is None:
return
if self.chessboard[chess_index[1]][chess_index[0]] != None:
return
self.chess = Chessman(color=self.turnChessColor,parent=self)
self.chess.setIndex(chess_index[1], chess_index[0])
self.chess.move(pos)
self.chess.show()#顯示棋子
self.history.append(self.chess)
self.history2.append(self.focusPoint)
self.focusPoint.move(QPoint(pos.x()-15,pos.y()-15))
self.focusPoint.show()
self.focusPoint.raise_()
print("棋盤交點(diǎn)位置:",chess_index)
#放入棋盤
self.chessboard[chess_index[1]][chess_index[0]] = self.chess
#發(fā)送落子信息
msg = {}
msg["msg_type"] = "position"
msg["x"] = chess_index[1]
msg["y"] = chess_index[0]
msg["color"] = self.turnChessColor
self.net_object.send(json.dumps(msg))
if self.turnChessColor=="black":
self.turnChessColor="white"
else:
self.turnChessColor="black"
self.lbl = None
result = self.isWin(self.chess)
if result != None:
print(result + '贏了')
self.showResult(result)
def huiqi(self):
if self.gameStatu == None:
QMessageBox.warning(self,'五子棋提示','游戲沒有開始,不能悔棋')
if self.m_color != self.turnChessColor:
QMessageBox.warning(self,'五子棋提示','不是你的回合')
msg = {}
msg['msg_type'] = 'huiqi'
self.net_object.send(json.dumps(msg))
def huiqigame(self):
if self.gameStatu == False:
return
m = self.history.pop()
a = self.history2.pop()
self.chessboard[m.y][m.x] = None
m.close()
a.close()
if self.turnChessColor=="black":
self.turnChessColor="white"
else:
self.turnChessColor="black"
def restar(self):
msg = {}
msg["msg_type"] = "restart"
self.net_object.send(json.dumps(msg))
def lose(self):
if self.gameStatu == False:
QMessageBox.warning(None,'五子棋','游戲沒有開始')
if self.m_color == "black":
self.lbl = QLabel(self)
self.lbl.setPixmap(QPixmap("source/白棋勝利.png"))
self.lbl.move(150,150)
self.lbl.show()
elif self.m_color == "white":
self.lbl = QLabel(self)
self.lbl.setPixmap(QPixmap("source/黑棋勝利.png"))
self.lbl.move(150,150)
self.lbl.show()
else:
return
msg = {}
msg['msg_type'] = "lose"
#msg['action_type'] = 'restart'
#msg['action_result'] = 'no'
self.net_object.send(json.dumps(msg))
if __name__ == '__main__':
import cgitb
cgitb.enable("text")
a = QApplication(sys.argv)
m = NetPlayerGame()
m.show()
sys.exit(a.exec_())
pass
MyButton.py代碼:
# -*- coding:utf-8 -*-
# @author: alex
# @time: 2018/12/27 16:29
from PyQt5 import QtGui, QtCore
from PyQt5.QtWidgets import *
from PyQt5 import *
from PyQt5.QtGui import *
import sys
from PyQt5.QtCore import *
class MyButton(QLabel):
clicked = pyqtSignal()#自定義一個(gè)信號(hào)
def __init__(self, *args, parent=None):
super().__init__(parent)
self.hoverPixmap = QPixmap(args[0])
self.normalPixmap = QPixmap(args[1])
self.pressPixmap = QPixmap(args[2])
self.enterState = False
self.setPixmap(self.normalPixmap)
self.setFixedSize(self.normalPixmap.size())
def mouseReleaseEvent(self, ev: QtGui.QMouseEvent):
if self.enterState == False:
self.setPixmap(self.normalPixmap)
else:
self.setPixmap(self.hoverPixmap)
self.clicked.emit()#發(fā)射信號(hào)
print("鼠標(biāo)釋放")
pass
def mousePressEvent(self, ev: QtGui.QMouseEvent):
self.setPixmap(self.pressPixmap)
print("鼠標(biāo)按下")
pass
def enterEvent(self, a0: QtCore.QEvent):
self.setPixmap(self.hoverPixmap)
self.enterState = True
print("鼠標(biāo)進(jìn)入")
pass
def leaveEvent(self, a0: QtCore.QEvent):
self.setPixmap(self.normalPixmap)
self.enterState = False
print("鼠標(biāo)離開")
pass
if __name__ == '__main__':
a = QApplication(sys.argv)
mybtn = MyButton('source/人機(jī)對(duì)戰(zhàn)_hover.png',
'source/人機(jī)對(duì)戰(zhàn)_normal.png',
'source/人機(jī)對(duì)戰(zhàn)_press.png')
mybtn.show()
sys.exit(a.exec_())
SingerPlayerGame.py代碼:
from DoublePlayerGame import *
class SinglePlayerGame(DoublePlayGame):
def __init__(self, parent=None):
super().__init__(parent=parent)
self.setWindowTitle('五子棋-單機(jī)模式')
def mouseReleaseEvent(self, a0: QtGui.QMouseEvent):
if self.gameStatu == False:
return None
print(a0.pos())
print("x:",a0.x())
print("y:",a0.y())
pos,chess_index = self.reversePos(a0)
if pos is None:
return
if self.chessboard[chess_index[1]][chess_index[0]] != None:
return
# 玩家落子
super().mouseReleaseEvent(a0)
# 電腦落子
self.autoDown()
def getPointScore(self, x, y, color):
'''
返回每個(gè)點(diǎn)的得分
y:行坐標(biāo)
x:列坐標(biāo)
color:棋子顏色
:return:
'''
# 分別計(jì)算點(diǎn)周圍5子以內(nèi),空白、和同色的分?jǐn)?shù)
blank_score = 0
color_score = 0
# 記錄每個(gè)方向的棋子分?jǐn)?shù)
blank_score_plus = [0, 0, 0, 0] # 橫向 縱向 正斜線 反斜線
color_score_plus = [0, 0, 0, 0]
# 橫線
# 右側(cè)
i = x # 橫坐標(biāo)
j = y # 縱坐標(biāo)
while i < 19:
if self.chessboard[j][i] is None:
blank_score += 1
blank_score_plus[0] += 1
break
elif self.chessboard[j][i].color == color:
color_score += 1
color_score_plus[0] += 1
else:
break
if i >= x + 4:
break
i += 1
# print('123123')
# 左側(cè)
i = x # 橫坐標(biāo)
j = y # 縱坐標(biāo)
while i >= 0:
if self.chessboard[j][i] is None:
blank_score += 1
blank_score_plus[0] += 1
break
elif self.chessboard[j][i].color == color:
color_score += 1
color_score_plus[0] += 1
else:
break
if i <= x - 4:
break
i -= 1
# 豎線
# 上方
i = x # 橫坐標(biāo)
j = y # 縱坐標(biāo)
while j >= 0:
if self.chessboard[j][i] is None:
blank_score += 1
blank_score_plus[1] += 1
break
elif self.chessboard[j][i].color == color:
color_score += 1
color_score_plus[1] += 1
else:
break
if j <= y - 4:
break
j -= 1
# 豎線
# 下方
i = x # 橫坐標(biāo)
j = y # 縱坐標(biāo)
while j < 19:
if self.chessboard[j][i] is None:
blank_score += 1
blank_score_plus[1] += 1
break
elif self.chessboard[j][i].color == color:
color_score += 1
color_score_plus[1] += 1
else:
break
if j >= y + 4: # 最近五個(gè)點(diǎn)
break
j += 1
# 正斜線
# 右上
i = x
j = y
while i < 19 and j >= 0:
if self.chessboard[j][i] is None:
blank_score += 1
blank_score_plus[2] += 1
break
elif self.chessboard[j][i].color == color:
color_score += 1
color_score_plus[2] += 1
else:
break
if i >= x + 4: # 最近五個(gè)點(diǎn)
break
i += 1
j -= 1
# 左下
i = x
j = y
while j < 19 and i >= 0:
if self.chessboard[j][i] is None:
blank_score += 1
blank_score_plus[2] += 1
break
elif self.chessboard[j][i].color == color:
color_score += 1
color_score_plus[2] += 1
else:
break
if j >= y + 4: # 最近五個(gè)點(diǎn)
break
i -= 1
j += 1
# 反斜線
# 左上
i = x
j = y
while i >= 0 and j >= 0:
if self.chessboard[j][i] is None:
blank_score += 1
blank_score_plus[3] += 1
break
elif self.chessboard[j][i].color == color:
color_score += 1
color_score_plus[3] += 1
else:
break
if i <= x - 4:
break
i -= 1
j -= 1
# 右上
i = x
j = y
while i < 19 and j < 19:
if self.chessboard[j][i] is None:
blank_score += 1
blank_score_plus[3] += 1
break
elif self.chessboard[j][i].color == color:
color_score += 1
color_score_plus[3] += 1
else:
break
if i >= x + 4:
break
i += 1
j += 1
for k in range(4):
if color_score_plus[k] >= 5:
return 100
# color_score *= 5
return max([x + y for x, y in zip(color_score_plus, blank_score_plus)])
def getPoint(self):
'''
返回落子位置
:return:
'''
# 簡單實(shí)現(xiàn):返回一個(gè)空白交點(diǎn)
# for i in range(19):
# for j in range(19):
# if self.chessboard[i][j] == None:
# return QPoint(j, i)
#
# 沒有找到合適的點(diǎn)
white_score = [ [ 0 for i in range(19) ] for j in range(19)]
black_score = [ [ 0 for i in range(19) ] for j in range(19)]
for i in range(19):
for j in range(19):
if self.chessboard[i][j] != None:
continue
# 模擬落子
self.chessboard[i][j] = Chessman(color='white',parent=self)
white_score[i][j] = self.getPointScore(j, i, 'white')
self.chessboard[i][j].close()
self.chessboard[i][j] = None
self.chessboard[i][j] = Chessman(color='black',parent=self)
black_score[i][j] = self.getPointScore(j, i, 'black')
self.chessboard[i][j].close()
self.chessboard[i][j] = None
print('----------------')
# 將二維坐標(biāo)轉(zhuǎn)換成以為進(jìn)行計(jì)算
r_white_score = []
r_black_score = []
for i in white_score:
r_white_score.extend(i)
for i in black_score:
r_black_score.extend(i)
# 找到分?jǐn)?shù)最大值
score = [ max(x,y) for x,y in zip(r_white_score,r_black_score) ]
# 找到分?jǐn)?shù)做大的下標(biāo)
chess_index = score.index(max(score))
print(score,'\n',max(score))
y = chess_index //19
x = chess_index % 19
return QPoint(x,y)
def autoDown(self):
'''
自動(dòng)落子
:return:
'''
point = self.getPoint()
# 注意:x,y坐標(biāo)對(duì)應(yīng)
chess_index = (point.y(), point.x()) # 棋子在棋盤中的下標(biāo)
pos = QPoint(50+point.x()*30, 50+point.y()*30) # 棋子在棋盤中的坐標(biāo)
self.chessman = Chessman(color=self.turnChessColor, parent=self)
self.chessman.setIndex(chess_index[1], chess_index[0])
self.chessman.move(pos)
self.chessman.show() # 顯示棋子
# 顯示標(biāo)識(shí)
self.focusPoint.move(QPoint(pos.x() - 15, pos.y() - 15))
self.focusPoint.show()
self.focusPoint.raise_()
self.chessboard[chess_index[0]][chess_index[1]] = self.chessman
# 歷史記錄
self.history.append((chess_index[0], chess_index[1], self.chessman.color))
# 改變落子顏色
if self.turnChessColor == 'black':
self.turnChessColor = 'white'
else:
self.turnChessColor = 'black'
# 判斷輸贏
result = self.isWin(self.chessman)
if result != None:
print(result + '贏了')
self.showResult(result)
pass
if __name__ == '__main__':
import cgitb
cgitb.enable('text')
a = QApplication(sys.argv)
m = SinglePlayerGame()
m.show()
sys.exit(a.exec_())
更多關(guān)于python游戲的精彩文章請點(diǎn)擊查看以下專題:
源碼下載:五子棋游戲人機(jī)版
以上就是本文的全部內(nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
python實(shí)現(xiàn)合并兩個(gè)有序列表的示例代碼
這篇文章主要介紹了python實(shí)現(xiàn)合并兩個(gè)有序列表的示例代碼,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-04-04
Python?matplotlib繪制散點(diǎn)圖配置(萬能模板案例)
這篇文章主要介紹了Python?matplotlib繪制散點(diǎn)圖配置(萬能模板案例),散點(diǎn)圖是指在??回歸分析???中,數(shù)據(jù)點(diǎn)在直角坐標(biāo)系平面上的?分布圖???,散點(diǎn)圖表示因變量隨??自變量???而?變化???的大致趨勢,據(jù)此可以選擇合適的函數(shù)??對(duì)數(shù)???據(jù)點(diǎn)進(jìn)行?擬合2022-07-07
Python?JMESPath庫輕松操作JSON進(jìn)行數(shù)據(jù)查詢方法實(shí)例
這篇文章主要為大家介紹了Python?JMESPath庫輕松操作JSON方法實(shí)例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2024-01-01
python實(shí)現(xiàn)LBP方法提取圖像紋理特征實(shí)現(xiàn)分類的步驟
這篇文章主要介紹了python實(shí)現(xiàn)LBP方法提取圖像紋理特征實(shí)現(xiàn)分類的步驟,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-07-07
python 數(shù)據(jù)庫查詢返回list或tuple實(shí)例
這篇文章主要介紹了python 數(shù)據(jù)庫查詢返回list或tuple實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2020-05-05
最新python 字符串?dāng)?shù)組互轉(zhuǎn)問題
這篇文章主要介紹了最新python 字符串?dāng)?shù)組互轉(zhuǎn)問題,主要介紹了字符串轉(zhuǎn)list數(shù)組問題和list數(shù)組轉(zhuǎn)字符串問題,本文結(jié)合示例代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下2023-02-02
pytest生成簡單自定義測試結(jié)果的html報(bào)告
這篇文章主要為大家介紹了pytest生成簡單自定義測試結(jié)果html報(bào)告,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-06-06

