本文將示範如何使用 Python 搭配 Pygame 函式庫,開發一個經典的 3x3 滑塊拼圖遊戲。程式碼包含遊戲盤面初始化、方塊移動邏輯、滑鼠鍵盤事件處理以及勝利判定等核心功能。
請確認已安裝 Python 與 Pygame:
pip install pygame
並準備一張名為 pic.bmp 的圖片置於程式同目錄,作為拼圖素材。
import pygame, sys, random
from pygame.locals import *
WINDOWWIDTH = 500
WINDOWHEIGHT = 500
BACKGROUNDCOLOR = (255, 255, 255)
BLUE = (0, 0, 255)
BLACK = (0, 0, 0)
FPS = 40
VHNUMS = 3 # 直向與橫向格數
CELLNUMS = VHNUMS * VHNUMS # 總格數
MAXRANDTIME = 100 # 打亂盤面的隨機移動次數
def terminate():
pygame.quit()
sys.exit()
從有序狀態出發,隨機移動空白格 MAXRANDTIME 次,確保盤面可解。
def newGameBoard():
board = list(range(CELLNUMS))
blackCell = CELLNUMS - 1
board[blackCell] = -1 # -1 代表空白格
for _ in range(MAXRANDTIME):
direction = random.randint(0, 3)
if direction == 0: blackCell = moveLeft(board, blackCell)
elif direction == 1: blackCell = moveRight(board, blackCell)
elif direction == 2: blackCell = moveUp(board, blackCell)
elif direction == 3: blackCell = moveDown(board, blackCell)
return board, blackCell
各函式檢查邊界,合法則交換空白格與相鄰格子,並回傳新空白格索引。
def moveRight(board, blackCell):
if blackCell % VHNUMS == 0: return blackCell
board[blackCell-1], board[blackCell] = board[blackCell], board[blackCell-1]
return blackCell-1
def moveLeft(board, blackCell):
if blackCell % VHNUMS == VHNUMS-1: return blackCell
board[blackCell+1], board[blackCell] = board[blackCell], board[blackCell+1]
return blackCell+1
def moveDown(board, blackCell):
if blackCell < VHNUMS: return blackCell
board[blackCell-VHNUMS], board[blackCell] = board[blackCell], board[blackCell-VHNUMS]
return blackCell-VHNUMS
def moveUp(board, blackCell):
if blackCell >= CELLNUMS-VHNUMS: return blackCell
board[blackCell+VHNUMS], board[blackCell] = board[blackCell], board[blackCell+VHNUMS]
return blackCell+VHNUMS
def isFinished(board, blackCell):
for i in range(CELLNUMS-1):
if board[i] != i:
return False
return True
pygame.init()
mainClock = pygame.time.Clock()
# 載入圖片並依格數計算單格寬高
gameImage = pygame.image.load('pic.bmp')
gameRect = gameImage.get_rect()
windowSurface = pygame.display.set_mode((gameRect.width, gameRect.height))
pygame.display.set_caption('拼圖遊戲')
cellWidth = gameRect.width // VHNUMS
cellHeight = gameRect.height // VHNUMS
finish = False
gameBoard, blackCell = newGameBoard()
while True:
for event in pygame.event.get():
if event.type == QUIT:
terminate()
if finish:
continue
if event.type == KEYDOWN:
if event.key in (K_LEFT, ord('a')):
blackCell = moveLeft(gameBoard, blackCell)
elif event.key in (K_RIGHT, ord('d')):
blackCell = moveRight(gameBoard, blackCell)
elif event.key in (K_UP, ord('w')):
blackCell = moveUp(gameBoard, blackCell)
elif event.key in (K_DOWN, ord('s')):
blackCell = moveDown(gameBoard, blackCell)
elif event.type == MOUSEBUTTONDOWN and event.button == 1:
x, y = pygame.mouse.get_pos()
col = x // cellWidth
row = y // cellHeight
index = col + row * VHNUMS
# 點擊的格子若與空白格相鄰則移動
if index in (blackCell-1, blackCell+1, blackCell-VHNUMS, blackCell+VHNUMS):
gameBoard[blackCell], gameBoard[index] = gameBoard[index], gameBoard[blackCell]
blackCell = index
# 檢查是否完成
if isFinished(gameBoard, blackCell):
gameBoard[blackCell] = CELLNUMS - 1
finish = True
# 繪製畫面
windowSurface.fill(BACKGROUNDCOLOR)
for i in range(CELLNUMS):
rowDst = i // VHNUMS
colDst = i % VHNUMS
rectDst = pygame.Rect(colDst*cellWidth, rowDst*cellHeight, cellWidth, cellHeight)
if gameBoard[i] == -1:
continue
rowArea = gameBoard[i] // VHNUMS
colArea = gameBoard[i] % VHNUMS
rectArea = pygame.Rect(colArea*cellWidth, rowArea*cellHeight, cellWidth, cellHeight)
windowSurface.blit(gameImage, rectDst, rectArea)
# 畫格線
for i in range(VHNUMS+1):
pygame.draw.line(windowSurface, BLACK, (i*cellWidth, 0), (i*cellWidth, gameRect.height))
pygame.draw.line(windowSurface, BLACK, (0, i*cellHeight), (gameRect.width, i*cellHeight))
pygame.display.update()
mainClock.tick(FPS)
此範例展示了 Pygame 處理圖形繪製、事件迴圈與遊戲狀態管理的基本架構。您可以嘗試擴充功能,例如增加計步器、計時器、不同難度(4x4、5x5)或自訂圖片載入介面。