官术网_书友最值得收藏!

2.2 編寫第一個小游戲

本書以游戲為編程主題,下面就讓我們嘗試編寫一個井字棋游戲來熱身。編寫該游戲一方面是為了復習我們以前學過的Python知識,另一方面也可以讓我們更熟悉VS Code。

井字棋游戲很簡單,它的棋盤是一個3×3的網格,玩家率先實現3顆棋子在一條直線上即可勝利。本游戲程序包含的核心數據就是棋盤信息,另外還需要若干函數來承載游戲功能,例如顯示棋盤信息的函數、處理玩家輸入的函數,以及判斷棋局勝負的函數等。所有代碼都在一個代碼文件中。

首先定義幾個變量,包括棋盤大小變量boardSize和棋盤信息變量board。我們會使用兩種符號分別表示兩個玩家的落子,其中一個玩家的落子使用字母符號“X”來表示,而另一個玩家的落子使用字母符號“O”來表示,當棋盤上還沒有玩家落子時,所有位置都以符號“.”來表示。先手玩家使用字母符號“X”來落子,將落子信息保存在變量currentPlayer中。隨后輸出一些游戲提示信息。

boardSize = 3
board = ['.'] * boardSize * boardSize
currentPlayer = 'X'
 
print("井字棋游戲開始")
print("規則:三子連成直線即勝利")
print("X先手,O后手")

隨后我們定義print_board函數,它負責在終端上顯示棋盤信息。

def print_board(board):
    print("\n")
    print("%s|%s|%s"%(board[0],board[1],board[2]))
    print("-+-+-")
    print("%s|%s|%s"%(board[3],board[4],board[5]))
    print("-+-+-")
print("%s|%s|%s"%(board[6],board[7],board[8]))

我們還需要一個函數來負責判斷勝負。函數hasWon看起來很復雜,但其內在邏輯很簡單,就是列舉各種可能獲勝的棋局狀態,只要滿足這種狀態就返回True。如果覺得某個地方不容易理解,可以通過VS Code設置斷點,并按鍵盤上的F5鍵進入調試模式,在調試模式下可以一步步地運行代碼,以觀察每個變量的值并理解代碼的運行邏輯。

def hasWon(currentBoard,player):
    winningSet=[player in range(boardSize)]
 
    row1=currentBoard[:3]
    row2=currentBoard[3:6]
    row3=currentBoard[6:]
    if winningSet in [row1,row2,row3]:
        return True
 
    col1=[currentBoard[0],currentBoard[3],currentBoard[6]]
    col2=[currentBoard[1],currentBoard[4],currentBoard[7]]
    col3=[currentBoard[2],currentBoard[5],currentBoard[8]]
    if winningSet in[col1,col2,col3]:
        return True
 
    diag1=[currentBoard[0],currentBoard[4],currentBoard[8]]
    diag2=[currentBoard[6],currentBoard[4],currentBoard[2]]
    if winningSet in [diag1,diag2]:
        return True
 
return False

因為兩個玩家交替落子,所以需要定義getNextPlayer函數以交換當前玩家。

def getNextPlayer(currentPlayer):
    if currentPlayer == 'X':
        return 'O'
return 'X'

getPlayerMove函數用來處理玩家的輸入。玩家輸入的是坐標的形式,每次需要輸入兩個數字,數字之間以英文逗號間隔,數字取值為0~2。“X,Y”表示落子位置在棋盤上的第X行、第Y列。需要注意的是,該函數獲取玩家輸入后,會將這些輸入信息通過字符串操作拆分成兩部分,再轉換成整數類型保存為坐標,最后將二維的坐標信息轉換成一維的索引。判斷當前棋盤的落子位置為空白位置時,就用當前玩家的表示落子的字母符號進行賦值。

def getPlayerMove(board,currentPlayer):
    isMoveValid = False
    while isMoveValid == False:
        print('')
        userMove = input(f'玩家{currentPlayer}輸入棋盤坐標(坐標取值0,1,2):    X,Y?    ')
        userX, userY = [int(char) for char in userMove.split(',')]
        userIndex = userX * boardSize + userY
        if board[userIndex] == '.':
            isMoveValid = True
 
    board[userIndex] = currentPlayer
return board

當棋盤上擺滿棋子時,需要結束游戲,因此要定義一個hasMovesLeft函數來判斷還有沒有空白位置供玩家落子。

def hasMovesLeft(board):
return '.' in board

最后將這些函數組裝在一起。

if __name__ == '__main__':
    print_board(board)
    while hasMovesLeft(board):
        board = getPlayerMove(board,currentPlayer)
        print_board(board)
        if hasWon(board, currentPlayer):
            print('Player'+currentPlayer+'haswon!')
            break
currentPlayer = getNextPlayer(currentPlayer)

首先顯示棋盤,只要棋盤上還有空白位置可以下棋,就保持運行游戲主循環中的代碼。代碼先處理玩家輸入,顯示新的棋盤;如果出現勝負結果,就顯示相關信息。否則輪換玩家。游戲畫面如圖2-3所示。

圖2-3

這個游戲是不是很簡單。讀者可以先試著玩一下。如果不能很好地理解這些代碼,可以進入調試模式慢慢理解每行代碼完成的任務。如果你對某些語法不熟悉,可以先復習、鞏固對應的知識。

主站蜘蛛池模板: 宜章县| 文成县| 双峰县| 浙江省| 定安县| 普格县| 玛纳斯县| 巴林左旗| 阜平县| 怀安县| 龙江县| 广平县| 亳州市| 金门县| 库伦旗| 油尖旺区| 托克逊县| 长寿区| 金阳县| 南京市| 澎湖县| 临清市| 木里| 漳州市| 天津市| 连州市| 镇赉县| 福泉市| 康乐县| 祁门县| 东莞市| 德令哈市| 垦利县| 九台市| 志丹县| 嘉定区| 福建省| 出国| 江都市| 沐川县| 易门县|