目录

1. 前言

2. 准备工作

3. 生成雷区

4. 鼠标点击扫雷

5. 胜利 or 失败

6. 游戏效果展示

7. 完整代码


1. 前言

本文使用 Pygame 实现的简化版扫雷游戏。

如上图所示,游戏包括基本的扫雷功能:生成雷区左键点击扫雷右键标记地雷显示数字提示等。

2. 准备工作

首先,当然要下载pygame 库文件,可以通过下面命令下载

pip install pygame

在这之前,我们需要提前规划好前期工作,例如游戏窗口多大,生成图形显示的颜色等等。

这里为了方便,我们采用大多数默认的版本,这里生成的格子数量就是 (400 / 40)*(400/40),也就是100个窗格

import pygame
import random

# 初始化 Pygame
pygame.init()

# 屏幕设置
SCREEN_WIDTH = 400
SCREEN_HEIGHT = 400
CELL_SIZE = 40
GRID_WIDTH = SCREEN_WIDTH // CELL_SIZE
GRID_HEIGHT = SCREEN_HEIGHT // CELL_SIZE

# 颜色定义
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
GRAY = (200, 200, 200)
RED = (255, 0, 0)
GREEN = (0, 255, 0)

# 字体设置
font = pygame.font.SysFont("Arial", 20)

如下:

3. 生成雷区

有了窗口格子区域,接下来就可以生成雷区,这里采用random函数随机生成,保证每次打开游戏雷区的位置不一样

# 生成雷区
def create_grid(width, height, num_mines):
    grid = [[0 for _ in range(width)] for _ in range(height)]
    mines = set()
    while len(mines) < num_mines:
        x = random.randint(0, width - 1)
        y = random.randint(0, height - 1)
        mines.add((x, y))
        grid[y][x] = -1  # -1 表示地雷

    # 计算每个格子周围的地雷数量
    for y in range(height):
        for x in range(width):
            if grid[y][x] == -1:
                continue
            count = 0
            for dy in [-1, 0, 1]:
                for dx in [-1, 0, 1]:
                    if 0 <= x + dx < width and 0 <= y + dy < height:
                        if grid[y + dy][x + dx] == -1:
                            count += 1
            grid[y][x] = count
    return grid, mines
  • 使用 create_grid 函数生成雷区,随机放置地雷,并计算每个格子周围的地雷数量。

  •  

    4. 鼠标点击扫雷

    生成雷区后,下面就是扫雷环节,之前写C语言扫雷,还需要在控制台键入区域。这里可以直接调用鼠标

    # 绘制格子
    def draw_grid():
        for y in range(GRID_HEIGHT):
            for x in range(GRID_WIDTH):
                rect = pygame.Rect(x * CELL_SIZE, y * CELL_SIZE, CELL_SIZE, CELL_SIZE)
                if revealed[y][x]:
                    if grid[y][x] == -1:
                        pygame.draw.rect(screen, RED, rect)  # 地雷
                    else:
                        pygame.draw.rect(screen, GRAY, rect)
                        if grid[y][x] > 0:
                            text = font.render(str(grid[y][x]), True, BLACK)
                            screen.blit(text, (x * CELL_SIZE + 10, y * CELL_SIZE + 10))
                else:
                    pygame.draw.rect(screen, WHITE, rect)
                    if flagged[y][x]:
                        pygame.draw.circle(screen, GREEN, rect.center, 10)  # 标记地雷
                pygame.draw.rect(screen, BLACK, rect, 1)  # 格子边框
    
    
    # 翻开格子
    def reveal_cell(x, y):
        if 0 <= x < GRID_WIDTH and 0 <= y < GRID_HEIGHT and not revealed[y][x]:
            revealed[y][x] = True
            if grid[y][x] == 0:
                for dy in [-1, 0, 1]:
                    for dx in [-1, 0, 1]:
                        reveal_cell(x + dx, y + dy)  # 递归翻开空白区域
    

    5. 胜利 or 失败

    胜利条件:所有非地雷格子都被翻开时,玩家胜利。

  • 游戏结束显示

  • 如果踩到地雷,显示 "Game Over!"。

  • 如果胜利,显示 "You Win!"。

  • # 检查是否胜利
    def check_win():
        for y in range(GRID_HEIGHT):
            for x in range(GRID_WIDTH):
                if grid[y][x] != -1 and not revealed[y][x]:
                    return False
        return True

    6. 游戏效果展示

    失败:

    胜利: 

    7. 完整代码

    直接复制到py脚本运行即可:

    import pygame
    import random
    
    # 初始化 Pygame
    pygame.init()
    
    # 屏幕设置
    SCREEN_WIDTH = 400
    SCREEN_HEIGHT = 400
    CELL_SIZE = 40
    GRID_WIDTH = SCREEN_WIDTH // CELL_SIZE
    GRID_HEIGHT = SCREEN_HEIGHT // CELL_SIZE
    
    # 颜色定义
    WHITE = (255, 255, 255)
    BLACK = (0, 0, 0)
    GRAY = (200, 200, 200)
    RED = (255, 0, 0)
    GREEN = (0, 255, 0)
    
    # 字体设置
    font = pygame.font.SysFont("Arial", 20)
    
    # 初始化屏幕
    screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
    pygame.display.set_caption("Minesweeper")
    
    # 游戏状态
    game_over = False
    win = False
    
    
    # 生成雷区
    def create_grid(width, height, num_mines):
        grid = [[0 for _ in range(width)] for _ in range(height)]
        mines = set()
        while len(mines) < num_mines:
            x = random.randint(0, width - 1)
            y = random.randint(0, height - 1)
            mines.add((x, y))
            grid[y][x] = -1  # -1 表示地雷
    
        # 计算每个格子周围的地雷数量
        for y in range(height):
            for x in range(width):
                if grid[y][x] == -1:
                    continue
                count = 0
                for dy in [-1, 0, 1]:
                    for dx in [-1, 0, 1]:
                        if 0 <= x + dx < width and 0 <= y + dy < height:
                            if grid[y + dy][x + dx] == -1:
                                count += 1
                grid[y][x] = count
        return grid, mines
    
    
    # 初始化雷区
    grid, mines = create_grid(GRID_WIDTH, GRID_HEIGHT, 10)
    
    # 记录翻开的格子和标记的地雷
    revealed = [[False for _ in range(GRID_WIDTH)] for _ in range(GRID_HEIGHT)]
    flagged = [[False for _ in range(GRID_WIDTH)] for _ in range(GRID_HEIGHT)]
    
    
    # 绘制格子
    def draw_grid():
        for y in range(GRID_HEIGHT):
            for x in range(GRID_WIDTH):
                rect = pygame.Rect(x * CELL_SIZE, y * CELL_SIZE, CELL_SIZE, CELL_SIZE)
                if revealed[y][x]:
                    if grid[y][x] == -1:
                        pygame.draw.rect(screen, RED, rect)  # 地雷
                    else:
                        pygame.draw.rect(screen, GRAY, rect)
                        if grid[y][x] > 0:
                            text = font.render(str(grid[y][x]), True, BLACK)
                            screen.blit(text, (x * CELL_SIZE + 10, y * CELL_SIZE + 10))
                else:
                    pygame.draw.rect(screen, WHITE, rect)
                    if flagged[y][x]:
                        pygame.draw.circle(screen, GREEN, rect.center, 10)  # 标记地雷
                pygame.draw.rect(screen, BLACK, rect, 1)  # 格子边框
    
    
    # 翻开格子
    def reveal_cell(x, y):
        if 0 <= x < GRID_WIDTH and 0 <= y < GRID_HEIGHT and not revealed[y][x]:
            revealed[y][x] = True
            if grid[y][x] == 0:
                for dy in [-1, 0, 1]:
                    for dx in [-1, 0, 1]:
                        reveal_cell(x + dx, y + dy)  # 递归翻开空白区域
    
    
    # 检查是否胜利
    def check_win():
        for y in range(GRID_HEIGHT):
            for x in range(GRID_WIDTH):
                if grid[y][x] != -1 and not revealed[y][x]:
                    return False
        return True
    
    # 游戏主循环
    clock = pygame.time.Clock()
    running = True
    
    
    while running:
        screen.fill(WHITE)
    
        # 事件处理
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                running = False
            if not game_over and not win:
                if event.type == pygame.MOUSEBUTTONDOWN:
                    x, y = event.pos
                    grid_x = x // CELL_SIZE
                    grid_y = y // CELL_SIZE
                    if event.button == 1:  # 左键翻开格子
                        if grid[grid_y][grid_x] == -1:
                            game_over = True  # 踩到地雷
                        else:
                            reveal_cell(grid_x, grid_y)
                            if check_win():
                                win = True
                    elif event.button == 3:  # 右键标记地雷
                        if not revealed[grid_y][grid_x]:
                            flagged[grid_y][grid_x] = not flagged[grid_y][grid_x]
    
        # 绘制雷区
        draw_grid()
    
        # 游戏结束显示
        if game_over:
            text = font.render("Game Over!", True, RED)
            screen.blit(text, (SCREEN_WIDTH // 2 - 60, SCREEN_HEIGHT // 2 - 10))
        if win:
            text = font.render("You Win!", True, GREEN)
            screen.blit(text, (SCREEN_WIDTH // 2 - 50, SCREEN_HEIGHT // 2 - 10))
    
        # 更新屏幕
        pygame.display.flip()
        clock.tick(30)
    
    # 退出游戏
    pygame.quit()
    

     

    作者:听风吹等浪起

    物联沃分享整理
    物联沃-IOTWORD物联网 » python 小游戏:扫雷

    发表回复