• C++
  • pygame十二课--主题:扫雷2

  • @ 2024-6-8 19:23:06

image image image image image

1 条评论

  • @ 2024-6-8 20:32:34
    import sys
    import time,random
    import pygame
    from pygame.locals import *
    from enum import Enum
    
    '''
    增加点击事件的右键事件
    增加方块状态
    右键标记几种状态
    增加BlockMine.getmine()方法
    给不同方块状态画不同的样子
    
    '''
    
    BLOCK_WIDTH = 20   # 棋盘的宽度方块个数
    BLOCK_HEIGHT = 10  # 棋盘的高度方块个数
    SIZE = 30    # 方块的长宽
    MINE_COUNT = 40   # 雷的数量
    
    # 游戏屏幕的宽
    SCREEN_WIDTH = BLOCK_WIDTH * SIZE
    # 游戏屏幕的高
    SCREEN_HEIGHT = (BLOCK_HEIGHT + 2) * SIZE
    
    def load_img(file,size):
        img = pygame.image.load(file).convert()
        return pygame.transform.smoothscale(img,(size,size))
    
    # 定义方块类
    class Mine:
        def __init__(self, row, column, value=0):
            self.row = row
            self.column = column
            self.pos = (self.column * SIZE, (self.row + 2) * SIZE)
            self.value = value   # 1:雷 0:安全
            self.status = BlockStatus.normal
            self.around_mine_count = -1  # 周围雷的数量
            self.image = load_img('resources/normal.jpg',SIZE)
    
        def __repr__(self):
            return str(self.value)
            # return f"({self.x},{self.y})"
    
    # 定义雷区
    class MineBlock:
        def __init__(self):
            # 生成方块棋盘组成列表,无地雷,每个方块是一个Mine实例()
            # 在 ipython 等终端中展示一下结果,有一个直观印象。
            # 列表推导式的用法
            self.blocks = [Mine(i, j) for i in range(BLOCK_HEIGHT) for j in range(BLOCK_WIDTH)]
    
            # 埋雷
            # 在总方块里随机选MINE_COUNT个数,做雷。
            mines = random.sample(range(BLOCK_WIDTH * BLOCK_HEIGHT), MINE_COUNT)
            for i in mines:
                self.blocks[i].value = 1
    
        # 返回指定行列的 mine 对象
        def getmine(self, row, column):
            return self.blocks[row * BLOCK_WIDTH + column]
    
        def open_mine(self):
            pass
    
    def print_text(screen, font, x, y, text, fcolor=(255, 255, 255)):
        imgText = font.render(text, True, fcolor)
        screen.blit(imgText, (x, y))
    
    class BlockStatus(Enum):
        normal = 1  # 未点击
        opened = 2  # 已点击
        mine = 3    # 地雷
        flag = 4    # 标记为地雷
        ask = 5   # 标记为问号
        bomb = 6    # 踩中地雷
    
    def main():
        pygame.init()
        screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
        pygame.display.set_caption('扫雷')
        bgcolor = (225, 225, 225)   # 背景色
    
        font1 = pygame.font.Font('resources/msyh.ttf', SIZE * 2)  # 得分的字体
        fwidth, fheight = font1.size('999')    # 具体的文本 999 的宽和高
        red = (200, 40, 40)
    
        block = MineBlock()
    
        while True:
            # 填充背景色
            screen.fill(bgcolor)
    
            for mine in block.blocks:
                screen.blit(mine.image,mine.pos)
            # 导入图片
            face_size = int(SIZE * 1.25)
            img_face_normal = load_img("resources/face_normal.bmp",face_size)
            img_face_fail = load_img("resources/face_fail.bmp",face_size)
            img_face_win = load_img("resources/face_win.bmp",face_size)
            face_pos_x = (SCREEN_WIDTH - face_size) // 2
            face_pos_y = (SIZE * 2 - face_size) // 2
    
            screen.blit(img_face_normal,(face_pos_x,face_pos_y))
    
            # 显示剩余雷和所用时间
            print_text(screen,font1,30,(SIZE * 2 - fheight)//2,"000",red)      # 用时
            print_text(screen,font1,SCREEN_WIDTH-fwidth,(SIZE * 2 - fheight)//2,"40",red)   # 剩余雷
    
            for event in pygame.event.get():
                if event.type == QUIT:
                    pygame.quit()
                    sys.exit()
                elif event.type == MOUSEBUTTONDOWN:
                    mouse_x, mouse_y = event.pos
                    column = mouse_x // SIZE
                    row = mouse_y // SIZE - 2    # 有上面的非雷区
                    b1, b2, b3 = pygame.mouse.get_pressed()
                elif event.type == MOUSEBUTTONUP:
                    mine = block.getmine(row, column)
    
                    # 点击左键
                    if b1 and not b3:
                        pass
                    # 点击右键
                    elif not b1 and b3:
                        if mine.status == BlockStatus.normal:
                            mine.status = BlockStatus.flag
                            mine.image = load_img("resources/flag.bmp", SIZE)
                        elif mine.status == BlockStatus.flag:
                            mine.status = BlockStatus.ask
                            mine.image = load_img("resources/ask.bmp", SIZE)
                        elif mine.status == BlockStatus.ask:
                            mine.status = BlockStatus.normal
                            mine.image = load_img("resources/normal.jpg", SIZE)
    
            pygame.display.update()
    
    if __name__ == '__main__':
        main()
    
    
    
    • 1