【Python案例】基於Pygame黑白棋游戲(附源碼)

来源:https://www.cnblogs.com/123456feng/archive/2022/04/04/16088924.html
-Advertisement-
Play Games

有沒有小火伴是特別喜歡玩五子棋的,我記得我初中是特別喜歡的。於是,我今天就用Python給大家寫了一個黑白棋游戲。代碼放在下麵了。 01、繪製棋盤 Python學習交流Q群:906715085### import pygame, sys, random from pygame.locals impo ...


有沒有小火伴是特別喜歡玩五子棋的,我記得我初中是特別喜歡的。於是,我今天就用Python給大家寫了一個黑白棋游戲。代碼放在下麵了。

在這裡插入圖片描述

01、繪製棋盤

Python學習交流Q群:906715085###
import pygame, sys, random
from pygame.locals import *
BACKGROUNDCOLOR = (255, 255, 255)
FPS = 40
# 初始化
pygame.init()
mainClock = pygame.time.Clock()
# 載入圖片
boardImage = pygame.image.load('board.png')
boardRect = boardImage.get_rect()
blackImage = pygame.image.load('black.png')
blackRect = blackImage.get_rect()
whiteImage = pygame.image.load('white.png')
whiteRect = whiteImage.get_rect()
# 設置視窗
windowSurface = pygame.display.set_mode((boardRect.width, boardRect.height))
pygame.display.set_caption('黑白棋')
# 游戲主迴圈
while True:
    for event in pygame.event.get():
        if event.type == QUIT:
            terminate()
        #滑鼠事件完成玩家走棋(見下文)…..
    #電腦走棋(見下文)…..
    windowSurface.fill(BACKGROUNDCOLOR)
    windowSurface.blit(boardImage, boardRect, boardRect)
    #重畫所有的棋子(見下文)…..
    #游戲結束,顯示雙方棋子數量(見下文)……
    pygame.display.update()
    mainClock.tick(FPS)

 

在這裡插入圖片描述

02、繪製棋子

(1)黑白棋的規則,開局時先放置上黑白各兩個棋子在中間。

(2)用一個8x8列表保存棋子。

CELLWIDTH = 80
CELLHEIGHT = 80
PIECEWIDTH = 78
PIECEHEIGHT = 78
BOARDX = 40
BOARDY = 40
# 重置棋盤
def resetBoard(board):
    for x in range(8):
        for y in range(8):
            board[x][y] = 'none'
    # Starting pieces:
    board[3][3] = 'black'
    board[3][4] = 'white'
    board[4][3] = 'white'
    board[4][4] = 'black'

# 開局時建立新棋盤
def getNewBoard():
    board = []
    for i in range(8):
        board.append(['none'] * 8)
    return board
mainBoard = getNewBoard()
resetBoard(mainBoard)
for x in range(8):
        for y in range(8):
            rectDst = pygame.Rect(BOARDX+x*CELLWIDTH+2, BOARDY+y*CELLHEIGHT+2, PIECEWIDTH, PIECEHEIGHT)
            if mainBoard[x][y] == 'black':
                windowSurface.blit(blackImage, rectDst, blackRect) #畫黑棋
            elif mainBoard[x][y] == 'white':
                windowSurface.blit(whiteImage, rectDst, whiteRect) #畫白棋

 

03、隨機決定誰先走棋

# 誰先走
def whoGoesFirst():
    if random.randint(0, 1) == 0:
        return 'computer'
    else:
        return 'player'

turn = whoGoesFirst()
if turn == 'player':
    playerTile = 'black'
    computerTile = 'white'
else:
    playerTile = 'white'
    computerTile = 'black'

 

04、滑鼠事件

(1)滑鼠操縱,完成玩家走棋

(2)輪流走棋

for event in pygame.event.get():
        if event.type == QUIT:
            terminate()
        #玩家走棋
        if turn == 'player' and event.type == MOUSEBUTTONDOWN and event.button == 1:
            x, y = pygame.mouse.get_pos()
            col = int((x-BOARDX)/CELLWIDTH)
            row = int((y-BOARDY)/CELLHEIGHT)
            if makeMove(mainBoard, playerTile, col, row) == True:
                if getValidMoves(mainBoard, computerTile) != []:
                    turn = 'computer'          #輪到電腦走棋
    #電腦走棋
    if (gameOver == False and turn == 'computer'):
        x, y = getComputerMove(mainBoard, computerTile)
        makeMove(mainBoard, computerTile, x, y)
        savex, savey = x, y
        # 玩家沒有可行的走法了,則電腦繼續,否則切換到玩家走
        if getValidMoves(mainBoard, playerTile) != []:
            turn = 'player'          #輪到玩家走棋
    windowSurface.fill(BACKGROUNDCOLOR)
    windowSurface.blit(boardImage, boardRect, boardRect)

 

在這裡插入圖片描述

05、游戲規則實現

(1)是否允許落子

(2)落子後的翻轉

# 是否是合法走法,如果合法返回需要翻轉的棋子列表
def isValidMove(board, tile, xstart, ystart):
    # 如果該位置已經有棋子或者出界了,返回False
    if not isOnBoard(xstart, ystart) or board[xstart][ystart] != 'none':
        return False
    # 臨時將tile 放到指定的位置
    board[xstart][ystart] = tile
    if tile == 'black':
        otherTile = 'white'
    else:
        otherTile = 'black'
    # 要被翻轉的棋子
    tilesToFlip = []
    for xdirection, ydirection in [ [0, 1], [1, 1], [1, 0], [1, -1], [0, -1], [-1, -1], [-1, 0], [-1, 1] ]:
        x, y = xstart, ystart
        x += xdirection
        y += ydirection
        if isOnBoard(x, y) and board[x][y] == otherTile:
            x += xdirection
            y += ydirection
            if not isOnBoard(x, y):
                continue
            # 一直走到出界或不是對方棋子的位置
            while board[x][y] == otherTile:
                x += xdirection
                y += ydirection
                if not isOnBoard(x, y):
                    break
            # 出界了,則沒有棋子要翻轉OXXXXX
            if not isOnBoard(x, y):
                continue
            # 是自己的棋子OXXXXXXO
            if board[x][y] == tile:
                while True:
                    x -= xdirection
                    y -= ydirection
                    # 回到了起點則結束
                    if x == xstart and y == ystart:
                        break
                    # 需要翻轉的棋子
                    tilesToFlip.append([x, y])
    # 將前面臨時放上的棋子去掉,即還原棋盤
    board[xstart][ystart] = 'none' # restore the empty space
    # 沒有要被翻轉的棋子,則走法非法。翻轉棋的規則。
    if len(tilesToFlip) == 0: # If no tiles were flipped, this is not a valid move.
        return False
    return tilesToFlip

# 是否出界
def isOnBoard(x, y):
    return x >= 0 and x <= 7 and y >= 0 and y <=7

# 獲取可落子的位置
def getValidMoves(board, tile):
    validMoves = []
    for x in range(8):
        for y in range(8):
            if isValidMove(board, tile, x, y) != False:
                validMoves.append([x, y])
    return validMoves
# 將一個tile棋子放到(xstart, ystart)
def makeMove(board, tile, xstart, ystart):
    tilesToFlip = isValidMove(board, tile, xstart, ystart)
    if tilesToFlip == False:
        return False
    board[xstart][ystart] = tile
    for x, y in tilesToFlip: #tilesToFlip是需要翻轉的棋子列表
        board[x][y] = tile #翻轉棋子

 

06、電腦AI走法

如果電腦在所有落子的選擇中,有四個邊角,可落子在邊角,因為邊角的棋子無法被翻轉。如果沒有邊角,則選擇可以翻轉對手最多的位置落子。

def getComputerMove(board, computerTile):
    # 獲取所以合法走法
    possibleMoves = getValidMoves(board, computerTile)
    # 打亂所有合法走法
    random.shuffle(possibleMoves)
    # [x, y]在角上,則優先走,因為角上的不會被再次翻轉
    for x, y in possibleMoves:
        if isOnCorner(x, y):
            return [x, y]
    bestScore = -1
    for x, y in possibleMoves:
        dupeBoard = getBoardCopy(board)
        makeMove(dupeBoard, computerTile, x, y)
        # 按照分數選擇走法,優先選擇翻轉後分數最多的走法
        score = getScoreOfBoard(dupeBoard)[computerTile]
        if score > bestScore:
            bestMove = [x, y]
            bestScore = score
    return bestMove
# 是否游戲結束
def isGameOver(board):
    for x in range(8):
        for y in range(8):
            if board[x][y] == 'none':
                return False
    return True
# 獲取棋盤上黑白雙方的棋子數
def getScoreOfBoard(board):
    xscore = 0
    oscore = 0
    for x in range(8):
        for y in range(8):
            if board[x][y] == 'black':
                xscore += 1
            if board[x][y] == 'white':
                oscore += 1
    return {'black':xscore, 'white':oscore}
主程式中加入游戲結束,顯示雙方棋子數量功能。

if isGameOver(mainBoard): #游戲結束,顯示雙方棋子數量
        scorePlayer = getScoreOfBoard(mainBoard)[playerTile]
        scoreComputer = getScoreOfBoard(mainBoard)[computerTile]
        outputStr = gameoverStr + str(scorePlayer) + ":" + str(scoreComputer)
        text = basicFont.render(outputStr, True, BLACK, BLUE)
        textRect = text.get_rect()
        textRect.centerx = windowSurface.get_rect().centerx
        textRect.centery = windowSurface.get_rect().centery
        windowSurface.blit(text, textRect)

 

至此完成基於Pygame的黑白棋游戲設計。游戲效果如圖所示。今天的分享就到這裡了,下一章見。
在這裡插入圖片描述

在這裡插入圖片描述


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 註意 一定要按照步驟激活 第一步:打開註冊機器,然後點擊patch,找到安裝Navicat15目錄下麵的exe文件 第二步:打開Navicat啟動文件,然後點擊註冊按鈕,然後點擊註冊機器的Generate按鈕,把文本中的內容填寫進去,然後點擊註冊,這時候會顯示註冊失敗,然後點擊手動激活 第三步,在註 ...
  • web前端開發規範 規範概述 一個人走的更快,一群人可以走的更遠,前提是統一的策略,還要不斷地反省和優化。不管有多少人共同參與同一項目,儘可能確保每一行代碼都像是同一個人編寫的 開發目錄規範 開發環境規範 開發編碼規範 一、目錄及文件命名規範 (一)、例靜態專題頁目錄 - src / html 源代 ...
  • 一、首先需要需要引入需要的包 <script src="https://cdn.bootcss.com/xlsx/0.11.5/xlsx.core.min.js"></script> 二、一個上傳文件的file類型的input標簽 <input type="file" onchange="showP ...
  • 註意如果你的mac是M1處理器 那抱歉當前文章可能不支持了,因為當前模擬器不支持。 3步完成mac uniapp 模擬器配置 1.下載網易mumu模擬器 https://mumu.163.com/mac/index.html 2.安裝 設置 下載完成後安裝運行就是這樣的 選擇屏幕旋轉 手機模式 3. ...
  • 工廠方法模式是什麼 工廠方法模式是一種創建型設計模式, 其在父類中提供一個創建對象的方法, 允許子類決定實例化對象的類型。 為什麼用工廠方法模式 在新增一個產品時,不用去修改已有的代碼。工廠方法將創建產品的代碼與實際使用產品的代碼分離,從而能在不影響其他代碼的情況下擴展產品創建部分代碼。例如,如果需 ...
  • 08-Functions, Parameters、 functions、 first class、 function signatures、 parameter、 pass by value、 p... ...
  • java是什麼? java是java面向對象程式設計語言和java平臺的總稱 java的開發平臺 javaSE:標準版 javaEE:企業版 javaME:嵌入式 JRE和JDK JRE:jre是java運行時環境,包含JVM和運行時所需要的核心類庫 JDK:jdk時java程式開發工具包,包含jr ...
  • 方法重載的規則,main方法也可以重載,JVM在調用main方法的時候傳入了一個空字元串數組 構成方法重載的規則: 1.首先必須是在同一個類中 2.函數名相同 3.形參列表不同(形參個數,類型,順序不同都可以構成方法重載) 只有返回值不同不能構成方法重載。 只有訪問修飾符不同也不能構成方法重載 ma ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...