有沒有小火伴是特別喜歡玩五子棋的,我記得我初中是特別喜歡的。於是,我今天就用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的黑白棋游戲設計。游戲效果如圖所示。今天的分享就到這裡了,下一章見。