Python 开心消消乐

慈云数据 2024-05-28 技术支持 28 0

在这里插入图片描述

💝💝💝欢迎莅临我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。

在这里插入图片描述

  • 推荐:「stormsha的主页」👈,持续学习,不断总结,共同进步,为了踏实,做好当下事儿~

  • 专栏导航

    • Python系列: Python面试题合集,剑指大厂
    • Git系列: Git操作技巧
    • GO系列: 记录博主学习GO语言的笔记,该笔记专栏尽量写的试用所有入门GO语言的初学者
    • 数据库系列: 详细总结了常用数据库 mysql 技术点,以及工作中遇到的 mysql 问题等
    • 运维系列: 总结好用的命令高效开发
    • 算法与数据结构系列: 总结数据结构和算法,不同类型针对性训练,提升编程思维

      非常期待和您一起在这个小小的网络世界里共同探索、学习和成长。💝💝💝 ✨✨ 欢迎订阅本专栏 ✨✨

      💖The Start💖点点关注,收藏不迷路💖

      📒文章目录

      • 效果图
      • 项目结构
      • 程序代码

        完整代码:https://gitcode.com/stormsha1/games/overview

        效果图

        消消乐

        项目结构

        在这里插入图片描述

        程序代码

        run.py

        import sys  
        import pygame  
        from pygame.locals import KEYDOWN, QUIT, K_q, K_ESCAPE, MOUSEBUTTONDOWN  
        from dissipate.level import Manager  
        from dissipate.level_tree import LevelTreeManager  
        from dissipate.sounds import Sounds  
          
          
        class Game:  
            """  
            游戏主类,负责初始化和主循环  
            """  
            def __init__(self):  
                """  
                初始化游戏  
                """        pygame.init()  
                pygame.mixer.init()  
                pygame.display.set_caption('开心消消乐')  # 设置游戏窗口标题  
                pygame.mouse.set_visible(False)  # 隐藏鼠标指针  
          
                # 初始化游戏管理器和声音  
                self.tree = LevelTreeManager()  # 树管理器,用于主菜单  
                self.manager = Manager(0, 0)  # 游戏管理器,用于处理游戏逻辑  
                self.world_bgm = pygame.mixer.Sound(Sounds.WORLD_BGM.value)  # 世界背景音乐  
                self.game_bgm = pygame.mixer.Sound(Sounds.GAME_BGM.value)  # 游戏背景音乐  
          
                # 提高游戏性能的优化  
                self.get_events = pygame.event.get  # 获取事件的方法  
                self.update_window = pygame.display.flip  # 刷新窗口的方法  
          
                self.sound_sign = 0  # 用于控制背景音乐切换的标志  
          
            def run(self):  
                """主游戏循环"""  
                while True:  
                    self.handle_music()  # 处理背景音乐  
                    self.draw()  # 绘制游戏界面  
                    self.handle_events()  # 处理用户输入事件  
                    self.update()  # 更新显示  
          
            def handle_music(self):  
                """根据游戏级别管理背景音乐"""  
                if self.manager.level == 0:  
                    if self.sound_sign == 0:  
                        self.game_bgm.stop()  # 停止游戏背景音乐  
                        self.world_bgm.play(-1)  # 循环播放世界背景音乐  
                        self.sound_sign = 1  
                else:  
                    if self.sound_sign == 1:  
                        self.world_bgm.stop()  # 停止世界背景音乐  
                        self.game_bgm.play(-1)  # 循环播放游戏背景音乐  
                        self.sound_sign = 0  
          
            def draw(self):  
                """根据级别绘制相应的游戏界面"""  
                if self.manager.level == 0:  
                    self.tree.draw_tree(self.manager.energy_num, self.manager.money)  # 绘制主菜单界面  
                else:  
                    self.manager.set_level_mode(self.manager.level)  # 设置当前关卡模式  
                    sprite_group = self.manager.draw()  # 绘制游戏关卡界面  
                    if self.manager.type == 0:  
                        self.manager.eliminate_animals()  # 消除动物  
                        self.manager.death_map()  # 更新死亡地图  
                        self.manager.swap(sprite_group)  # 处理交换逻辑  
                    self.manager.judge_level()  # 判断关卡状态  
          
            def handle_events(self):  
                """处理用户输入事件"""  
                for event in self.get_events():  
                    if event.type == KEYDOWN:  
                        if event.key in (K_q, K_ESCAPE):  
                            sys.exit()  # 按下 Q 或 ESC 键退出游戏  
                    elif event.type == QUIT:  
                        sys.exit()  # 点击关闭按钮退出游戏  
                    elif event.type == MOUSEBUTTONDOWN:  
                        mouse_x, mouse_y = event.pos  # 获取鼠标点击位置  
                        if self.manager.level == 0:  
                            self.tree.mouse_select(  
                                self.manager, mouse_x,  
                                mouse_y,  
                                self.manager.level,  
                                self.manager.energy_num,  
                                self.manager.money  
                            )  # 处理主菜单鼠标选择  
                        self.manager.mouse_select(mouse_x, mouse_y)  # 处理游戏内鼠标选择  
          
            def update(self):  
                """  
                更新鼠标图像并刷新显示  
                :return:  
                """        self.manager.mouse_image()  # 更新鼠标图像  
                self.update_window()  # 刷新显示  
          
          
        if __name__ == '__main__':  
            game = Game()  # 创建游戏实例  
            game.run()  # 启动游戏
        

        level.py

        import os  
        from random import randint  
        import pygame  
        from pygame.locals import *  
        from pygame.time import delay  
        from dissipate.img import img_basic  
        from dissipate.sounds import Sounds, play_sound  
        from dissipate.sprites import Board, Element  
          
          
        class Manager:  
            """Game manager."""  
            # 游戏屏幕的大小设置为900x600像素  
            __screen_size = (900, 600)  
            # 使用pygame库设置屏幕模式,DOUBLEBUF是双缓冲,32是位深度  
            screen = pygame.display.set_mode(__screen_size, DOUBLEBUF, 32)  
            # 砖块的大小设置为50x50像素  
            __brick_size = 50  
            # 加载背景图片并转换为优化格式  
            __bg = pygame.image.load(os.path.join(img_basic, 'bg.png')).convert()  
            # 停止宽度,可能用于游戏结束或暂停的界面  
            stop_width = 63  
            # 当前选中的砖块位置,格式为[row, col]  
            selected = [-1, -1]  
            # 交换标志,可能用于交换砖块或游戏逻辑  
            swap_sign = -1  
            # 上一次选中的砖块位置,格式为[row, col]  
            last_sel = [-1, -1]  
            # 是否交换的标志,用于判断是否发生了交换  
            value_swapped = False  
            # 死亡地图的标志,可能用于显示或隐藏死亡相关的游戏元素  
            death_sign = True  
            # 消除4个砖块时选中的位置,格式为[row, col]  
            boom_sel = [-1, -1]  
            # 当前关卡,0表示树(可能是特殊关卡或菜单)  
            level = 0  
            # 玩家的金钱数量  
            money = 100  
            # 能量点数  
            energy_num = 30  
            # 数字标志,可能用于显示或隐藏数字相关的游戏元素  
            num_sign = True  
            # 游戏类型,0为进行中,1为通过,-1为失败,2为树  
            type = 2  
            # 是否重置布局的标志  
            reset_mode = True  
            # 每个关卡的初始步数  
            init_step = 15  
            # 当前游戏剩余的步数  
            step = init_step  
            # 玩家的得分  
            score = 0  
            # 中等得分的两个阈值  
            min = 20  
            max = 50  
            # 已消除动物的数量列表,长度为6,可能代表6种不同的动物  
            animal_num = [0, 0, 0, 0, 0, 0]  
            # 剩余需要消除的冰块数量  
            ice_num = 0  
            # 成功板,继承自Board类,位置在[200, 0]  
            success_board = Board(Board.success, [200, 0])  
            # 失败板,继承自Board类,位置在[200, 0]  
            fail_board = Board(Board.fail, [200, 0])  
            # 游戏网格的高度和宽度,都是9  
            height, width = 9, 9  
            # 选中的行和列,初始值为5  
            row, col = 5, 5  
            # 冰块列表,21x21的二维列表,-1表示无冰块,1表示有冰块  
            ice_list = [[-1 for _ in range(21)] for _ in range(21)]  
            # 动物列表,21x21的二维列表,-2表示已消除,-1表示无动物,0-4表示不同的动物  
            animal = [[-1 for _ in range(21)] for _ in range(21)]  
            # 砖块的x和y位置列表,用于确定砖块在屏幕上的位置  
            list_x, list_y = (__screen_size[0] - 11 * __brick_size) / 2, (__screen_size[1] - 11 * __brick_size) / 2  
          
            def __init__(self, width, height):  
                self.height = height  
                self.width = width  
                self.list_x = (Manager.__screen_size[0] - self.width * Manager.__brick_size) / 2  
                self.list_y = (Manager.__screen_size[1] - self.height * Manager.__brick_size) / 2  
                self.row, self.col = Manager.xy_rc(self.list_x, self.list_y)  
                self.list_x, self.list_y = Manager.rc_xy(self.row, self.col)  
                self.ice_list = [[-1 for _ in range(21)] for _ in range(21)]  
                self.animal = [[-1 for _ in range(21)] for _ in range(21)]  
                self.reset_animals()  
          
            def reset_animals(self):  
                """  
                用于将游戏板上的动物随机重置为0到5之间的数字,  
                其中0可能表示没有动物,1到5表示不同类型的动物。  
                """        # 遍历由self.row和self.col确定的起始行和列,直到高度和宽度决定的结束行和列  
                for row in range(self.row, self.row + self.height):  
                    # 对于每一行row,遍历由self.col和self.col + self.width确定的起始列和结束列  
                    for col in range(self.col, self.col + self.width):  
                        # 为当前位置(row, col)随机分配一个动物编号,编号范围从0到5  
                        # randint是random模块中的一个函数,用于生成一个指定范围内的随机整数  
                        self.animal[row][col] = randint(0, 5)  
          
            @staticmethod  
            def rc_xy(row, col):  
                """(row, col) -> (x, y)"""  
                return int(Manager.list_x + (col - Manager.col) * Manager.__brick_size), int \  
                    (Manager.list_y + (row - Manager.row) * Manager.__brick_size)  
          
            @staticmethod  
            def xy_rc(x, y):  
                """(x, y) -> (row, col)"""  
                return int((y - Manager.list_y) / Manager.__brick_size + Manager.row), int \  
                    ((x - Manager.list_x) / Manager.__brick_size + Manager.col)  
          
            @staticmethod  
            def draw_brick(x, y):  
                """Draw a brick at (x, y)."""  
                brick = Element(Element.brick, (x, y))  
                Manager.screen.blit(brick.image, brick.rect)  
          
            def draw_task(self, task_animal_num, which_animal, board_position=(400, 90), animal_position=(430, 35),  
                          txt_position=(455, 60)):  
                """  
                绘制任务板  
                """        txt_size = 24  
                txt_color = (0, 0, 0)  
                Board(Board.task_board, board_position).draw(self.screen)  
                if which_animal == 6:  
                    task_animal = Element(Element.ice, animal_position)  
                else:  
                    task_animal = Element(Element.animals[which_animal], animal_position)  
                task_animal.image = pygame.transform.smoothscale(task_animal.image, (40, 40))  
                task_animal.draw(self.screen)  
                if which_animal == 6:  
                    if task_animal_num - self.ice_num = 16:  # L3: 16 只青蛙和 16 头牛  
                        self.type = 1  # 通过第三关  
                        self.num_add()  
                elif self.level == 4:  
                    if self.animal_num[5] >= 18 and self.animal_num[2] >= 18:  # L4: 18 头牛和 18 只小鸡  
                        self.type = 1  # 通过第四关  
                        self.num_add()  
                elif self.level == 5:  
                    if self.animal_num[2] >= 28 and self.animal_num[0] >= 28:  # L5: 28 只小鸡和 28 只狐狸  
                        self.type = 1  # 通过第五关  
                        self.num_add()  
                elif self.level == 6:  
                    if self.animal_num[4] >= 70:  # L6: 70 只青蛙  
                        self.type = 1  # 通过第六关  
                        self.num_add()  
                elif self.level == 7:  
                    if self.animal_num[2] >= 36 and self.animal_num[1] >= 36 \  
                            and self.animal_num[0] >= 36:  # L7: 36 只小鸡、36 只熊和 36 只狐狸  
                        self.type = 1  # 通过第七关  
                        self.num_add()  
                elif self.level == 8:  
                    if self.ice_num >= 15:  # L8: 15 冰块  
                        self.type = 1  # 通过第八关  
                        self.num_add()  
                elif self.level == 9:  
                    if self.ice_num >= 49:  # L9: 49 冰块  
                        self.type = 1  # 通过第九关  
                        self.num_add()  
                else:  
                    if self.ice_num >= 39:  # L10: 39 冰块  
                        self.type = 1  # 通过第十关  
                        self.num_add()  
          
                self.judge_next(self.type, self.score)
        

        level_tree.py

        import pygame  
        from pygame import DOUBLEBUF  
        from pygame.time import delay  
          
        from dissipate.sounds import play_sound, Sounds  # 导入声音播放功能和声音资源  
        from dissipate.sprites import Tree  # 导入关卡树的类  
          
          
        class LevelTreeManager:  
            """  
            关卡树管理器类,用于管理关卡树及其相关功能。  
            """    __screen_size = (900, 600)  # 屏幕尺寸  
            screen = pygame.display.set_mode(__screen_size, DOUBLEBUF, 32)  # 设置屏幕显示模式  
            fruit_list = []  # 用于存储水果对象的列表  
            fruit_image = pygame.image.load(Tree.fruit).convert_alpha()  # 加载水果图片  
            fruit_width = fruit_image.get_width()  # 获取水果图片宽度  
            fruit_height = fruit_image.get_height()  # 获取水果图片高度  
            type = 0  # 场景类型,0 表示关卡树场景,1 表示能量场景  
            energy_full = False  # 能量已满标志  
            money_empty = False  # 金钱不足标志  
          
            def display_text(self, text, position, txt_size=25, txt_color=(255, 255, 255)):  
                """  
                显示指定的文本内容。  
                参数:  
                text: 要显示的文本  
                position: 文本位置  
                txt_size: 文本大小  
                txt_color: 文本颜色  
                """        my_font = pygame.font.SysFont(None, txt_size)  # 创建字体对象  
                text_screen = my_font.render(text, True, txt_color)  # 渲染文本  
                self.screen.blit(text_screen, position)  # 在屏幕上绘制文本  
          
            def draw_tree(self, energy_num, money_num):  
                """  
                绘制游戏中的关卡树和相关资源。  
                参数:  
                energy_num: 当前能量值  
                money_num: 当前金钱数量  
                """        Tree(Tree.tree, (0, 600)).draw(self.screen)  # 绘制关卡树  
                Tree(Tree.energy_num, Tree.energy_num_position).draw(self.screen)  # 绘制能量数  
                if energy_num > 30:  
                    self.display_text(str(30) + '/30', (22, 55), 21)  # 显示最大能量值  
                else:  
                    self.display_text(str(energy_num) + '/30', (22, 55), 21)  # 显示当前能量值  
                Tree(Tree.money, (15, 135)).draw(self.screen)  # 绘制金钱  
                self.display_text(str(money_num), (32, 124), 21)  # 显示当前金钱数量  
                for i in range(0, 10):  # 绘制水果  
                    Tree(Tree.fruit, Tree.position[i]).draw(self.screen)  
                    self.display_text(str(i + 1), (Tree.position[i][0] + 15, Tree.position[i][1] - 47))  
                if self.type == 1:  
                    Tree(Tree.energy_buy, Tree.energy_buy_position).draw(self.screen)  # 绘制购买能量按钮  
                    if self.energy_full:  
                        self.display_text('energy is full!', (430, 310), 30, (255, 0, 0))  # 显示能量已满提示  
                        pygame.display.flip()  # 更新屏幕显示  
                        delay(500)  # 延迟500毫秒  
                        self.energy_full = False  # 重置能量已满标志  
                    if self.money_empty:  
                        self.display_text('money is not enough!', (410, 310), 30, (255, 0, 0))  # 显示金钱不足提示  
                        pygame.display.flip()  # 更新屏幕显示  
                        delay(500)  # 延迟500毫秒  
                        self.money_empty = False  # 重置金钱不足标志  
          
            def mouse_select(self, mgr, mouse_x, mouse_y, level, energy_num, money_num):  
                """  
                处理鼠标事件。  
                参数:  
                mgr: 管理器对象  
                mouse_x: 鼠标x坐标  
                mouse_y: 鼠标y坐标  
                level: 当前等级  
                energy_num: 当前能量值  
                money_num: 当前金钱数量  
                """        if self.type == 0:  # 关卡树场景  
                    for i in range(0, 10):  
                        if Tree.position[i][0] = 50:  
                            energy_num += 5  # 增加能量  
                            money_num -= 50  # 减少金钱  
                    elif 619  
        

        sprites.py

        import os  
        from pygame.sprite import Sprite  
        from pygame.image import load  
          
        from dissipate.img import img_basic, img_energy, img_board, img_text, img_level, img_button, img_animal, img_ice, \  
            img_boom  
          
          
        # 基类,GameSprite类定义了所有游戏精灵的基类,包括加载图像、设置位置和绘制方法。  
        class GameSprite(Sprite):  
            def __init__(self, icon, position):  
                # 初始化GameSprite类,继承自pygame的Sprite类。  
                super().__init__()  
                # 加载图像并转换为具有透明通道的格式。  
                self.image = load(icon).convert_alpha()  
                # 获取图像的矩形区域。  
                self.rect = self.image.get_rect()  
                # 设置精灵的位置。  
                self.rect.topleft = position  
                self.rect.bottomleft = position  
          
            def draw(self, screen):  
                # 将精灵绘制到屏幕上。  
                screen.blit(self.image, self.rect)  
          
          
        class Tree(GameSprite):  
            """  
            关卡树类,显示关卡树和相关资源。  
            """    # 树、果实、能量数字、金钱和购买能量按钮的图像路径。  
            tree = os.path.join(img_basic, 'tree.png')  
            fruit = os.path.join(img_basic, 'fruit.png')  
            energy_num = os.path.join(img_energy, 'num.png')  
            money = os.path.join(img_basic, 'money.png')  
            energy_buy = os.path.join(img_energy, 'buy.png')  
          
            # 树、果实、能量数字、购买能量按钮的位置定义。  
            x, y = 340, 510  
            h = 90  
            position = (  
                [x, y],  
                [x + 50, y - 25],  
                [x + 105, y - 45],  
                [x - 5, y - h - 5],  
                [x + 55, y - 25 - h + 10],  
                [x + 105, y - 45 - h],  
                [x, y - h * 2],  
                [x + 50 + 10, y - 25 - h * 2 - 5],  
                [x + 105 + 25, y - 45 - h * 2 - 14],  
                [x + 30, y - h * 3 - 30]  
            )  # 果实位置  
            energy_num_position = (15, 70)  # 能量位置  
            energy_buy_position = (250, 400)  # 购买能量位置  
          
            def __init__(self, icon, position):  
                """  
                初始化树对象  
                """        # 重写GameSprite的构造函数,用于初始化树对象。  
                super().__init__(icon, position)  
                self.image = load(icon).convert_alpha()  
                self.rect = self.image.get_rect()  
                self.rect.bottomleft = position  
          
          
        class Board(GameSprite):  
            """  
            游戏面板类,显示游戏面板和相关资源。  
            Board类继承自GameSprite类,用于创建和显示游戏板的精灵,并包含移动逻辑。  
            """    # 游戏板、数字格式、任务板、成功、失败、下一步、重玩、星星、金钱的图像路径。  
            step_board = os.path.join(img_board, 'step.png')  
            num_format = os.path.join(img_text, '%d.png')  
            task_board = os.path.join(img_basic, 'task.png')  
            ok = os.path.join(img_basic, 'ok.png')  
            level_format = os.path.join(img_level, '%d.png')  
            success = os.path.join(img_board, 'success.png')  
            fail = os.path.join(img_board, 'fail.png')  
            step_add = os.path.join(img_button, 'step_add.png')  
            next = os.path.join(img_button, 'next.png')  
            replay = os.path.join(img_button, 'replay.png')  
            stars = os.path.join(img_basic, 'star.png')  
            money = os.path.join(img_basic, 'money.png')  
          
            # 按钮和星星的位置定义。  
            button_position = [[300, 465], [500, 465]]  
            starts_position = [[330, 340], [413, 340], [495, 340]]  
          
            def __init__(self, icon, position):  
                """  
                初始化板对象  
                """        super().__init__(icon, position)  
                # 重写GameSprite的构造函数,用于初始化板对象。  
                self.image = load(icon).convert_alpha()  
                self.speed = [0, 44]  # 初始速度  
                self.rect = self.image.get_rect()  
                self.rect.bottomleft = position  
          
            def move(self):  
                """  
                根据速度移动面板  
                """        self.rect = self.rect.move(self.speed)  
                if self.rect.bottom >= 543:  # 到达底部边界  
                    self.speed = [0, -45]  
                if self.speed == [0, -45] and self.rect.bottom 
微信扫一扫加客服

微信扫一扫加客服

点击启动AI问答
Draggable Icon