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

海洋承德网站建设公司店铺推广语

海洋承德网站建设公司,店铺推广语,门户网站建设方案公司,吉林品牌网站建设商家整体架构设计游戏采用经典的MVC(模型-视图-控制器)架构模式:模型(Model):Minesweeper和Cell类,负责游戏逻辑和数据视图(View):draw_menu()和draw_game()函数,负责界面渲染控制器(Controller)&am…

整体架构设计

游戏采用经典的MVC(模型-视图-控制器)架构模式:

  • 模型(Model)MinesweeperCell类,负责游戏逻辑和数据

  • 视图(View)draw_menu()draw_game()函数,负责界面渲染

  • 控制器(Controller)main()函数中的事件循环,处理用户输入

核心数据结构

Cell类

每个格子对象保存了游戏所需的所有状态信息。

class Cell:def __init__(self, x, y):self.x = x  # 格子x坐标self.y = y  # 格子y坐标self.is_mine = False  # 是否是地雷self.is_revealed = False  # 是否已揭开self.is_flagged = False  # 是否被标记self.neighbor_mines = 0  # 周围地雷数

Minesweeper类

游戏主类管理整个游戏状态。

class Minesweeper:def __init__(self, difficulty=1):self.grid = [[Cell(x, y) for y in range(GRID_HEIGHT)] for x in range(GRID_WIDTH)]self.game_over = Falseself.win = Falseself.first_click = Trueself.difficulty = difficultyself.mine_count = MINE_COUNTS[difficulty]self.place_mines()self.calculate_neighbors()self.start_time = 0self.elapsed_time = 0

关键算法实现

地雷布置算法

使用随机数生成地雷位置,确保不会重复在同一个位置放置地雷。

def place_mines(self):mines_placed = 0while mines_placed < self.mine_count:x = random.randint(0, GRID_WIDTH - 1)y = random.randint(0, GRID_HEIGHT - 1)if not self.grid[x][y].is_mine:self.grid[x][y].is_mine = Truemines_placed += 1

 计算相邻地雷数

def calculate_neighbors(self):for x in range(GRID_WIDTH):for y in range(GRID_HEIGHT):if not self.grid[x][y].is_mine:total = 0for dx in [-1, 0, 1]:for dy in [-1, 0, 1]:nx, ny = x + dx, y + dyif 0 <= nx < GRID_WIDTH and 0 <= ny < GRID_HEIGHT and self.grid[nx][ny].is_mine:total += 1self.grid[x][y].neighbor_mines = total

揭开格子算法

def reveal(self, x, y):if not (0 <= x < GRID_WIDTH and 0 <= y < GRID_HEIGHT) or self.grid[x][y].is_revealed or self.grid[x][y].is_flagged:returnif self.first_click:self.start_time = pygame.time.get_ticks()self.first_click = Falseself.grid[x][y].is_revealed = Trueif self.grid[x][y].is_mine:self.game_over = Trueself.reveal_all_mines()returnif self.grid[x][y].neighbor_mines == 0:for dx in [-1, 0, 1]:for dy in [-1, 0, 1]:self.reveal(x + dx, y + dy)self.check_win()

界面设计思路

状态分离

  • 开始菜单:显示游戏标题、难度选择和操作说明

  • 游戏界面:顶部状态栏+底部游戏网格,胜利/失败时显示覆盖层

视觉反馈

  • 不同难度使用不同颜色按钮(绿-黄-红)

  • 数字使用不同颜色增强可读性

  • 半透明覆盖层显示游戏结果不遮挡游戏界面

交互设计

# 主事件循环
for event in pygame.event.get():if event.type == QUIT:pygame.quit()sys.exit()if event.type == MOUSEBUTTONDOWN:mouse_x, mouse_y = pygame.mouse.get_pos()if restart_rect.collidepoint(mouse_x, mouse_y):in_game = Falseelif not game.game_over and mouse_y >= 100:grid_x, grid_y = mouse_x // GRID_SIZE, (mouse_y - 100) // GRID_SIZEif 0 <= grid_x < GRID_WIDTH and 0 <= grid_y < GRID_HEIGHT:if event.button == 1:  # 左键game.reveal(grid_x, grid_y)elif event.button == 3:  # 右键game.toggle_flag(grid_x, grid_y)

 游戏流程设计

  1. 初始化:创建窗口、加载字体、设置常量

  2. 菜单循环:显示开始菜单,等待玩家选择难度

  3. 游戏循环

    • 初始化游戏状态

    • 处理玩家输入

    • 更新游戏状态

    • 渲染游戏界面

  4. 结束处理:显示结果,提供重新开始选项

关键设计决策

首次点击保护:确保玩家第一次点击不会是地雷。

if game.first_click and game.grid[grid_x][grid_y].is_mine:while game.grid[grid_x][grid_y].is_mine:game = Minesweeper(game.difficulty)

递归揭开空白区域:自动揭开相连的空白区域,提升游戏体验。

if self.grid[x][y].neighbor_mines == 0:for dx in [-1, 0, 1]:for dy in [-1, 0, 1]:self.reveal(x + dx, y + dy)

 状态分离:明确区分游戏状态和渲染逻辑,使代码更易维护。

完整代码

import pygame
import random
import sys
from pygame.locals import *# 游戏常量
WINDOW_WIDTH = 400
WINDOW_HEIGHT = 500
GRID_SIZE = 40
GRID_WIDTH = 10
GRID_HEIGHT = 10
MINE_COUNTS = [10, 15, 20]  # 简单、中等、困难的地雷数量# 颜色定义
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
GRAY = (192, 192, 192)
DARK_GRAY = (128, 128, 128)
RED = (255, 0, 0)
BLUE = (0, 0, 255)
GREEN = (0, 128, 0)
LIGHT_BLUE = (173, 216, 230)# 初始化pygame
pygame.init()
WINDOW = pygame.display.set_mode((WINDOW_WIDTH, WINDOW_HEIGHT))
pygame.display.set_caption('扫雷')
FONT = pygame.font.SysFont('simhei', 30)
SMALL_FONT = pygame.font.SysFont('simhei', 20)
MEDIUM_FONT = pygame.font.SysFont('simhei', 24)class Cell:def __init__(self, x, y):self.x = xself.y = yself.is_mine = Falseself.is_revealed = Falseself.is_flagged = Falseself.neighbor_mines = 0def draw(self):rect = pygame.Rect(self.x * GRID_SIZE, self.y * GRID_SIZE + 100, GRID_SIZE, GRID_SIZE)if not self.is_revealed:pygame.draw.rect(WINDOW, GRAY, rect)pygame.draw.rect(WINDOW, WHITE, rect, 1)if self.is_flagged:flag_text = FONT.render("旗", True, RED)WINDOW.blit(flag_text, (self.x * GRID_SIZE + 10, self.y * GRID_SIZE + 100))else:pygame.draw.rect(WINDOW, WHITE, rect)pygame.draw.rect(WINDOW, DARK_GRAY, rect, 1)if self.is_mine:mine_text = FONT.render("雷", True, BLACK)WINDOW.blit(mine_text, (self.x * GRID_SIZE + 10, self.y * GRID_SIZE + 100))elif self.neighbor_mines > 0:colors = [BLUE, GREEN, RED, (0, 0, 128), (128, 0, 0), (0, 128, 128), BLACK, GRAY]text = FONT.render(str(self.neighbor_mines), True, colors[self.neighbor_mines - 1])WINDOW.blit(text, (self.x * GRID_SIZE + 15, self.y * GRID_SIZE + 105))class Minesweeper:def __init__(self, difficulty=1):self.grid = [[Cell(x, y) for y in range(GRID_HEIGHT)] for x in range(GRID_WIDTH)]self.game_over = Falseself.win = Falseself.first_click = Trueself.difficulty = difficultyself.mine_count = MINE_COUNTS[difficulty]self.place_mines()self.calculate_neighbors()self.start_time = 0self.elapsed_time = 0self.paused = Falseself.pause_time = 0self.total_paused_time = 0def place_mines(self):mines_placed = 0while mines_placed < self.mine_count:x = random.randint(0, GRID_WIDTH - 1)y = random.randint(0, GRID_HEIGHT - 1)if not self.grid[x][y].is_mine:self.grid[x][y].is_mine = Truemines_placed += 1def calculate_neighbors(self):for x in range(GRID_WIDTH):for y in range(GRID_HEIGHT):if not self.grid[x][y].is_mine:total = 0for dx in [-1, 0, 1]:for dy in [-1, 0, 1]:nx, ny = x + dx, y + dyif 0 <= nx < GRID_WIDTH and 0 <= ny < GRID_HEIGHT and self.grid[nx][ny].is_mine:total += 1self.grid[x][y].neighbor_mines = totaldef reveal(self, x, y):if not (0 <= x < GRID_WIDTH and 0 <= y < GRID_HEIGHT) or self.grid[x][y].is_revealed or self.grid[x][y].is_flagged or self.paused:returnif self.first_click:self.start_time = pygame.time.get_ticks()self.first_click = Falseself.grid[x][y].is_revealed = Trueif self.grid[x][y].is_mine:self.game_over = Trueself.reveal_all_mines()returnif self.grid[x][y].neighbor_mines == 0:for dx in [-1, 0, 1]:for dy in [-1, 0, 1]:self.reveal(x + dx, y + dy)self.check_win()def reveal_all_mines(self):for x in range(GRID_WIDTH):for y in range(GRID_HEIGHT):if self.grid[x][y].is_mine:self.grid[x][y].is_revealed = Truedef toggle_flag(self, x, y):if not self.game_over and not self.grid[x][y].is_revealed and not self.paused:self.grid[x][y].is_flagged = not self.grid[x][y].is_flaggeddef check_win(self):for x in range(GRID_WIDTH):for y in range(GRID_HEIGHT):if not self.grid[x][y].is_mine and not self.grid[x][y].is_revealed:returnself.game_over = Trueself.win = Trueself.elapsed_time = (pygame.time.get_ticks() - self.start_time - self.total_paused_time) // 1000def toggle_pause(self):if not self.game_over:self.paused = not self.pausedif self.paused:self.pause_time = pygame.time.get_ticks()else:self.total_paused_time += pygame.time.get_ticks() - self.pause_timedef draw_game(self):# 绘制游戏状态栏pygame.draw.rect(WINDOW, LIGHT_BLUE, (0, 0, WINDOW_WIDTH, 100))# 显示难度difficulties = ["简单", "中等", "困难"]diff_text = MEDIUM_FONT.render(f"难度: {difficulties[self.difficulty]}", True, BLACK)WINDOW.blit(diff_text, (20, 20))# 显示剩余地雷数flags = sum(cell.is_flagged for row in self.grid for cell in row)mines_text = MEDIUM_FONT.render(f"剩余地雷: {self.mine_count - flags}", True, BLACK)WINDOW.blit(mines_text, (20, 50))# 显示用时if not self.first_click and not self.game_over and not self.paused:self.elapsed_time = (pygame.time.get_ticks() - self.start_time - self.total_paused_time) // 1000# 如果暂停,显示"暂停中"if self.paused:time_text = MEDIUM_FONT.render(f"用时: {self.elapsed_time}秒 暂停中", True, BLACK)else:time_text = MEDIUM_FONT.render(f"用时: {self.elapsed_time}秒", True, BLACK)WINDOW.blit(time_text, (200, 20))# 绘制暂停/继续按钮pause_text = "继续" if self.paused else "暂停"pause_rect = pygame.Rect(300, 50, 80, 30)pygame.draw.rect(WINDOW, GRAY, pause_rect)pause_btn_text = SMALL_FONT.render(pause_text, True, BLACK)WINDOW.blit(pause_btn_text, (310, 55))# 绘制网格for x in range(GRID_WIDTH):for y in range(GRID_HEIGHT):self.grid[x][y].draw()# 绘制游戏结束信息if self.game_over:overlay = pygame.Surface((WINDOW_WIDTH, WINDOW_HEIGHT - 100))overlay.set_alpha(180)overlay.fill(WHITE)WINDOW.blit(overlay, (0, 100))if self.win:result_text = FONT.render("恭喜获胜!", True, GREEN)time_result = MEDIUM_FONT.render(f"用时: {self.elapsed_time}秒", True, BLACK)WINDOW.blit(result_text, (WINDOW_WIDTH // 2 - 60, WINDOW_HEIGHT // 2 - 30))WINDOW.blit(time_result, (WINDOW_WIDTH // 2 - 60, WINDOW_HEIGHT // 2 + 10))else:result_text = FONT.render("游戏结束!", True, RED)WINDOW.blit(result_text, (WINDOW_WIDTH // 2 - 60, WINDOW_HEIGHT // 2 - 20))# 重新开始按钮restart_rect = pygame.Rect(WINDOW_WIDTH // 2 - 80, WINDOW_HEIGHT // 2 + 50, 160, 40)pygame.draw.rect(WINDOW, GRAY, restart_rect)restart_text = MEDIUM_FONT.render("重新开始", True, BLACK)WINDOW.blit(restart_text, (WINDOW_WIDTH // 2 - 40, WINDOW_HEIGHT // 2 + 60))return restart_rect, Nonereturn None, pause_rectdef draw_menu():WINDOW.fill(LIGHT_BLUE)# 标题title_text = FONT.render("扫雷游戏", True, BLACK)WINDOW.blit(title_text, (WINDOW_WIDTH // 2 - 60, 50))# 难度选择subtitle_text = MEDIUM_FONT.render("选择难度:", True, BLACK)WINDOW.blit(subtitle_text, (WINDOW_WIDTH // 2 - 60, 120))# 难度按钮easy_rect = pygame.Rect(WINDOW_WIDTH // 2 - 100, 170, 200, 50)medium_rect = pygame.Rect(WINDOW_WIDTH // 2 - 100, 240, 200, 50)hard_rect = pygame.Rect(WINDOW_WIDTH // 2 - 100, 310, 200, 50)pygame.draw.rect(WINDOW, GREEN, easy_rect)pygame.draw.rect(WINDOW, (255, 255, 0), medium_rect)pygame.draw.rect(WINDOW, RED, hard_rect)easy_text = MEDIUM_FONT.render("简单 (10个雷)", True, BLACK)medium_text = MEDIUM_FONT.render("中等 (15个雷)", True, BLACK)hard_text = MEDIUM_FONT.render("困难 (20个雷)", True, BLACK)WINDOW.blit(easy_text, (WINDOW_WIDTH // 2 - 60, 185))WINDOW.blit(medium_text, (WINDOW_WIDTH // 2 - 60, 255))WINDOW.blit(hard_text, (WINDOW_WIDTH // 2 - 60, 325))# 操作说明instruction_text = SMALL_FONT.render("左键点击揭开格子, 右键点击标记地雷", True, BLACK)WINDOW.blit(instruction_text, (WINDOW_WIDTH // 2 - 180, 400))# 暂停说明pause_text = SMALL_FONT.render("游戏中按暂停按钮可暂停游戏", True, BLACK)WINDOW.blit(pause_text, (WINDOW_WIDTH // 2 - 150, 430))return easy_rect, medium_rect, hard_rectdef main():clock = pygame.time.Clock()game = Nonein_game = Falsewhile True:if in_game:WINDOW.fill(WHITE)restart_rect, pause_rect = game.draw_game()for event in pygame.event.get():if event.type == QUIT:pygame.quit()sys.exit()if event.type == MOUSEBUTTONDOWN:mouse_x, mouse_y = pygame.mouse.get_pos()if restart_rect and restart_rect.collidepoint(mouse_x, mouse_y):in_game = Falseelif pause_rect and pause_rect.collidepoint(mouse_x, mouse_y):game.toggle_pause()elif not game.game_over and mouse_y >= 100 and not game.paused:  # 确保点击在游戏区域且游戏未暂停grid_x, grid_y = mouse_x // GRID_SIZE, (mouse_y - 100) // GRID_SIZEif 0 <= grid_x < GRID_WIDTH and 0 <= grid_y < GRID_HEIGHT:if event.button == 1:  # 左键点击if game.first_click and game.grid[grid_x][grid_y].is_mine:# 如果第一次点击就是雷,重新生成游戏while game.grid[grid_x][grid_y].is_mine:game = Minesweeper(game.difficulty)game.reveal(grid_x, grid_y)elif event.button == 3:  # 右键点击game.toggle_flag(grid_x, grid_y)else:easy_rect, medium_rect, hard_rect = draw_menu()for event in pygame.event.get():if event.type == QUIT:pygame.quit()sys.exit()if event.type == MOUSEBUTTONDOWN and event.button == 1:mouse_x, mouse_y = pygame.mouse.get_pos()if easy_rect.collidepoint(mouse_x, mouse_y):game = Minesweeper(0)in_game = Trueelif medium_rect.collidepoint(mouse_x, mouse_y):game = Minesweeper(1)in_game = Trueelif hard_rect.collidepoint(mouse_x, mouse_y):game = Minesweeper(2)in_game = Truepygame.display.update()clock.tick(30)if __name__ == "__main__":main()

http://www.dtcms.com/a/569663.html

相关文章:

  • elasticsearch学习笔记-02
  • 构建一个自主深度思考的RAG管道以解决复杂查询--创建多阶段检索漏斗(5)
  • 网站开发方案 文档视频网站设计论文
  • 做钢材什么网站好个人装修设计软件
  • MFC - Picture Control 控件显示图片
  • 同一个网口有两个同名相机
  • mfc140.dll文件的丢失问题怎么处理?mfc140.dll文件的具体作用是什么
  • 第6章 支持向量机
  • 网站建设与管理大作业总结如何建设一个公众号电影网站
  • 网站模板去哪下载软件公司是干嘛的
  • rag:给大模型更精确的开端
  • Linux权限(5)
  • CVE-2025-4334 深度分析:WordPress wp-registration 插件权限提升漏洞
  • 【题解】洛谷 P3980 [NOI2008] 志愿者招募 [最大流最小费用]
  • Fastapi服务在高并发情况下大量超时问题排查
  • 分类与回归算法(二) - 线性回归
  • 中国建设银行官网站企业企业信息网查询
  • [创业之路-709]:管理与经营的异同
  • 网站的数据库在哪里专业上海网站建设
  • 使用IOT-Tree Server通过S7 Eth协议连接西门子PLC S7-1200
  • 59网一起做网站如何把字体安装在wordpress
  • PostgreSQL 之上的开源时序数据库 TimescaleDB 详解
  • wordpress网站投放广告网站后台管理图片
  • 查询域名网站软文写作是什么意思
  • TCN-Transformer-GRU时间卷积神经网络结合编码器组合门控循环单元多特征分类预测Matlab实现
  • 类和对象(中):深入理解 C++ 类与对象:6 个默认成员函数核心解析
  • 中山哪里有做微网站的中国经济网
  • win11蓝屏笑脸提示重启怎么回事 蓝屏重启解决方法
  • 佰力博检测与你探讨压电薄膜介电/阻抗-频谱的应用领域有哪些
  • 长沙教育类网站建设好兄弟资源网