python 小游戏:扫雷

发布于:2025-02-10 ⋅ 阅读:(120) ⋅ 点赞:(0)

目录

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()

 


网站公告

今日签到

点亮在社区的每一天
去签到