pyzyd 发表于 3 天前

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

某一个“天” 发表于 3 天前

{:10_256:}

小甲鱼 发表于 3 天前

{:10_254:} 加个程序截图就更好啦~

ydwb 发表于 3 天前

口含明珠,进退自如

player-none 发表于 3 天前

好!

星陨落石 发表于 3 天前

6

sfqxx 发表于 前天 08:13

优质贴值得有 C 币

sfqxx_小 发表于 前天 08:13

感谢

Tyroe 发表于 前天 09:49

{:9_232:}

一定能行 发表于 前天 15:25

{:10_256:}

销声匿迹 发表于 前天 23:11


好!{:5_109:}

liduv5 发表于 昨天 10:51

好好学习 天天向上

Mr.江南 发表于 昨天 19:57

牛哇牛哇
页: [1]
查看完整版本: 扫雷(python)