python游戏实战项目之智能五子棋
短信预约 -IT技能 免费直播动态提醒
导语
今日游戏更新,大家好,我是木木子,每天都给大家更新最好玩的游戏!关注我,从此你再也不用去费力找游戏了!
最热门最好玩的Python游戏点击即玩!
今天推荐的游戏是五子棋小游戏——人机对战、联机对战皆可!
你是否还记得?中学时代和同桌下过的五子棋?
这样下棋只怕是会被打!!!!我怀疑他开挂了,并且找到了证据。
正文
首先准备好需要的图片等素材部分如下:
好了!直接上代码吧——设置游戏开始界面:
class gameStartUI(QWidget):
def __init__(self, parent=None, **kwargs):
super(gameStartUI, self).__init__(parent)
self.setFixedSize(760, 650)
self.setWindowTitle('五子棋游戏对战')
self.setWindowIcon(QIcon(cfg.ICON_FILEPATH))
# 背景图片
palette = QPalette()
palette.setBrush(self.backgroundRole(), QBrush(QPixmap(cfg.BACKGROUND_IMAGEPATHS.get('bg_start'))))
self.setPalette(palette)
# 按钮
# --人机对战
self.ai_button = PushButton(cfg.BUTTON_IMAGEPATHS.get('ai'), self)
self.ai_button.move(250, 200)
self.ai_button.show()
self.ai_button.click_signal.connect(self.playWithAI)
# --联机对战
self.online_button = PushButton(cfg.BUTTON_IMAGEPATHS.get('online'), self)
self.online_button.move(250, 350)
self.online_button.show()
self.online_button.click_signal.connect(self.playOnline)
'''人机对战'''
def playWithAI(self):
self.close()
self.gaming_ui = playWithAIUI(cfg)
self.gaming_ui.exit_signal.connect(lambda: sys.exit())
self.gaming_ui.back_signal.connect(self.show)
self.gaming_ui.show()
'''联机对战'''
def playOnline(self):
self.close()
self.gaming_ui = playOnlineUI(cfg, self)
self.gaming_ui.show()
'''run'''
if __name__ == '__main__':
app = QApplication(sys.argv)
handle = gameStartUI()
font = QFont()
font.setPointSize(12)
handle.setFont(font)
handle.show()
sys.exit(app.exec_())
效果如下:
一个是五子棋规则设置的人机对战:
import pygame
from ..misc import *
from PyQt5 import QtCore
from PyQt5.QtGui import *
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *
from itertools import product
from .aiGobang import aiGobang
'''人机对战'''
class playWithAIUI(QWidget):
back_signal = pyqtSignal()
exit_signal = pyqtSignal()
send_back_signal = False
def __init__(self, cfg, parent=None, **kwargs):
super(playWithAIUI, self).__init__(parent)
self.cfg = cfg
self.setFixedSize(760, 650)
self.setWindowTitle('五子棋人机对战')
self.setWindowIcon(QIcon(cfg.ICON_FILEPATH))
# 背景图片
palette = QPalette()
palette.setBrush(self.backgroundRole(), QBrush(QPixmap(cfg.BACKGROUND_IMAGEPATHS.get('bg_game'))))
self.setPalette(palette)
# 按钮
self.home_button = PushButton(cfg.BUTTON_IMAGEPATHS.get('home'), self)
self.home_button.click_signal.connect(self.goHome)
self.home_button.move(680, 10)
self.startgame_button = PushButton(cfg.BUTTON_IMAGEPATHS.get('startgame'), self)
self.startgame_button.click_signal.connect(self.startgame)
self.startgame_button.move(640, 240)
self.regret_button = PushButton(cfg.BUTTON_IMAGEPATHS.get('regret'), self)
self.regret_button.click_signal.connect(self.regret)
self.regret_button.move(640, 310)
self.givein_button = PushButton(cfg.BUTTON_IMAGEPATHS.get('givein'), self)
self.givein_button.click_signal.connect(self.givein)
self.givein_button.move(640, 380)
# 落子标志
self.chessman_sign = QLabel(self)
sign = QPixmap(cfg.CHESSMAN_IMAGEPATHS.get('sign'))
self.chessman_sign.setPixmap(sign)
self.chessman_sign.setFixedSize(sign.size())
self.chessman_sign.show()
self.chessman_sign.hide()
# 棋盘(19*19矩阵)
self.chessboard = [[None for i in range(19)] for _ in range(19)]
# 历史记录(悔棋用)
self.history_record = []
# 是否在游戏中
self.is_gaming = True
# 胜利方
self.winner = None
self.winner_info_label = None
# 颜色分配and目前轮到谁落子
self.player_color = 'white'
self.ai_color = 'black'
self.whoseround = self.player_color
# 实例化ai
self.ai_player = aiGobang(self.ai_color, self.player_color)
# 落子声音加载
pygame.mixer.init()
self.drop_sound = pygame.mixer.Sound(cfg.SOUNDS_PATHS.get('drop'))
'''鼠标左键点击事件-玩家回合'''
def mousePressEvent(self, event):
if (event.buttons() != QtCore.Qt.LeftButton) or (self.winner is not None) or (self.whoseround != self.player_color) or (not self.is_gaming):
return
# 保证只在棋盘范围内响应
if event.x() >= 50 and event.x() <= 50 + 30 * 18 + 14 and event.y() >= 50 and event.y() <= 50 + 30 * 18 + 14:
pos = Pixel2Chesspos(event)
# 保证落子的地方本来没有人落子
if self.chessboard[pos[0]][pos[1]]:
return
# 实例化一个棋子并显示
c = Chessman(self.cfg.CHESSMAN_IMAGEPATHS.get(self.whoseround), self)
c.move(event.pos())
c.show()
self.chessboard[pos[0]][pos[1]] = c
# 落子声音响起
self.drop_sound.play()
# 最后落子位置标志对落子位置进行跟随
self.chessman_sign.show()
self.chessman_sign.move(c.pos())
self.chessman_sign.raise_()
# 记录这次落子
self.history_record.append([*pos, self.whoseround])
# 是否胜利了
self.winner = checkWin(self.chessboard)
if self.winner:
self.showGameEndInfo()
return
# 切换回合方(其实就是改颜色)
self.nextRound()
'''鼠标左键释放操作-调用电脑回合'''
def mouseReleaseEvent(self, event):
if (self.winner is not None) or (self.whoseround != self.ai_color) or (not self.is_gaming):
return
self.aiAct()
'''电脑自动下-AI回合'''
def aiAct(self):
if (self.winner is not None) or (self.whoseround == self.player_color) or (not self.is_gaming):
return
next_pos = self.ai_player.act(self.history_record)
# 实例化一个棋子并显示
c = Chessman(self.cfg.CHESSMAN_IMAGEPATHS.get(self.whoseround), self)
c.move(QPoint(*Chesspos2Pixel(next_pos)))
c.show()
self.chessboard[next_pos[0]][next_pos[1]] = c
# 落子声音响起
self.drop_sound.play()
# 最后落子位置标志对落子位置进行跟随
self.chessman_sign.show()
self.chessman_sign.move(c.pos())
self.chessman_sign.raise_()
# 记录这次落子
self.history_record.append([*next_pos, self.whoseround])
# 是否胜利了
self.winner = checkWin(self.chessboard)
if self.winner:
self.showGameEndInfo()
return
# 切换回合方(其实就是改颜色)
self.nextRound()
'''改变落子方'''
def nextRound(self):
self.whoseround = self.player_color if self.whoseround == self.ai_color else self.ai_color
'''显示游戏结束结果'''
def showGameEndInfo(self):
self.is_gaming = False
info_img = QPixmap(self.cfg.WIN_IMAGEPATHS.get(self.winner))
self.winner_info_label = QLabel(self)
self.winner_info_label.setPixmap(info_img)
self.winner_info_label.resize(info_img.size())
self.winner_info_label.move(50, 50)
self.winner_info_label.show()
'''认输'''
def givein(self):
if self.is_gaming and (self.winner is None) and (self.whoseround == self.player_color):
self.winner = self.ai_color
self.showGameEndInfo()
'''悔棋-只有我方回合的时候可以悔棋'''
def regret(self):
if (self.winner is not None) or (len(self.history_record) == 0) or (not self.is_gaming) and (self.whoseround != self.player_color):
return
for _ in range(2):
pre_round = self.history_record.pop(-1)
self.chessboard[pre_round[0]][pre_round[1]].close()
self.chessboard[pre_round[0]][pre_round[1]] = None
self.chessman_sign.hide()
'''开始游戏-之前的对弈必须已经结束才行'''
def startgame(self):
if self.is_gaming:
return
self.is_gaming = True
self.whoseround = self.player_color
for i, j in product(range(19), range(19)):
if self.chessboard[i][j]:
self.chessboard[i][j].close()
self.chessboard[i][j] = None
self.winner = None
self.winner_info_label.close()
self.winner_info_label = None
self.history_record.clear()
self.chessman_sign.hide()
'''关闭窗口事件'''
def closeEvent(self, event):
if not self.send_back_signal:
self.exit_signal.emit()
'''返回游戏主页面'''
def goHome(self):
self.send_back_signal = True
self.close()
self.back_signal.emit()
如下:害!我这下了很久呢,有几次都没下赢人机!2333游戏废材
另一个定义联机对战:
import sys
import random
from .server import *
from .client import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *
'''联机对战'''
class playOnlineUI(QWidget):
def __init__(self, cfg, home_ui, parent=None, **kwargs):
super(playOnlineUI, self).__init__(parent)
self.cfg = cfg
self.home_ui = home_ui
self.setWindowTitle('联机对战')
self.setWindowIcon(QIcon(cfg.ICON_FILEPATH))
self.setFixedSize(300, 200)
# 昵称
self.nickname = random.choice(['杰尼龟', '皮卡丘', '小火龙', '小锯鳄', '妙蛙种子', '菊草叶'])
self.layout0 = QHBoxLayout()
self.nickname_label = QLabel('游戏昵称:', self)
self.nickname_edit = QLineEdit(self)
self.nickname_edit.setText(self.nickname)
self.layout0.addWidget(self.nickname_label, 1)
self.layout0.addWidget(self.nickname_edit, 3)
# IP
self.target_ip = '127.0.0.1'
self.layout1 = QHBoxLayout()
self.ip_label = QLabel('对方IP:', self)
self.ip_edit = QLineEdit(self)
self.ip_edit.setText(self.target_ip)
self.layout1.addWidget(self.ip_label, 1)
self.layout1.addWidget(self.ip_edit, 3)
# 按钮
self.layout2 = QHBoxLayout()
self.connect_button = QPushButton('作为客户端', self)
self.connect_button.clicked.connect(self.becomeClient)
self.ashost_button = QPushButton('作为服务器', self)
self.ashost_button.clicked.connect(self.becomeHost)
self.layout2.addWidget(self.connect_button)
self.layout2.addWidget(self.ashost_button)
# 布局
self.layout = QVBoxLayout()
self.layout.addLayout(self.layout0)
self.layout.addLayout(self.layout1)
self.layout.addLayout(self.layout2)
self.setLayout(self.layout)
'''作为客户端'''
def becomeClient(self):
self.close()
self.nickname = self.nickname_edit.text()
self.target_ip = self.ip_edit.text()
self.client_ui = gobangClient(cfg=self.cfg, nickname=self.nickname, server_ip=self.target_ip)
self.client_ui.exit_signal.connect(lambda: sys.exit())
self.client_ui.back_signal.connect(self.home_ui.show)
self.client_ui.show()
'''作为服务器'''
def becomeHost(self):
self.close()
self.nickname = self.nickname_edit.text()
self.server_ui = gobangSever(cfg=self.cfg, nickname=self.nickname)
self.server_ui.exit_signal.connect(lambda: sys.exit())
self.server_ui.back_signal.connect(self.home_ui.show)
self.server_ui.show()
如下联机对战界面第一步:
定义五子棋AI算法:
import random
from itertools import product
'''五子棋AI算法'''
class aiGobang():
def __init__(self, ai_color, player_color, search_depth=1, **kwargs):
assert search_depth % 2, 'search_depth must be odd number'
self.ai_color = ai_color
self.player_color = player_color
self.search_depth = search_depth
self.score_model = [(50, (0, 1, 1, 0, 0)), (50, (0, 0, 1, 1, 0)), (200, (1, 1, 0, 1, 0)),
(500, (0, 0, 1, 1, 1)), (500, (1, 1, 1, 0, 0)), (5000, (0, 1, 1, 1, 0)),
(5000, (0, 1, 0, 1, 1, 0)), (5000, (0, 1, 1, 0, 1, 0)), (5000, (1, 1, 1, 0, 1)),
(5000, (1, 1, 0, 1, 1)), (5000, (1, 0, 1, 1, 1)), (5000, (1, 1, 1, 1, 0)),
(5000, (0, 1, 1, 1, 1)), (50000, (0, 1, 1, 1, 1, 0)), (99999999, (1, 1, 1, 1, 1))]
self.alpha = -99999999
self.beta = 99999999
self.all_list = [(i, j) for i, j in product(range(19), range(19))]
'''外部调用'''
def act(self, history_record):
self.ai_list = []
self.player_list = []
self.aiplayer_list = []
for item in history_record:
self.aiplayer_list.append((item[0], item[1]))
if item[-1] == self.ai_color:
self.ai_list.append((item[0], item[1]))
elif item[-1] == self.player_color:
self.player_list.append((item[0], item[1]))
while True:
self.next_point = random.choice(range(19)), random.choice(range(19))
if self.next_point not in self.aiplayer_list:
break
self.__doSearch(True, self.search_depth, self.alpha, self.beta)
return self.next_point
'''负极大值搜索, alpha+beta剪枝'''
def __doSearch(self, is_ai_round, depth, alpha, beta):
if self.__isgameover(self.ai_list) or self.__isgameover(self.player_list) or depth == 0:
return self.__evaluation(is_ai_round)
blank_list = list(set(self.all_list).difference(set(self.aiplayer_list)))
blank_list = self.__rearrange(blank_list)
for next_step in blank_list:
if not self.__hasNeighbor(next_step):
continue
if is_ai_round:
self.ai_list.append(next_step)
else:
self.player_list.append(next_step)
self.aiplayer_list.append(next_step)
value = -self.__doSearch(not is_ai_round, depth-1, -beta, -alpha)
if is_ai_round:
self.ai_list.remove(next_step)
else:
self.player_list.remove(next_step)
self.aiplayer_list.remove(next_step)
if value > alpha:
if depth == self.search_depth:
self.next_point = next_step
if value >= beta:
return beta
alpha = value
return alpha
'''游戏是否结束了'''
def __isgameover(self, oneslist):
for i, j in product(range(19), range(19)):
if i < 15 and (i, j) in oneslist and (i+1, j) in oneslist and (i+2, j) in oneslist and (i+3, j) in oneslist and (i+4, j) in oneslist:
return True
elif j < 15 and (i, j) in oneslist and (i, j+1) in oneslist and (i, j+2) in oneslist and (i, j+3) in oneslist and (i, j+4) in oneslist:
return True
elif i < 15 and j < 15 and (i, j) in oneslist and (i+1, j+1) in oneslist and (i+2, j+2) in oneslist and (i+3, j+3) in oneslist and (i+4, j+4) in oneslist:
return True
elif i > 3 and j < 15 and (i, j) in oneslist and (i-1, j+1) in oneslist and (i-2, j+2) in oneslist and (i-3, j+3) in oneslist and (i-4, j+4) in oneslist:
return True
return False
'''重新排列未落子位置'''
def __rearrange(self, blank_list):
last_step = self.aiplayer_list[-1]
for item in blank_list:
for i, j in product(range(-1, 2), range(-1, 2)):
if i == 0 and j == 0:
continue
next_step = (last_step[0]+i, last_step[1]+j)
if next_step in blank_list:
blank_list.remove(next_step)
blank_list.insert(0, next_step)
return blank_list
'''是否存在近邻'''
def __hasNeighbor(self, next_step):
for i, j in product(range(-1, 2), range(-1, 2)):
if i == 0 and j == 0:
continue
if (next_step[0]+i, next_step[1]+j) in self.aiplayer_list:
return True
return False
'''计算得分'''
def __calcScore(self, i, j, x_direction, y_direction, list1, list2, all_scores):
add_score = 0
max_score = (0, None)
for each in all_scores:
for item in each[1]:
if i == item[0] and j == item[1] and x_direction == each[2][0] and y_direction == each[2][1]:
return 0, all_scores
for noffset in range(-5, 1):
position = []
for poffset in range(6):
x, y = i + (poffset + noffset) * x_direction, j + (poffset + noffset) * y_direction
if (x, y) in list2:
position.append(2)
elif (x, y) in list1:
position.append(1)
else:
position.append(0)
shape_len5 = tuple(position[0: -1])
shape_len6 = tuple(position)
for score, shape in self.score_model:
if shape_len5 == shape or shape_len6 == shape:
if score > max_score[0]:
max_score = (score, ((i + (0 + noffset) * x_direction, j + (0 + noffset) * y_direction),
(i + (1 + noffset) * x_direction, j + (1 + noffset) * y_direction),
(i + (2 + noffset) * x_direction, j + (2 + noffset) * y_direction),
(i + (3 + noffset) * x_direction, j + (3 + noffset) * y_direction),
(i + (4 + noffset) * x_direction, j + (4 + noffset) * y_direction)), (x_direction, y_direction))
if max_score[1] is not None:
for each in all_scores:
for p1 in each[1]:
for p2 in max_score[1]:
if p1 == p2 and max_score[0] > 10 and each[0] > 10:
add_score += max_score[0] + each[0]
all_scores.append(max_score)
return add_score+max_score[0], all_scores
'''评估函数'''
def __evaluation(self, is_ai_round):
if is_ai_round:
list1 = self.ai_list
list2 = self.player_list
else:
list2 = self.ai_list
list1 = self.player_list
active_all_scores = []
active_score = 0
for item in list1:
score, active_all_scores = self.__calcScore(item[0], item[1], 0, 1, list1, list2, active_all_scores)
active_score += score
score, active_all_scores = self.__calcScore(item[0], item[1], 1, 0, list1, list2, active_all_scores)
active_score += score
score, active_all_scores = self.__calcScore(item[0], item[1], 1, 1, list1, list2, active_all_scores)
active_score += score
score, active_all_scores = self.__calcScore(item[0], item[1], -1, 1, list1, list2, active_all_scores)
active_score += score
passive_all_scores = []
passive_score = 0
for item in list2:
score, passive_all_scores = self.__calcScore(item[0], item[1], 0, 1, list2, list1, passive_all_scores)
passive_score += score
score, passive_all_scores = self.__calcScore(item[0], item[1], 1, 0, list2, list1, passive_all_scores)
passive_score += score
score, passive_all_scores = self.__calcScore(item[0], item[1], 1, 1, list2, list1, passive_all_scores)
passive_score += score
score, passive_all_scores = self.__calcScore(item[0], item[1], -1, 1, list2, list1, passive_all_scores)
passive_score += score
total_score = active_score - passive_score * 0.1
return total_score
总结
好啦!五子棋现在人机对战也可,真人局域网联机也可!文章就到这里
到此这篇关于python游戏实战项目之智能五子棋的文章就介绍到这了,更多相关python 五子棋内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!
免责声明:
① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。
② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341