当前位置: 首页 > article >正文

python 小游戏:扫雷

目录

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

 


http://www.kler.cn/a/535470.html

相关文章:

  • 【2】高并发导出场景下,服务器性能瓶颈优化方案-异步导出
  • 【玩转全栈】--创建一个自己的vue项目
  • 基础篇05-直方图操作
  • 【深度学习】基于MXNet的多层感知机的实现
  • Selenium记录RPA初阶 - 基本输入元件
  • SpringBoot开发(五)SpringBoot接收请求参数
  • JVM与Java体系结构
  • 【贪心算法篇】:“贪心”之旅--算法练习题中的智慧与策略(四)
  • VUE小技能:通过 Prop 向子组件传递数据
  • 【游戏设计】游戏中的玩法与规则
  • 虹科波形小课堂 | 三分钟掌握车辆相对压缩测试!不拆发动机、不测缸压就能判断故障缸!
  • 深度学习-103-RAG技术之通过分块技术提升RAG的效果
  • 从零开始:OpenCV 图像处理快速入门教程
  • 1.8 组合模式(Composite Pattern)
  • Three.js 实现海面效果
  • Java面试题及答案整理( 2023年 6 月最新版,持续更新)
  • Java面试知识点总结
  • Monorepo保姆级教程
  • SpringCloud详细讲解
  • ubuntu linux 内核锁定
  • WindowsServer搭建内网Gitea【中文更方便使用】
  • 打造高效Facebook矩阵账号运营策略
  • 【码道初阶】Floyd判圈法个人总结:快慢双指针判断环形列表(适用Leetcode142)
  • Java全栈项目-校园闲置教室查询系统
  • 【漫画机器学习】082.岭回归(或脊回归)中的α值(alpha in ridge regression)
  • 机器学习模型--线性回归、逻辑回归、分类