python遊戲實戰項目之智能五子棋
導語
今日遊戲更新,大傢好,我是木木子,每天都給大傢更新最好玩的遊戲!關註我,從此你再也不用去費力找遊戲瞭!
最熱門最好玩的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 五子棋內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!