扫雷
import pygame
import sys
import random
初始化pygame
pygame.init()
游戏常量
CELL_SIZE = 30
MARGIN = 10
中等难度设置(可调整)
GRID_WIDTH = 16
GRID_HEIGHT = 16
MINE_COUNT = 40
确保窗口尺寸合适
WINDOW_WIDTH = MARGIN * 2 + CELL_SIZE * GRID_WIDTH
WINDOW_HEIGHT = MARGIN * 2 + CELL_SIZE * GRID_HEIGHT + 50 # 额外空间用于显示信息
颜色定义
BG_COLOR = (200, 200, 200)
CELL_COLOR = (180, 180, 180)
COVERED_COLOR = (120, 120, 120)
HIGHLIGHT_COLOR = (150, 150, 150)
BORDER_COLOR = (100, 100, 100)
TEXT_COLORS = {
1: (0, 0, 255), # 蓝色
2: (0, 128, 0), # 绿色
3: (255, 0, 0), # 红色
4: (0, 0, 128), # 深蓝色
5: (128, 0, 0), # 暗红色
6: (0, 128, 128), # 青绿色
7: (0, 0, 0), # 黑色
8: (128, 128, 128)# 灰色
}
MINE_COLOR = (0, 0, 0)
MINE_BG_COLOR = (255, 0, 0)
FLAG_COLOR = (255, 255, 0)
创建游戏窗口
screen = pygame.display.set_mode((WINDOW_WIDTH, WINDOW_HEIGHT))
pygame.display.set_caption("扫雷游戏")
font = pygame.font.SysFont("Arial", 24)
class MineSweeper:
def init(self):
self.reset_game()
def reset_game(self):
"""重置游戏状态"""
# 初始化网格
self.grid = [[0 for _ in range(GRID_WIDTH)] for _ in range(GRID_HEIGHT)]
self.covered = [[True for _ in range(GRID_WIDTH)] for _ in range(GRID_HEIGHT)]
self.flagged = [[False for _ in range(GRID_WIDTH)] for _ in range(GRID_HEIGHT)]
self.game_over = False
self.game_won = False
self.first_click = True
# 随机放置地雷
mines_placed = 0
while mines_placed < MINE_COUNT:
row = random.randint(0, GRID_HEIGHT - 1)
col = random.randint(0, GRID_WIDTH - 1)
if self.grid[row][col] != -1:
self.grid[row][col] = -1 # -1表示地雷
mines_placed += 1
# 计算每个非地雷格子周围的地雷数
for row in range(GRID_HEIGHT):
for col in range(GRID_WIDTH):
if self.grid[row][col] != -1:
self.grid[row][col] = self.count_neighbor_mines(row, col)
def count_neighbor_mines(self, row, col):
"""计算指定格子周围的地雷数量"""
count = 0
for r in range(max(0, row - 1), min(GRID_HEIGHT, row + 2)):
for c in range(max(0, col - 1), min(GRID_WIDTH, col + 2)):
if self.grid[r][c] == -1:
count += 1
return count
def uncover_cell(self, row, col):
"""揭开格子,如果是空白格则递归揭开周围格子"""
if (row < 0 or row >= GRID_HEIGHT or col < 0 or col >= GRID_WIDTH or
not self.covered[row][col] or self.flagged[row][col]):
return
self.covered[row][col] = False
if self.grid[row][col] == -1:
# 挖到地雷,游戏结束
self.game_over = True
return
if self.grid[row][col] == 0:
# 空白格,递归揭开周围格子
for r in range(max(0, row - 1), min(GRID_HEIGHT, row + 2)):
for c in range(max(0, col - 1), min(GRID_WIDTH, col + 2)):
self.uncover_cell(r, c)
# 检查是否获胜
self.check_win()
def toggle_flag(self, row, col):
"""切换格子的标记状态"""
if (row < 0 or row >= GRID_HEIGHT or col < 0 or col >= GRID_WIDTH or
not self.covered[row][col] or self.game_over):
return
self.flagged[row][col] = not self.flagged[row][col]
def check_win(self):
"""检查是否获胜"""
for row in range(GRID_HEIGHT):
for col in range(GRID_WIDTH):
if self.grid[row][col] != -1 and self.covered[row][col]:
return
self.game_won = True
def draw(self):
"""绘制游戏界面"""
# 绘制背景
screen.fill(BG_COLOR)
# 绘制剩余地雷数
mines_left = MINE_COUNT - sum(row.count(True) for row in self.flagged)
mines_text = font.render(f"剩余地雷: {mines_left}", True, (0, 0, 0))
screen.blit(mines_text, (MARGIN, WINDOW_HEIGHT - 40))
# 绘制游戏状态
if self.game_over:
status_text = font.render("游戏结束!", True, (255, 0, 0))
elif self.game_won:
status_text = font.render("恭喜获胜!", True, (0, 255, 0))
else:
status_text = font.render("游戏进行中...", True, (0, 0, 0))
screen.blit(status_text, (WINDOW_WIDTH // 2 - 100, WINDOW_HEIGHT - 40))
# 绘制网格
for row in range(GRID_HEIGHT):
for col in range(GRID_WIDTH):
x = MARGIN + col * CELL_SIZE
y = MARGIN + row * CELL_SIZE
# 绘制格子边框
pygame.draw.rect(screen, BORDER_COLOR, (x, y, CELL_SIZE, CELL_SIZE), 1)
if self.covered[row][col]:
# 未揭开的格子
pygame.draw.rect(screen, COVERED_COLOR, (x + 1, y + 1, CELL_SIZE - 2, CELL_SIZE - 2))
if self.flagged[row][col]:
# 标记的格子
pygame.draw.rect(screen, FLAG_COLOR, (x + 5, y + 5, CELL_SIZE - 10, CELL_SIZE - 10))
else:
# 已揭开的格子
pygame.draw.rect(screen, CELL_COLOR, (x + 1, y + 1, CELL_SIZE - 2, CELL_SIZE - 2))
if self.grid[row][col] == -1:
# 地雷格子
pygame.draw.circle(screen, MINE_BG_COLOR, (x + CELL_SIZE // 2, y + CELL_SIZE // 2), CELL_SIZE // 3)
pygame.draw.circle(screen, MINE_COLOR, (x + CELL_SIZE // 2, y + CELL_SIZE // 2), CELL_SIZE // 6)
elif self.grid[row][col] > 0:
# 显示周围地雷数
num_text = font.render(str(self.grid[row][col]), True, TEXT_COLORS[self.grid[row][col]])
text_rect = num_text.get_rect(center=(x + CELL_SIZE // 2, y + CELL_SIZE // 2))
screen.blit(num_text, text_rect)
pygame.display.flip()
def main():
game = MineSweeper()
clock = pygame.time.Clock()
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
elif event.type == pygame.MOUSEBUTTONDOWN:
if game.game_over or game.game_won:
continue
x, y = event.pos
# 忽略状态显示区域
if y >= WINDOW_HEIGHT - 50:
continue
col = (x - MARGIN) // CELL_SIZE
row = (y - MARGIN) // CELL_SIZE
if 0 <= row < GRID_HEIGHT and 0 <= col < GRID_WIDTH:
if event.button == 1: # 左键点击
if game.first_click:
# 确保第一次点击不会挖到地雷
if game.grid[row][col] == -1:
# 重新生成地雷
game.reset_game()
# 再次点击当前位置
game.uncover_cell(row, col)
game.first_click = False
else:
game.uncover_cell(row, col)
elif event.button == 3: # 右键点击
game.toggle_flag(row, col)
game.draw()
clock.tick(60)
if name == "main":
main()

浙公网安备 33010602011771号