python做一個人機對戰五子棋,AI版本
川川以前夢寐以求的想找個五子棋對手,由於學習原因,實在沒小夥伴陪我玩了,於是我就想著做一個AI五子棋來陪我玩吧。網上的遊戲搜可以看到一大堆,我們不能說白嫖,白嫖過來總要改一改成自己想要的吧,雖然我也喜歡白嫖,但是我還是喜歡改成我自己想要的。
需要完整檔案加我**QQ:2835809579**
於是我就改編做了一個五子棋,別說,這五子棋真的強,有時候我下不過他!
看一小段視訊演示一下:
AI.mp4
截圖看下:
程式碼實在太多了,我就只上傳一部分了,有需要再加我 QQ.
from PyQt5.QtWidgets import QMainWindow, QMessageBox
from PyQt5.QtGui import QPainter, QPen, QColor, QPalette, QBrush, QPixmap, QRadialGradient
from PyQt5.QtCore import Qt, QPoint, QTimer
import traceback
from game import Gomoku
from corner_widget import CornerWidget
def run_with_exc(f):
"""遊戲執行出現錯誤時,用messagebox把錯誤資訊顯示出來"""
def call(window, *args, **kwargs):
try:
return f(window, *args, **kwargs)
except Exception:
exc_info = traceback.format_exc()
QMessageBox.about(window, '錯誤資訊', exc_info)
return call
class GomokuWindow(QMainWindow):
def __init__(self):
super().__init__()
self.init_ui() # 初始化遊戲介面
self.g = Gomoku() # 初始化遊戲內容
self.last_pos = (-1, -1)
self.res = 0 # 記錄那邊獲得了勝利
self.operate_status = 0 # 遊戲操作狀態。0為遊戲中(可操作),1為遊戲結束閃爍過程中(不可操作)
def init_ui(self):
"""初始化遊戲介面"""
# 1. 確定遊戲介面的標題,大小和背景顏色
self.setObjectName('MainWindow')
self.setWindowTitle('五子棋')
self.setFixedSize(650, 650)
# self.setStyleSheet('#MainWindow{background-color: green}')
palette = QPalette()
palette.setBrush(QPalette.Window, QBrush(QPixmap('imgs/muzm.jpg')))
self.setPalette(palette)
# 2. 開啟滑鼠位置的追蹤。並在滑鼠位置移動時,使用特殊符號標記當前的位置
self.setMouseTracking(True)
# 3. 滑鼠位置移動時,對滑鼠位置的特殊標記
self.corner_widget = CornerWidget(self)
self.corner_widget.repaint()
self.corner_widget.hide()
# 4. 遊戲結束時閃爍的定時器
self.end_timer = QTimer(self)
self.end_timer.timeout.connect(self.end_flash)
self.flash_cnt = 0 # 遊戲結束之前閃爍了多少次
self.flash_pieces = ((-1, -1), ) # 哪些棋子需要閃爍
# 5. 顯示初始化的遊戲介面
self.show()
@run_with_exc
def paintEvent(self, e):
"""繪製遊戲內容"""
def draw_map():
"""繪製棋盤"""
qp.setPen(QPen(QColor(0, 0, 0), 2, Qt.SolidLine)) # 棋盤的顏色為黑色
# 繪製橫線
for x in range(15):
qp.drawLine(40 * (x + 1), 40, 40 * (x + 1), 600)
# 繪製豎線
for y in range(15):
qp.drawLine(40, 40 * (y + 1), 600, 40 * (y + 1))
# 繪製棋盤中的黑點
qp.setBrush(QColor(0, 0, 0))
key_points = [(4, 4), (12, 4), (4, 12), (12, 12), (8, 8)]
for t in key_points:
qp.drawEllipse(QPoint(40 * t[0], 40 * t[1]), 5, 5)
def draw_pieces():
"""繪製棋子"""
# 繪製黑棋子
qp.setPen(QPen(QColor(0, 0, 0), 1, Qt.SolidLine))
# qp.setBrush(QColor(0, 0, 0))
for x in range(15):
for y in range(15):
if self.g.g_map[x][y] == 1:
if self.flash_cnt % 2 == 1 and (x, y) in self.flash_pieces:
continue
radial = QRadialGradient(40 * (x + 1), 40 * (y + 1), 15, 40 * x + 35, 40 * y + 35) # 棋子的漸變效果
radial.setColorAt(0, QColor(96, 96, 96))
radial.setColorAt(1, QColor(0, 0, 0))
qp.setBrush(QBrush(radial))
qp.drawEllipse(QPoint(40 * (x + 1), 40 * (y + 1)), 15, 15)
# 繪製白棋子
qp.setPen(QPen(QColor(160, 160, 160), 1, Qt.SolidLine))
# qp.setBrush(QColor(255, 255, 255))
for x in range(15):
for y in range(15):
if self.g.g_map[x][y] == 2:
if self.flash_cnt % 2 == 1 and (x, y) in self.flash_pieces:
continue
radial = QRadialGradient(40 * (x + 1), 40 * (y + 1), 15, 40 * x + 35, 40 * y + 35) # 棋子的漸變效果
radial.setColorAt(0, QColor(255, 255, 255))
radial.setColorAt(1, QColor(160, 160, 160))
qp.setBrush(QBrush(radial))
qp.drawEllipse(QPoint(40 * (x + 1), 40 * (y + 1)), 15, 15)
if hasattr(self, 'g'): # 遊戲還沒開始的話,就不用畫了
qp = QPainter()
qp.begin(self)
draw_map() # 繪製棋盤
draw_pieces() # 繪製棋子
qp.end()
@run_with_exc
def mouseMoveEvent(self, e):
# 1. 首先判斷滑鼠位置對應棋盤中的哪一個格子
mouse_x = e.windowPos().x()
mouse_y = e.windowPos().y()
if 25 <= mouse_x <= 615 and 25 <= mouse_y <= 615 and (mouse_x % 40 <= 15 or mouse_x % 40 >= 25) and (mouse_y % 40 <= 15 or mouse_y % 40 >= 25):
game_x = int((mouse_x + 15) // 40) - 1
game_y = int((mouse_y + 15) // 40) - 1
else: # 滑鼠當前的位置不對應任何一個遊戲格子,將其標記為(01, 01
game_x = -1
game_y = -1
# 2. 然後判斷滑鼠位置較前一時刻是否發生了變化
pos_change = False # 標記滑鼠位置是否發生了變化
if game_x != self.last_pos[0] or game_y != self.last_pos[1]:
pos_change = True
self.last_pos = (game_x, game_y)
# 3. 最後根據滑鼠位置的變化,繪製特殊標記
if pos_change and game_x != -1:
self.setCursor(Qt.PointingHandCursor)
if pos_change and game_x == -1:
self.setCursor(Qt.ArrowCursor)
if pos_change and game_x != -1:
self.corner_widget.move(25 + game_x * 40, 25 + game_y * 40)
self.corner_widget.show()
if pos_change and game_x == -1:
self.corner_widget.hide()
@run_with_exc
def mousePressEvent(self, e):
"""根據滑鼠的動作,確定落子位置"""
if not (hasattr(self, 'operate_status') and self.operate_status == 0):
return
if e.button() == Qt.LeftButton:
# 1. 首先判斷按下了哪個格子
mouse_x = e.windowPos().x()
mouse_y = e.windowPos().y()
if (mouse_x % 40 <= 15 or mouse_x % 40 >= 25) and (mouse_y % 40 <= 15 or mouse_y % 40 >= 25):
game_x = int((mouse_x + 15) // 40) - 1
game_y = int((mouse_y + 15) // 40) - 1
else: # 滑鼠點選的位置不正確
return
self.g.move_1step(True, game_x, game_y)
# 2. 根據操作結果進行一輪遊戲迴圈
res, self.flash_pieces = self.g.game_result(show=True) # 判斷遊戲結果
if res != 0: # 如果遊戲結果為“已經結束”,則顯示遊戲內容,並退出主迴圈
self.repaint(0, 0, 650, 650)
self.game_restart(res)
return
# self.g.ai_move_1step() # 電腦下一步
self.g.ai_play_1step() # 電腦下一步
res, self.flash_pieces = self.g.game_result(show=True)
if res != 0:
self.repaint(0, 0, 650, 650)
self.game_restart(res)
return
self.repaint(0, 0, 650, 650) # 在遊戲還沒有結束的情況下,顯示遊戲內容,並繼續下一輪迴圈
@run_with_exc
def end_flash(self):
# 遊戲結束時的閃爍操作
if self.flash_cnt <= 5:
# 執行閃爍
self.flash_cnt += 1
self.repaint()
else:
# 閃爍完畢,執行重新開始的操作
self.end_timer.stop()
# 1. 顯示遊戲結束的資訊
if self.res == 1:
QMessageBox.about(self, '遊戲結束', '玩家獲勝!')
elif self.res == 2:
QMessageBox.about(self, '遊戲結束', '電腦獲勝!')
elif self.res == 3:
QMessageBox.about(self, '遊戲結束', '平局!')
else:
raise ValueError('當前遊戲結束的標誌位為' + self.res + '. 而遊戲結束的標誌位必須為1, 2 或 3')
# 2. 遊戲重新開始的操作
self.res = 0
self.operate_status = 0
self.flash_cnt = 0
self.g = Gomoku() # 重新初始化遊戲內容
self.repaint(0, 0, 650, 650) # 重新繪製遊戲介面
def game_restart(self, res):
"""遊戲出現開始"""
self.res = res # 標記誰獲勝了
self.operate_status = 1 # 遊戲結束時的閃爍過程中,不可操作
self.end_timer.start(300) # 開始結束時閃爍的計時器
from PyQt5.QtGui import QPainter, QPen
from PyQt5.QtWidgets import QWidget
from PyQt5.QtCore import Qt
class CornerWidget(QWidget):
def __init__(self, parent):
super().__init__(parent=parent)
self.setFixedSize(30, 30)
def paintEvent(self, e):
qp = QPainter()
qp.begin(self)
pen = QPen(Qt.red, 3, Qt.SolidLine)
qp.setPen(pen)
qp.drawLine(0, 8, 0, 0)
qp.drawLine(0, 0, 8, 0)
qp.drawLine(22, 0, 28, 0)
qp.drawLine(28, 0, 28, 8)
qp.drawLine(28, 22, 28, 28)
qp.drawLine(28, 28, 20, 28)
qp.drawLine(8, 28, 0, 28)
qp.drawLine(0, 28, 0, 22)
現在我準備把這個封裝成exe軟體來用,嘿嘿!
相關文章
- Python:遊戲:五子棋之人機對戰Python遊戲
- Python實現五子棋人機對戰的二次開發Python
- 用 Python 做一個 H5 遊戲機器人PythonH5遊戲機器人
- 動手做個 AI 機器人,幫我回訊息!AI機器人
- 用Python基於Google Bard做一個互動式的聊天機器人PythonGo機器人
- AI電話機器人可以做什麼?AI機器人
- 五子棋AI演算法(一)AI演算法
- 實戰:30 行程式碼做一個網頁端的 AI 聊天助手行程網頁AI
- 鬥地主老是輸?一起用Python做個AI出牌器!PythonAI
- 使用 python 打造一個微信聊天機器人Python機器人
- [譯] 如何用 Python 寫一個 Discord 機器人Python機器人
- 在匹配模式中玩人機對戰?模式
- 實戰 | 用Python做影象處理(一)Python
- 【Demo見真章】基於HarmonyOS手機實現五子棋對戰小遊戲遊戲
- 通過Azure bot framework composer 設計一個AI對話機器人bot(查詢天氣)FrameworkAI機器人
- 利用網頁版微信API做一個微信機器人網頁API機器人
- 用Swoole來寫個聯機對戰遊戲呀!(一)前言遊戲
- 智慧對話機器人實戰視訊教程機器人
- Java實現五子棋對戰小遊戲【完整版】Java遊戲
- 用Python做一個翻譯軟體Python
- 如何使用python做一個聊天小程式?Python
- 用Python做一個三階拼圖。Python
- Python ------ 一起來對網格做下回測Python
- 教你用python搭建一個「生活常識解答」機器人Python機器人
- 機器人託管2.0,更智慧、更個性的AI客服機器人機器人AI
- 打造一個window桌面應用:線上聊天對話機器人機器人
- python 五子棋原始碼Python原始碼
- 以機器人為入口構建老年人健康服務全閉環,養老會是AI的下一個「主戰場」嗎?機器人健康服務AI
- 做過頭個人看法
- 乾貨 | 如何用 Python 打造一個聊天機器人?【附程式碼】Python機器人
- 掌握這20個JS技巧,做一個不加班的前端人JS前端
- 人工智慧(AI)對下一代工業機器人的影響人工智慧AI機器人
- 當前端玩起 CoolQ:做個技術文章推送機器人前端機器人
- 實現一個質量過硬五子棋
- 用Unity做半個2D戰棋小遊戲(三):新增對戰雙方Unity遊戲
- RPA結合AI(NLP)便有了“對話式RPA機器人”AI機器人
- 用 canvas 做一個 DVD 待機動畫Canvas動畫
- 那些“一個人做的遊戲” 和它的玩家們遊戲