使用 Python 和 Pygame 实现扫雷游戏 — 完整教程与代码示例

本教程将详细指导你如何使用 Python 编程语言和 Pygame 库从零开始构建一个经典的扫雷游戏。我们将涵盖项目设置、核心游戏逻辑、Pygame 渲染与用户交互的实现,并提供可直接运行的代码片段。

目录

  1. 引言
  2. 项目概览与功能特性
  3. 环境准备与依赖安装
  4. 核心游戏逻辑设计
    1. 游戏板与单元格表示
    2. 地雷的生成与放置
    3. 计算周围地雷数量
    4. 单元格的揭开与旗帜标记
    5. 自动展开空白区域算法
    6. 胜负判定
  5. Pygame 渲染与用户交互
    1. 窗口初始化与基本设置
    2. 绘制游戏板
    3. 处理鼠标事件
    4. 游戏循环与状态更新
  6. 完整示例代码
    1. config.py (配置)
    2. game_logic.py (游戏逻辑)
    3. main.py (主程序与渲染)
  7. 如何运行游戏
  8. 进一步的扩展与优化
  9. 结语

1. 引言

扫雷(Minesweeper)是一款经典的单人益智类游戏,其核心在于推理和排除地雷。本教程将带你一步步使用 Pygame 库,从头实现这款游戏。Pygame 是一个用于开发 2D 游戏和多媒体应用程序的 Python 库,它提供了丰富的功能,包括图形绘制、声音播放、事件处理等。


2. 项目概览与功能特性

我们将实现一个功能相对完整的扫雷游戏,包括:

  • 可配置的游戏板:支持自定义行、列数和地雷数量。
  • 基本交互:鼠标左键揭开方块,右键标记/取消标记旗帜。
  • 智能展开:当揭开一个没有地雷的空白方块时,自动展开周围所有相邻的空白方块,直到遇到数字方块。
  • 胜负判定:踩到地雷则失败,成功揭开所有非地雷方块则胜利。
  • 图形界面:使用 Pygame 绘制游戏板、方块状态(未揭开、已揭开、数字、地雷、旗帜)。

3. 环境准备与依赖安装

在开始之前,请确保你的系统已安装 Python。本教程建议使用 Python 3.8 或更高版本。

  1. 安装 Python
    如果你尚未安装 Python,请访问 Python 官方网站 下载并安装适合你操作系统的版本。安装时请确保勾选 “Add Python to PATH”(将 Python 添加到系统路径)。

  2. 创建虚拟环境(推荐)
    为了项目的依赖隔离,建议创建一个虚拟环境。打开命令行或终端,进入你希望存放项目的目录,然后执行:

    # 创建名为 'venv' 的虚拟环境
    python -m venv venv
    
  3. 激活虚拟环境
    根据你的操作系统,选择相应的命令激活虚拟环境:

    • Windows:
      .\venv\Scripts\activate
      
    • macOS / Linux:
      source venv/bin/activate
      

    激活后,你的命令行提示符前会显示 (venv),表示你已在虚拟环境中。

  4. 安装 Pygame
    在虚拟环境激活的状态下,安装 Pygame 库:

    pip install pygame
    

    你也可以将项目所需依赖写入 requirements.txt 文件:

    # requirements.txt
    pygame
    

    然后通过以下命令安装:

    pip install -r requirements.txt
    

4. 核心游戏逻辑设计

游戏逻辑是扫雷项目的核心。我们将把这部分代码组织在独立的模块中。

4.1 游戏板与单元格表示

我们可以使用一个二维列表(或 NumPy 数组)来表示游戏板。每个单元格需要存储其状态:

  • 是否是地雷
  • 是否已揭开
  • 是否被标记为旗帜
  • 如果不是地雷,周围有多少个地雷(0-8)
# 示例:一个单元格的内部表示
class Cell:
    def __init__(self):
        self.is_mine = False         # 是否是地雷
        self.is_revealed = False     # 是否已揭开
        self.is_flagged = False      # 是否被标记
        self.mines_around = 0        # 周围地雷数量

# 游戏板可以是一个 Cell 对象的二维列表
# 例如:board = [[Cell() for _ in range(cols)] for _ in range(rows)]

4.2 地雷的生成与放置

地雷应该随机但均匀地分布在游戏板上。

  1. 计算总单元格数和要放置的地雷数。
  2. 生成一个包含所有单元格索引的列表。
  3. 随机选择地雷数量的索引,并将对应单元格设置为地雷。
import random

def place_mines(board, rows, cols, num_mines):
    all_cells = [(r, c) for r in range(rows) for c in range(cols)]
    mine_locations = random.sample(all_cells, num_mines)

    for r, c in mine_locations:
        board[r][c].is_mine = True
    return board

4.3 计算周围地雷数量

当地雷放置完毕后,需要遍历所有非地雷单元格,计算其八个方向(包括对角线)相邻单元格中的地雷数量。

def calculate_mines_around(board, rows, cols):
    for r in range(rows):
        for c in range(cols):
            if board[r][c].is_mine:
                continue

            count = 0
            # 检查周围8个方向
            for dr in [-1, 0, 1]:
                for dc in [-1, 0, 1]:
                    if dr == 0 and dc == 0:  # 跳过自身
                        continue
                    nr, nc = r + dr, c + dc
                    if 0 <= nr < rows and 0 <= nc < cols and board[nr][nc].is_mine:
                        count += 1
            board[r][c].mines_around = count
    return board

4.4 单元格的揭开与旗帜标记

  • 左键点击
    • 如果单元格已标记,则不能揭开。
    • 如果单元格是地雷,游戏结束(失败)。
    • 如果单元格没有地雷且 mines_around 为 0,触发自动展开。
    • 将单元格 is_revealed 设为 True
  • 右键点击
    • 如果单元格已揭开,则不能标记。
    • 切换 is_flagged 状态。
def reveal_cell(board, r, c, rows, cols):
    cell = board[r][c]
    if cell.is_revealed or cell.is_flagged:
        return False # 无法揭开

    cell.is_revealed = True
    if cell.is_mine:
        return True # 踩到地雷,游戏失败

    # 如果揭开的单元格周围地雷数为0,则自动展开
    if cell.mines_around == 0:
        auto_expand(board, r, c, rows, cols)
    return False # 未踩到地雷

def toggle_flag(board, r, c):
    cell = board[r][c]
    if not cell.is_revealed:
        cell.is_flagged = not cell.is_flagged

4.5 自动展开空白区域算法

当玩家点击一个没有地雷且周围地雷数为 0 的单元格时,游戏会自动揭开其周围所有相邻的空白单元格(包括对角线),并递归地对这些新揭开的、周围地雷数为 0 的空白单元格重复此操作,直到遇到带有数字的单元格。这通常通过递归或使用队列(BFS)实现。

使用队列(BFS)实现:

from collections import deque

def auto_expand(board, start_r, start_c, rows, cols):
    q = deque([(start_r, start_c)])
    
    while q:
        r, c = q.popleft()
        
        for dr in [-1, 0, 1]:
            for dc in [-1, 0, 1]:
                nr, nc = r + dr, c + dc
                
                if 0 <= nr < rows and 0 <= nc < cols:
                    neighbor_cell = board[nr][nc]
                    if not neighbor_cell.is_revealed and not neighbor_cell.is_flagged:
                        neighbor_cell.is_revealed = True
                        if neighbor_cell.mines_around == 0:
                            q.append((nr, nc)) # 只有周围没有地雷的空白格才继续扩展

4.6 胜负判定

  • 游戏失败:当玩家揭开一个地雷单元格时。
  • 游戏胜利:当所有非地雷单元格都被成功揭开时。
def check_win(board, rows, cols, num_mines):
    revealed_count = 0
    for r in range(rows):
        for c in range(cols):
            if board[r][c].is_revealed and not board[r][c].is_mine:
                revealed_count += 1
    
    return revealed_count == (rows * cols - num_mines)

# 示例:游戏状态
GAME_ACTIVE = 0
GAME_OVER_LOSE = 1
GAME_OVER_WIN = 2

5. Pygame 渲染与用户交互

这部分将处理游戏的视觉呈现和玩家输入。

5.1 窗口初始化与基本设置

设置窗口大小、标题和加载字体等。

import pygame

# 初始化 Pygame
pygame.init()

# 屏幕尺寸和颜色定义 (在单独的 config.py 中定义更好)
SCREEN_WIDTH = 800
SCREEN_HEIGHT = 600
CELL_SIZE = 40
BOARD_ROWS = 15
BOARD_COLS = 15

# 颜色
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
GRAY = (180, 180, 180)
LIGHT_GRAY = (220, 220, 220)
BLUE = (0, 0, 255)
RED = (255, 0, 0)
GREEN = (0, 255, 0)

# 设置屏幕
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
pygame.display.set_caption("Pygame 扫雷")

# 字体
font = pygame.font.Font(None, 36) # 默认字体,大小36

5.2 绘制游戏板

根据每个单元格的状态(未揭开、已揭开、旗帜、地雷、数字)进行绘制。

def draw_board(screen, board, rows, cols, cell_size):
    for r in range(rows):
        for c in range(cols):
            cell_x = c * cell_size
            cell_y = r * cell_size
            rect = pygame.Rect(cell_x, cell_y, cell_size, cell_size)

            cell = board[r][c]

            # 绘制背景
            if cell.is_revealed:
                pygame.draw.rect(screen, LIGHT_GRAY, rect)
                pygame.draw.rect(screen, GRAY, rect, 1) # 边框
                
                if cell.is_mine:
                    pygame.draw.circle(screen, BLACK, rect.center, cell_size // 3) # 绘制地雷
                elif cell.mines_around > 0:
                    text_surface = font.render(str(cell.mines_around), True, BLUE) # 绘制数字
                    text_rect = text_surface.get_rect(center=rect.center)
                    screen.blit(text_surface, text_rect)
            else:
                pygame.draw.rect(screen, GRAY, rect) # 未揭开
                pygame.draw.rect(screen, BLACK, rect, 1)

                if cell.is_flagged:
                    pygame.draw.polygon(screen, RED, [
                        (cell_x + cell_size * 0.25, cell_y + cell_size * 0.25),
                        (cell_x + cell_size * 0.75, cell_y + cell_size * 0.5),
                        (cell_x + cell_size * 0.25, cell_y + cell_size * 0.75)
                    ]) # 绘制旗帜

5.3 处理鼠标事件

Pygame 的事件循环会捕获所有用户输入。我们需要监听 MOUSEBUTTONDOWN 事件来处理玩家的点击。

# 在游戏主循环中
for event in pygame.event.get():
    if event.type == pygame.QUIT:
        running = False
    elif event.type == pygame.MOUSEBUTTONDOWN:
        mouse_x, mouse_y = event.pos
        clicked_col = mouse_x // CELL_SIZE
        clicked_row = mouse_y // CELL_SIZE

        if event.button == 1: # 左键
            game_over_state = reveal_cell(game_board, clicked_row, clicked_col, BOARD_ROWS, BOARD_COLS)
            if game_over_state: # 踩到地雷
                current_game_state = GAME_OVER_LOSE
                # 显示所有地雷
                for r in range(BOARD_ROWS):
                    for c in range(BOARD_COLS):
                        if game_board[r][c].is_mine:
                            game_board[r][c].is_revealed = True
            elif check_win(game_board, BOARD_ROWS, BOARD_COLS, NUM_MINES):
                current_game_state = GAME_OVER_WIN
        elif event.button == 3: # 右键
            toggle_flag(game_board, clicked_row, clicked_col)

5.4 游戏循环与状态更新

游戏的主循环会不断地更新游戏状态和重绘屏幕。

def run_game():
    # 游戏板初始化
    game_board = initialize_board(BOARD_ROWS, BOARD_COLS)
    game_board = place_mines(game_board, BOARD_ROWS, BOARD_COLS, NUM_MINES)
    game_board = calculate_mines_around(game_board, BOARD_ROWS, BOARD_COLS)

    current_game_state = GAME_ACTIVE # 初始状态
    running = True
    
    while running:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                running = False
            
            if current_game_state == GAME_ACTIVE:
                # 处理鼠标点击逻辑 (如上述示例)
                pass # 在此处添加鼠标事件处理代码

        # 绘制背景
        screen.fill(WHITE)
        
        # 绘制游戏板
        draw_board(screen, game_board, BOARD_ROWS, BOARD_COLS, CELL_SIZE)

        # 显示游戏状态信息 (胜利/失败)
        if current_game_state == GAME_OVER_LOSE:
            lose_text = font.render("游戏失败!", True, RED)
            screen.blit(lose_text, (SCREEN_WIDTH // 2 - lose_text.get_width() // 2, SCREEN_HEIGHT // 2))
        elif current_game_state == GAME_OVER_WIN:
            win_text = font.render("恭喜,你赢了!", True, GREEN)
            screen.blit(win_text, (SCREEN_WIDTH // 2 - win_text.get_width() // 2, SCREEN_HEIGHT // 2))
        
        # 更新显示
        pygame.display.flip()

    pygame.quit()

6. 完整示例代码

为了更好的组织,我们将代码分成几个文件。

6.1 config.py (配置)

# config.py
import pygame

# 游戏板配置
BOARD_ROWS = 16
BOARD_COLS = 16
NUM_MINES = 40 # 简单:10, 中等:40, 困难:99

# 视觉配置
CELL_SIZE = 30 # 每个单元格的像素大小
HEADER_HEIGHT = 60 # 顶部信息栏高度
SCREEN_WIDTH = BOARD_COLS * CELL_SIZE
SCREEN_HEIGHT = BOARD_ROWS * CELL_SIZE + HEADER_HEIGHT

# 颜色定义
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
GRAY = (180, 180, 180)
LIGHT_GRAY = (220, 220, 220)
DARK_GRAY = (100, 100, 100)

# 数字颜色 (为了美观,通常数字1-8有不同颜色)
NUM_COLORS = [
    (0, 0, 0),       # 占位符,数字0不显示
    (0, 0, 255),     # 1: 蓝色
    (0, 128, 0),     # 2: 绿色
    (255, 0, 0),     # 3: 红色
    (0, 0, 128),     # 4: 深蓝
    (128, 0, 0),     # 5: 深红
    (0, 128, 128),   # 6: 青色
    (0, 0, 0),       # 7: 黑色 (或灰色)
    (128, 128, 128)  # 8: 灰色
]

# 游戏状态
GAME_ACTIVE = 0
GAME_OVER_LOSE = 1
GAME_OVER_WIN = 2

6.2 game_logic.py (游戏逻辑)

# game_logic.py
import random
from collections import deque
from config import BOARD_ROWS, BOARD_COLS, NUM_MINES, GAME_ACTIVE, GAME_OVER_LOSE, GAME_OVER_WIN

class Cell:
    def __init__(self):
        self.is_mine = False
        self.is_revealed = False
        self.is_flagged = False
        self.mines_around = 0

def initialize_board():
    """初始化一个全新的游戏板"""
    board = [[Cell() for _ in range(BOARD_COLS)] for _ in range(BOARD_ROWS)]
    return board

def place_mines(board):
    """随机放置地雷"""
    all_cells = [(r, c) for r in range(BOARD_ROWS) for c in range(BOARD_COLS)]
    mine_locations = random.sample(all_cells, NUM_MINES)

    for r, c in mine_locations:
        board[r][c].is_mine = True
    return board

def calculate_mines_around(board):
    """计算每个非地雷单元格周围的地雷数量"""
    for r in range(BOARD_ROWS):
        for c in range(BOARD_COLS):
            if board[r][c].is_mine:
                continue

            count = 0
            for dr in [-1, 0, 1]:
                for dc in [-1, 0, 1]:
                    if dr == 0 and dc == 0:
                        continue
                    nr, nc = r + dr, c + dc
                    if 0 <= nr < BOARD_ROWS and 0 <= nc < BOARD_COLS and board[nr][nc].is_mine:
                        count += 1
            board[r][c].mines_around = count
    return board

def reveal_cell(board, r, c):
    """
    揭开一个单元格。
    返回 True 如果踩到地雷,False 否则。
    """
    cell = board[r][c]
    if cell.is_revealed or cell.is_flagged:
        return False

    cell.is_revealed = True
    if cell.is_mine:
        return True # 踩到地雷

    if cell.mines_around == 0:
        auto_expand(board, r, c)
    return False

def auto_expand(board, start_r, start_c):
    """自动展开相邻的空白区域"""
    q = deque([(start_r, start_c)])
    
    while q:
        r, c = q.popleft()
        
        for dr in [-1, 0, 1]:
            for dc in [-1, 0, 1]:
                nr, nc = r + dr, c + dc
                
                if 0 <= nr < BOARD_ROWS and 0 <= nc < BOARD_COLS:
                    neighbor_cell = board[nr][nc]
                    if not neighbor_cell.is_revealed and not neighbor_cell.is_flagged:
                        neighbor_cell.is_revealed = True
                        if neighbor_cell.mines_around == 0:
                            q.append((nr, nc))

def toggle_flag(board, r, c):
    """标记或取消标记一个单元格"""
    cell = board[r][c]
    if not cell.is_revealed:
        cell.is_flagged = not cell.is_flagged
        return True # 成功标记/取消标记
    return False

def check_game_state(board):
    """
    检查当前游戏状态(进行中、胜利、失败)。
    假定在调用此函数前已经处理了踩雷导致失败的情况。
    """
    all_non_mines_revealed = True
    for r in range(BOARD_ROWS):
        for c in range(BOARD_COLS):
            cell = board[r][c]
            if not cell.is_mine and not cell.is_revealed:
                all_non_mines_revealed = False
                break
        if not all_non_mines_revealed:
            break
            
    if all_non_mines_revealed:
        return GAME_OVER_WIN
    
    return GAME_ACTIVE

6.3 main.py (主程序与渲染)

# main.py
import pygame
from config import (
    SCREEN_WIDTH, SCREEN_HEIGHT, CELL_SIZE, BOARD_ROWS, BOARD_COLS, NUM_MINES,
    WHITE, BLACK, GRAY, LIGHT_GRAY, DARK_GRAY, NUM_COLORS, HEADER_HEIGHT,
    GAME_ACTIVE, GAME_OVER_LOSE, GAME_OVER_WIN
)
from game_logic import (
    initialize_board, place_mines, calculate_mines_around,
    reveal_cell, toggle_flag, check_game_state
)

# 初始化 Pygame
pygame.init()
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
pygame.display.set_caption("Pygame 扫雷")

# 字体
font = pygame.font.Font(None, 30) # 用于数字和信息

def draw_board(current_board):
    """绘制游戏板上的所有单元格"""
    for r in range(BOARD_ROWS):
        for c in range(BOARD_COLS):
            cell_x = c * CELL_SIZE
            cell_y = r * CELL_SIZE + HEADER_HEIGHT # 加上顶部偏移

            rect = pygame.Rect(cell_x, cell_y, CELL_SIZE, CELL_SIZE)
            cell = current_board[r][c]

            if cell.is_revealed:
                pygame.draw.rect(screen, LIGHT_GRAY, rect) # 已揭开的背景
                pygame.draw.rect(screen, DARK_GRAY, rect, 1) # 边框
                
                if cell.is_mine:
                    # 绘制地雷 (一个黑色的圆)
                    pygame.draw.circle(screen, BLACK, rect.center, CELL_SIZE // 3)
                elif cell.mines_around > 0:
                    # 绘制数字
                    text_color = NUM_COLORS[cell.mines_around]
                    text_surface = font.render(str(cell.mines_around), True, text_color)
                    text_rect = text_surface.get_rect(center=rect.center)
                    screen.blit(text_surface, text_rect)
            else:
                # 未揭开的方块
                pygame.draw.rect(screen, GRAY, rect)
                pygame.draw.rect(screen, BLACK, rect, 1)
                
                if cell.is_flagged:
                    # 绘制旗帜 (一个红色三角形)
                    pygame.draw.polygon(screen, (255, 0, 0), [
                        (rect.left + CELL_SIZE * 0.25, rect.top + CELL_SIZE * 0.25),
                        (rect.right - CELL_SIZE * 0.25, rect.top + CELL_SIZE * 0.5),
                        (rect.left + CELL_SIZE * 0.25, rect.bottom - CELL_SIZE * 0.25)
                    ])

def draw_header(current_game_state, mines_left):
    """绘制顶部信息栏(地雷剩余数量、游戏状态等)"""
    header_rect = pygame.Rect(0, 0, SCREEN_WIDTH, HEADER_HEIGHT)
    pygame.draw.rect(screen, DARK_GRAY, header_rect) # 顶部背景

    # 剩余地雷数
    mines_text = font.render(f"剩余地雷: {mines_left}", True, WHITE)
    screen.blit(mines_text, (10, 15))

    # 游戏状态信息
    status_text = ""
    text_color = WHITE
    if current_game_state == GAME_OVER_LOSE:
        status_text = "游戏失败!"
        text_color = (255, 50, 50) # 红色
    elif current_game_state == GAME_OVER_WIN:
        status_text = "恭喜,你赢了!"
        text_color = (50, 255, 50) # 绿色
    
    if status_text:
        status_surface = font.render(status_text, True, text_color)
        status_rect = status_surface.get_rect(center=(SCREEN_WIDTH // 2, HEADER_HEIGHT // 2))
        screen.blit(status_surface, status_rect)


def count_flags(board):
    """计算当前标记的旗帜数量"""
    count = 0
    for r in range(BOARD_ROWS):
        for c in range(BOARD_COLS):
            if board[r][c].is_flagged:
                count += 1
    return count

def reset_game():
    """重置游戏到初始状态"""
    new_board = initialize_board()
    new_board = place_mines(new_board)
    new_board = calculate_mines_around(new_board)
    return new_board, GAME_ACTIVE

def main():
    game_board, current_game_state = reset_game() # 初始游戏板和状态

    running = True
    while running:
        mines_left_count = NUM_MINES - count_flags(game_board)

        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                running = False
            elif event.type == pygame.MOUSEBUTTONDOWN:
                # 检查点击是否在游戏板区域内
                if event.pos[1] > HEADER_HEIGHT: # Y 坐标大于顶部信息栏高度
                    clicked_col = event.pos[0] // CELL_SIZE
                    clicked_row = (event.pos[1] - HEADER_HEIGHT) // CELL_SIZE

                    if not (0 <= clicked_row < BOARD_ROWS and 0 <= clicked_col < BOARD_COLS):
                        continue # 点击超出游戏板范围

                    if current_game_state == GAME_ACTIVE: # 只有游戏进行中才能交互
                        if event.button == 1: # 左键
                            mine_hit = reveal_cell(game_board, clicked_row, clicked_col)
                            if mine_hit:
                                current_game_state = GAME_OVER_LOSE
                                # 揭示所有地雷
                                for r in range(BOARD_ROWS):
                                    for c in range(BOARD_COLS):
                                        if game_board[r][c].is_mine:
                                            game_board[r][c].is_revealed = True
                            else:
                                if check_game_state(game_board) == GAME_OVER_WIN:
                                    current_game_state = GAME_OVER_WIN
                        elif event.button == 3: # 右键
                            toggle_flag(game_board, clicked_row, clicked_col)
                    else: # 游戏已结束,点击可重置
                        game_board, current_game_state = reset_game()

        # 渲染
        screen.fill(WHITE) # 填充背景
        draw_header(current_game_state, mines_left_count)
        draw_board(game_board)
        
        pygame.display.flip() # 更新显示

    pygame.quit()

if __name__ == "__main__":
    main()

7. 如何运行游戏

  1. 保存代码
    将上述三个代码块分别保存为:

    • config.py
    • game_logic.py
    • main.py
      确保它们都在同一个文件夹下。
  2. 打开命令行/终端
    进入你存放这些文件的目录。

  3. 激活虚拟环境(如果之前创建了):

    • Windows: .\venv\Scripts\activate
    • macOS / Linux: source venv/bin/activate
  4. 运行主程序

    python main.py
    

    这时,你将看到一个 Pygame 窗口弹出,扫雷游戏界面应该会显示出来。


8. 进一步的扩展与优化

这个基础版本可以作为你进一步开发的起点。你可以考虑添加以下功能来增强游戏体验:

  • 计时器:在顶部信息栏显示游戏时间。
  • 难度选择:在游戏开始前让玩家选择简单、中等或困难模式,并根据选择调整 BOARD_ROWS, BOARD_COLS, NUM_MINES
  • 游戏重新开始按钮:在游戏结束时显示一个“再玩一次”的按钮。
  • 中键点击展开:实现当数字方块周围标记的旗帜数量等于数字时,中键点击该方块自动揭开周围未标记的方块。
  • 音效:点击、标记、踩雷、胜利等音效。
  • 动画效果:揭开方块、爆炸等简单动画。
  • 自定义图案/主题:允许用户更换方块或地雷的图片。
  • 更完善的错误处理:例如点击超出边界。
  • 记录最佳时间:保存玩家在不同难度下的最佳通关时间。

9. 结语

通过本教程,你已经学习了如何使用 Python 和 Pygame 从零开始构建一个扫雷游戏。这不仅涵盖了 Pygame 的基础用法,还深入探讨了扫雷游戏的核心算法。希望这个项目能帮助你更好地理解游戏开发逻辑,并激发你进一步探索和创造的热情!

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐