扫雷(python)
本帖最后由 pyzyd 于 2025-5-31 11:58 编辑经典扫雷游戏{:10_257:}
鼠标点击即玩
import pygame
import random
import sys
import traceback
from tkinter import messagebox
import time
class SaoLei():
def __init__(self):
self.WIDTH = 10 # 宽
self.HEIGHT = 10 # 高
self.GRID_SIZE = 35 # 格子边长
self.NUM = 10 # 雷的个数
self.KEY_DATA = 20 # 加密层数
self.map = [] # 地图,初始化
self.is_easy = self.choose_difficulty()
self.start = 0
self.elapsed_time = 0
for i in range(self.HEIGHT):
self.map.append([])
for j in range(self.WIDTH):
self.map.append(0)
self.images = [] # 加载图像
for i in range(12):
image = pygame.image.load(f'images/{i}.jpg')
scaled_image = pygame.transform.scale(image, (self.GRID_SIZE, self.GRID_SIZE))
self.images.append(scaled_image)
self.is_over = False
pygame.init()
self.screen = pygame.display.set_mode((self.WIDTH * self.GRID_SIZE + 140, self.HEIGHT * self.GRID_SIZE))
pygame.display.set_caption('扫雷')
self.clock = pygame.time.Clock()
self.font = pygame.font.SysFont('Microsoft YaHei', 20)
self.init_map()
self.update_map()
def show_map(self):
for i in range(self.HEIGHT):
for j in range(self.WIDTH):
print(f'{self.map:4}', end='')
print()
def init_map(self):
count = 0
while count < self.NUM:
j = random.randrange(self.WIDTH)
i = random.randrange(self.HEIGHT)
if self.map == 0:
self.map = -1
count += 1
for i in range(self.HEIGHT):
for j in range(self.WIDTH):
if self.map == 0:
self.map += self.search_lei(i,j)
for i in range(self.HEIGHT):
for j in range(self.WIDTH):
self.map += self.KEY_DATA
def mask_num(self):
num = 0
for i in range(self.HEIGHT):
for j in range(self.WIDTH):
if self.map >= -1 + 2 * self.KEY_DATA:
num += 1
return num
def search_lei(self, x, y):
count = 0
for i in range(x-1, x+2):
for j in range(y-1, y+2):
if 0 <= i < self.HEIGHT and 0 <= j < self.WIDTH:
if self.map == -1:
count += 1
return count
def over(self):
for i in range(self.HEIGHT):
for j in range(self.WIDTH):
if self.map == -1 + self.KEY_DATA or self.map == -1 + 2 * self.KEY_DATA:
self.map = -1
def is_win(self):
count = 0
t_count = 0
r_count = 0
for i in range(self.HEIGHT):
for j in range(self.WIDTH):
if self.map >= -1 + 2 * self.KEY_DATA:
count += 1
if self.map == -1 + 2 * self.KEY_DATA:
t_count += 1
if self.map <= 8:
r_count += 1
if count == self.NUM and t_count == self.NUM and r_count == self.WIDTH * self.HEIGHT - self.NUM:
return True
def calc_time(self):
# 计算经过的时间
self.elapsed_time = time.time() - self.start
minutes = int(self.elapsed_time // 60)
seconds = int(self.elapsed_time % 60)
text1 = "所用时间:"
time_text = f"{minutes:02d}:{seconds:02d}"# 格式化为 "分:秒" 格式
# 渲染文本
text1_surface = self.font.render(text1, True, (0, 0, 0))
text_surface = self.font.render(time_text, True, (0, 0, 0))
best_time = 0
file = ''
if self.is_easy:
file = r'record_easy.txt'
else:
file = r'record_difficult.txt'
try:
with open(file, 'r') as f:
best_time = float(f.read())
except FileNotFoundError:
pass
text2 = "最佳时间:"
minutes = int(best_time // 60)
seconds = int(best_time % 60)
best_time_text = f"{minutes:02d}:{seconds:02d}"
if best_time == 0:
best_time_text = "暂无"
text2_surface = self.font.render(text2, True, (235, 100, 0))
best_time_surface = self.font.render(best_time_text, True, (0, 0, 0))
num = self.mask_num()
text3 = f"标记个数:{num}"
text3_surface = self.font.render(text3, True, (0, 0, 0))
# 绘制
self.screen.fill((230, 235, 235))
self.screen.blit(self.font.render(f"雷的个数:{self.NUM}", True, (255, 0, 0)),
(self.WIDTH * self.GRID_SIZE + 10, 10))
self.screen.blit(text1_surface, (self.WIDTH * self.GRID_SIZE + 10, 50))
self.screen.blit(text_surface, (self.WIDTH * self.GRID_SIZE + 10, 90))
self.screen.blit(text2_surface, (self.WIDTH * self.GRID_SIZE + 10, 130))
self.screen.blit(best_time_surface, (self.WIDTH * self.GRID_SIZE + 10, 170))
self.screen.blit(text3_surface, (self.WIDTH * self.GRID_SIZE + 10, 210))
def game_over(self):
title = 'Game Over'
msg = ''
if self.is_over == True:
self.over()
msg = '你踩到雷了,你输了,Fail T^T'
elif self.is_win():
msg = '你排掉了所有的雷,恭喜你,你赢了,Win!'
best_time = 0
file = ''
if self.is_easy:
file = r'record_easy.txt'
else:
file = r'record_difficult.txt'
try:
with open(file, 'r') as f:
best_time = float(f.read())
except FileNotFoundError:
pass
if best_time == 0 or best_time > self.elapsed_time:
with open(file, 'w') as f:
f.write(str(self.elapsed_time))
if msg:
self.over()
res = messagebox.askretrycancel(title, msg, icon='question')
if res == True:
self.__init__()
self.run()
else:
pygame.quit()
sys.exit()
def draw_map(self):
for i in range(self.HEIGHT):
for j in range(self.WIDTH):
x = j * self.GRID_SIZE
y = i * self.GRID_SIZE
if self.map == -1:
self.screen.blit(self.images, (x, y))
elif 0 <= self.map <= 8:
self.screen.blit(self.images], (x, y))
elif -1 + self.KEY_DATA <= self.map <= 8 + self.KEY_DATA:
self.screen.blit(self.images, (x, y))
elif -1 + 2 * self.KEY_DATA <= self.map <= 8 + 2 * self.KEY_DATA:
self.screen.blit(self.images, (x, y))
def open_null(self, x, y):
for i in range(x-1, x+2):
for j in range(y-1, y+2):
if 0 <= i < self.HEIGHT and 0 <= j < self.WIDTH:
if -1 + self.KEY_DATA < self.map <= 8 + self.KEY_DATA:
self.map -= self.KEY_DATA
if self.map == 0:
self.open_null(i, j)
def run(self):
self.start = time.time()
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
elif event.type == pygame.MOUSEBUTTONDOWN:
pos = pygame.mouse.get_pos()
i = int(pos / self.GRID_SIZE)
j = int(pos / self.GRID_SIZE)
if 0 <= i < self.HEIGHT and 0 <= j < self.WIDTH:
if pygame.mouse.get_pressed() == 1:
# 左键按下
if -1 + self.KEY_DATA <= self.map <= 8 + self.KEY_DATA:
self.map -= self.KEY_DATA
if self.map == -1:
self.is_over = True
elif self.map == 0:
self.open_null(i, j)
elif pygame.mouse.get_pressed() == 1:
# 右键按下
if -1 + self.KEY_DATA <= self.map <= 8 + self.KEY_DATA:
self.map += self.KEY_DATA
elif -1 + 2 * self.KEY_DATA <= self.map <= 8 + 2 * self.KEY_DATA:
self.map -= self.KEY_DATA
self.update_map()
self.clock.tick(60)
self.game_over()
def update_map(self):
self.calc_time()
self.draw_map()
pygame.display.update()
def choose_difficulty(self):
choice = ''
choice = messagebox.askquestion("选择模式", "简单请选‘是’,困难请选‘否’", icon='question')
if choice == 'yes':
self.NUM = 10
return True
elif choice == 'no':
self.NUM = 30
self.WIDTH = 20
return False
else:
sys.exit()
if __name__ == '__main__':
sl = SaoLei()
try:
sl.run()
except SystemExit:
pass
except:
traceback.print_exc()
pygame.quit()
{:10_256:} {:10_254:} 加个程序截图就更好啦~ 口含明珠,进退自如 好! 6 优质贴值得有 C 币 感谢 {:9_232:} {:10_256:}
好!{:5_109:} 好好学习 天天向上 牛哇牛哇
页:
[1]