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遊戲
- BetaMeow:利用機器學習做五子棋AI機器學習AI
- Python實現五子棋人機對戰的二次開發Python
- 五子棋AI演算法(一)AI演算法
- 【Demo見真章】基於HarmonyOS手機實現五子棋對戰小遊戲遊戲
- Java做的五子棋Java
- 用Python實現一個人工智慧對對聯Python人工智慧
- 實戰 | 用Python做影象處理(一)Python
- Android小遊戲——簡單易懂單機人人對戰五子棋原始碼詳解Android遊戲原始碼
- Java實現五子棋對戰小遊戲【完整版】Java遊戲
- Python ------ 一起來對網格做下回測Python
- 結對專案——五子棋
- 結對專案 五子棋
- 藉助實時資料推送快速製作線上對戰五子棋小遊戲丨實戰遊戲
- python 五子棋原始碼Python原始碼
- 那些“一個人做的遊戲” 和它的玩家們遊戲
- 為什麼做AI的都選Python?AIPython
- 做過頭個人看法
- 鬥地主老是輸?一起用Python做個AI出牌器!PythonAI
- 對銷售個人而言,應該選擇做渠道還是做直銷的崗位?
- AI電話機器人可以做什麼?AI機器人
- 關於五子棋電腦AI演算法的一些思考AI演算法
- Python飛機大戰Python
- 結對專案之五子棋遊戲遊戲
- 一個人人網python爬蟲Python爬蟲
- 用 Python 做一個 H5 遊戲機器人PythonH5遊戲機器人
- 用Swoole來寫個聯機對戰遊戲呀!(一)前言遊戲
- PYTHON教程中“編寫一個Python指令碼”版本一的windows版本Python指令碼Windows
- mfc版本及其對應vc版本一覽表 (轉)
- 【日報】谷歌AI與圍棋冠軍對戰日程谷歌AI
- 人機大戰一觸即發 AlphaGo對戰李世石你押誰贏?Go
- tensorflow與python版本對應關係Python
- 人大:和清、北做不一樣的AIAI
- AI時代,6小時做一款遊戲!AI遊戲
- 給AI系統做“安全體檢” 阿里釋出自動化AI對抗平臺AI阿里
- AI晶片的長征之路:挑戰與機遇AI晶片
- Thin框架的應用(一) 單機雙人對戰象棋程式框架
- Thin框架的應用(一):單機雙人對戰象棋程式框架