Python实现贪吃蛇二

news2025/4/18 3:00:07

        上篇文章Python实现贪吃蛇一,实现了一个贪吃蛇的基础版本,但存在一些不足,也缺乏一些乐趣。本篇文章将对其进行一些改进,主要修改/实现以下几点:

        1、解决食物随机生成的位置与蛇身重合问题

        2、蛇身移动加速/减速功能

        3、增加一些音效

        一、首先看如何解决食物随机生成的位置与蛇身重合问题,基础版本食物位置是随机生成的,这样有一定概率与蛇身重合,并且随着得分越来越高,重合的概率越来越大。思路是随机生成食物后检测食物位置是否与蛇身重合,如果重合,再次生成,直到不重合。修改后的代码片段如下:

    def _update_food(self):
        """ 更新食物 """
        while True:
            if self._check_food():
                return

    def _check_food(self):
        """ 检查新生成的食物是否不与蛇身重合 """
        food = self.food
        food.rect.x = round(
            random.randrange(20, self.settings.screen_width - self.settings.snake_width * 2) / 20.0) * 20.0
        food.rect.y = round(
            random.randrange(20, self.settings.screen_height - self.settings.snake_height * 2) / 20.0) * 20.0
        for snake in self.snakes:
            if snake.rect.colliderect(food.rect):
                return False
        return True

        二、蛇身移动加速/减速功能,计划实现的效果是按蛇身前进方向相同的按键时,速度加1,按相反的按键时速度减1,但是不能减到0。例如:蛇在向上移动时,此时按“向上”键,速度加1,按“向下”键,速度减1,按“向左”或“向右”键,速度不变,只变方向。代码实现如下:

    def _check_keydown_events(self, event):
        # 响应按键
        if event.key == pygame.K_RIGHT:
            if self.settings.snake_direction == 'right':
                self._change_speed(1)
            elif self.settings.snake_direction == 'left':
                self._change_speed(-1)
            else:
                self.settings.snake_direction = 'right'
        elif event.key == pygame.K_LEFT:
            if self.settings.snake_direction == 'left':
                self._change_speed(1)
            elif self.settings.snake_direction == 'right':
                self._change_speed(-1)
            else:
                self.settings.snake_direction = 'left'
        elif event.key == pygame.K_UP:
            if self.settings.snake_direction == 'up':
                self._change_speed(1)
            elif self.settings.snake_direction == 'down':
                self._change_speed(-1)
            else:
                self.settings.snake_direction = 'up'
        elif event.key == pygame.K_DOWN:
            if self.settings.snake_direction == 'down':
                self._change_speed(1)
            elif self.settings.snake_direction == 'up':
                self._change_speed(-1)
            else:
                self.settings.snake_direction = 'down'
        elif event.key == pygame.K_q:
            sys.exit()

    def _change_speed(self, add):
        # 改变蛇的移动速度
        if (self.settings.game_speed + add) > 0:
            self.settings.game_speed += add

         三、增加游戏音效:在游戏开始后,循环播放背景音乐;蛇吃到食物的时候播放一个吃食物的声音;每吃到十个食物播放鼓掌声;蛇撞到周边或自己身体时播放游戏结束声音。思路是,游戏初始化的时候加载声音,在相关的节点,播放对应的声音。代码如下:

        声音类(game_sound.py):

import pygame


class GameSound:
    """ 游戏声音的类 """

    def __init__(self, file_name):
        """ 初始化声音 """
        super().__init__()
        self.file_name = file_name

        # 加载音效
        self.sound = pygame.mixer.Sound(f"sounds/{self.file_name}")

    def play(self, times=1):
        # 播放声音
        self.sound.play(loops=times - 1)

        声音素材:

        声音初始化:

# 初始化音频混合器
pygame.mixer.init()

# 初始化游戏声音
self.snake_eat_food_sound = GameSound('snake_eat_food.mp3')
self.snake_game_over_sound = GameSound('snake_game_over.mp3')
self.background_sound = GameSound('snake_background_sound.mp3')
self.cheer_sound = GameSound('snake_cheer_sound.mp3')

        播放声音的场景:

    def _check_eat_food(self):
        """ 检测蛇吃到食物 """
        snake_head = self.snakes[0]
        food = self.food
        if snake_head.rect.colliderect(food.rect):
            self.stats.score += self.settings.food_score
            # 播放声音
            if self.stats.score % 100 == 0:
                self.cheer_sound.play(1)
            else:
                self.snake_eat_food_sound.play(1)
            self.sb.prep_score()
            self._update_food()
            return True
        else:
            return False

    def _game_over(self):
        # 播放音乐
        self.snake_game_over_sound.play(1)
        self.stats.game_active = False
        # 显示鼠标光标
        pygame.mouse.set_visible(True)

    def _check_play_button(self, mouse_pos):
        """ 在玩家单击Play按钮时开始新游戏 """
        button_clicked = self.play_button.rect.collidepoint(mouse_pos)
        if button_clicked and not self.stats.game_active:
            # 重置游戏设置
            self.stats.game_active = True

            # 播放背景音乐
            self.background_sound.play(0)

            # 隐藏鼠标光标
            pygame.mouse.set_visible(False)

        下面是修改后的主程序类(gluttonous_snake.py)的完整代码:

import sys
import time

import pygame
import random

from settings import Settings
from snake import Snake
from game_stats import GameStats
from button import Button
from food import Food
from scoreboard import Scoreboard
from game_sound import GameSound


class GluttonousSnake:
    """ 管理游戏资源和行为的类 """

    def __init__(self):
        """ 初始化游戏并创建游戏资源 """
        pygame.init()

        # 初始化音频混合器
        pygame.mixer.init()

        # 初始化游戏声音
        self.snake_eat_food_sound = GameSound('snake_eat_food.mp3')
        self.snake_game_over_sound = GameSound('snake_game_over.mp3')
        self.background_sound = GameSound('snake_background_sound.mp3')
        self.cheer_sound = GameSound('snake_cheer_sound.mp3')

        self.settings = Settings()

        self.screen = pygame.display.set_mode((self.settings.screen_width, self.settings.screen_height))

        pygame.display.set_caption("贪吃蛇")

        # 创建一个用于存储游戏统计信息的实例
        self.stats = GameStats(self)

        # 创建记分牌
        self.sb = Scoreboard(self)

        self.food = Food(self)

        self.snakes = []

        self._create_snakes()

        # 创建Play按钮
        self.play_button = Button(self, "Play")

    def _create_snakes(self):
        """ 初始化创建长度为3的蛇 """
        for snake_number in range(3):
            self._create_snake(snake_number)

    def _create_snake(self, snake_number):
        """ 创建一段蛇身 """
        snake = Snake(self)
        self.screen_rect = self.screen.get_rect()
        snake.x = self.settings.screen_width / 2
        snake.y = self.settings.screen_height / 2 + snake_number * self.settings.snake_height
        snake.rect.x = snake.x
        snake.rect.y = snake.y
        self.snakes.append(snake)

    def _check_events(self):
        # 监视键盘和鼠标的事件
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                sys.exit()
            elif event.type == pygame.KEYDOWN:
                self._check_keydown_events(event)
            elif event.type == pygame.MOUSEBUTTONDOWN:
                mouse_pos = pygame.mouse.get_pos()
                self._check_play_button(mouse_pos)

    def _check_play_button(self, mouse_pos):
        """ 在玩家单击Play按钮时开始新游戏 """
        button_clicked = self.play_button.rect.collidepoint(mouse_pos)
        if button_clicked and not self.stats.game_active:
            # 重置游戏设置
            self.stats.game_active = True

            # 播放背景音乐
            self.background_sound.play(0)

            # 隐藏鼠标光标
            pygame.mouse.set_visible(False)

            self.stats.score = 0
            self.sb.prep_score()
            self.settings.snake_direction = 'up'
            self.settings.update_count = 0
            self.settings.game_speed = 1

            # 清空余下的蛇身
            self.snakes.clear()

            # 重新创建蛇身
            self._create_snakes()

    def _check_keydown_events(self, event):
        # 响应按键
        if event.key == pygame.K_RIGHT:
            if self.settings.snake_direction == 'right':
                self._change_speed(1)
            elif self.settings.snake_direction == 'left':
                self._change_speed(-1)
            else:
                self.settings.snake_direction = 'right'
        elif event.key == pygame.K_LEFT:
            if self.settings.snake_direction == 'left':
                self._change_speed(1)
            elif self.settings.snake_direction == 'right':
                self._change_speed(-1)
            else:
                self.settings.snake_direction = 'left'
        elif event.key == pygame.K_UP:
            if self.settings.snake_direction == 'up':
                self._change_speed(1)
            elif self.settings.snake_direction == 'down':
                self._change_speed(-1)
            else:
                self.settings.snake_direction = 'up'
        elif event.key == pygame.K_DOWN:
            if self.settings.snake_direction == 'down':
                self._change_speed(1)
            elif self.settings.snake_direction == 'up':
                self._change_speed(-1)
            else:
                self.settings.snake_direction = 'down'
        elif event.key == pygame.K_q:
            sys.exit()

    def _change_speed(self, add):
        # 改变蛇的移动速度
        if (self.settings.game_speed + add) > 0:
            self.settings.game_speed += add

    def _update_snakes(self):
        """ 更新蛇 """
        snake_head = self.snakes[0]
        self._create_snake_head(snake_head.rect.x, snake_head.rect.y)

        """ 检查是否吃到食物 """
        eat_food = self._check_eat_food()
        if not eat_food:
            self.snakes.pop()

    def _check_edges(self):
        """ 蛇碰到边缘时采取相应的措施 """
        snake_head = self.snakes[0]
        if snake_head.check_edges():
            self._game_over()

    def _check_eat_self(self, snake_head):
        """ 是否碰到自己 """
        for snake in self.snakes:
            if snake.rect.colliderect(snake_head.rect):
                self._game_over()
                break

    def _game_over(self):
        # 播放音乐
        self.snake_game_over_sound.play(1)
        self.stats.game_active = False
        # 显示鼠标光标
        pygame.mouse.set_visible(True)

    def _check_eat_food(self):
        """ 检测蛇吃到食物 """
        snake_head = self.snakes[0]
        food = self.food
        if snake_head.rect.colliderect(food.rect):
            self.stats.score += self.settings.food_score
            # 播放声音
            if self.stats.score % 100 == 0:
                self.cheer_sound.play(1)
            else:
                self.snake_eat_food_sound.play(1)
            self.sb.prep_score()
            self._update_food()
            return True
        else:
            return False

    def _update_food(self):
        """ 更新食物 """
        while True:
            if self._check_food():
                return

    def _check_food(self):
        """ 检查新生成的食物是否不与蛇身重合 """
        food = self.food
        food.rect.x = round(
            random.randrange(20, self.settings.screen_width - self.settings.snake_width * 2) / 20.0) * 20.0
        food.rect.y = round(
            random.randrange(20, self.settings.screen_height - self.settings.snake_height * 2) / 20.0) * 20.0
        for snake in self.snakes:
            if snake.rect.colliderect(food.rect):
                return False
        return True

    def _create_snake_head(self, x, y):
        """ 创建蛇头 """
        snake = Snake(self)
        if self.settings.snake_direction == 'up':
            snake.x = x
            snake.y = y - self.settings.snake_height
        elif self.settings.snake_direction == 'down':
            snake.x = x
            snake.y = y + self.settings.snake_height
        elif self.settings.snake_direction == 'right':
            snake.x = x + self.settings.snake_width
            snake.y = y
        elif self.settings.snake_direction == 'left':
            snake.x = x - self.settings.snake_width
            snake.y = y
        snake.rect.x = snake.x
        snake.rect.y = snake.y
        self._check_eat_self(snake)
        self.snakes.insert(0, snake)

    def run_game(self):
        """ 开始游戏的主循环 """
        while True:
            self._check_events()
            if self.stats.game_active:
                if self.settings.update_count > 500: #控制游戏速度
                    self._update_snakes()
                    self._check_edges()
                    self.settings.update_count = 0
                self.settings.update_count += self.settings.game_speed
            self._update_screen()

    def _update_screen(self):
        # 每次循环时都会重绘屏幕
        self.screen.fill(self.settings.bg_color)
        self.food.draw_food()
        for snake in self.snakes:
            snake.draw_snake()

        # 如果游戏处于非活动状态,就绘制Play按钮
        if not self.stats.game_active:
            self.play_button.draw_button()

        # 显示得分
        self.sb.show_score()

        # 让最近绘制的屏幕可见
        pygame.display.flip()

if __name__ == '__main__':
    # 创建实例并运行游戏
    ai = GluttonousSnake()
    ai.run_game()

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2335504.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

基于51单片机的正负5V数字电压表( proteus仿真+程序+设计报告+讲解视频)

基于51单片机的正负5V数字电压表( proteus仿真程序设计报告讲解视频) 仿真图proteus7.8及以上 程序编译器:keil 4/keil 5 编程语言:C语言 设计编号:S0101 1. 主要功能: 设计一个基于51单片机数字电压表 1、能够…

Java雪花算法

以下是用Java实现的雪花算法代码示例,包含详细注释和异常处理: 代码下面有解析 public class SnowflakeIdGenerator {// 起始时间戳(2020-01-01 00:00:00)private static final long START_TIMESTAMP 1577836800000L;// 各部分…

前端大屏可视化项目 局部全屏(指定盒子全屏)

需求是这样的&#xff0c;我用的项目是vue admin 项目 现在需要在做大屏项目 不希望显示除了大屏的其他东西 于是想了这个办法 至于大屏适配问题 请看我文章 底部的代码直接复制就可以运行 vue2 px转rem 大屏适配方案 postcss-pxtorem-CSDN博客 <template><div …

01_JDBC

文章目录 一、概述1.1、什么是JDBC1.2、JDBC原理 二、JDBC入门2.1、准备工作2.1.1、建库建表2.1.2、新建项目 2.2、建立连接2.2.1、准备四大参数2.2.2、加载驱动2.2.3、准备SQL语句2.2.4、建立连接2.2.5、常见问题 2.3、获取发送SQL的对象2.4、执行SQL语句2.5、处理结果2.6、释…

Spring Boot 热部署详解,包含详细的配置项说明

Spring Boot 热部署详解 1. 热部署简介 热部署&#xff08;Hot Deployment&#xff09;允许在应用运行时修改代码或配置文件&#xff0c;无需重启应用即可使更改生效。Spring Boot 通过 spring-boot-devtools 模块实现这一功能&#xff0c;其核心依赖于 LiveReload 技术和自动…

剑指Offer(数据结构与算法面试题精讲)C++版——day12

剑指Offer&#xff08;数据结构与算法面试题精讲&#xff09;C版——day12 题目一&#xff1a;小行星碰撞题目二&#xff1a;每日温度题目三&#xff1a;直方图最大矩形面积附录&#xff1a;源码gitee仓库 题目一&#xff1a;小行星碰撞 题目&#xff1a;输入一个表示小行星的数…

Docker学习笔记-docker安装、删除

一、在centOS 7中docker的默认安装目录 # Docker 主配置文件目录 ls /etc/docker# Docker 数据目录&#xff08;镜像、容器、卷等&#xff09; ls /var/lib/docker# Docker 可执行文件路径 which docker # 输出类似 /usr/bin/docker 二、docker文件目录说明 目录/文件用途/…

【Python 开源】你的 Windows 关机助手——PyQt5 版定时关机工具

&#x1f5a5;️ 你的 Windows 关机助手——PyQt5 版定时关机工具 相关资源文件已经打包成EXE文件&#xff0c;可双击直接运行程序&#xff0c;且文章末尾已附上相关源码&#xff0c;以供大家学习交流&#xff0c;博主主页还有更多Python相关程序案例&#xff0c;秉着开源精神的…

【Python爬虫】简单介绍

目录 一、基本概念 1.1 什么是爬虫 1.2 Python为什么适合爬虫 1.3 Python爬虫应用领域 &#xff08;1&#xff09;数据采集与分析 市场调研 学术研究 &#xff08;2&#xff09;内容聚合与推荐 新闻聚合 视频内容聚合 &#xff08;3&#xff09;金融领域 股票数据获…

使用MCP服务通过自然语言操作数据库(vscode+cline版本)

使用MCP服务操纵数据库(vscodecline版本) 本文主要介绍&#xff0c;在vscode中使用cline插件调用deepseek模型&#xff0c;通过MCP服务器 使用自然语言去操作指定数据库。本文使用的是以己经创建号的珠海航展数据库。 理解MCP服务&#xff1a; MCP&#xff08;Model Context…

Vue 3 + TypeScript 实现一个多语言国际化组件(支持语言切换与内容加载)

文章目录 一、项目背景与功能概览二、项目技术架构与依赖安装2.1 技术栈2.2 安装依赖 三、国际化组件实现3.1 创建 i18n 实例3.2 配置 i18n 到 Vue 应用3.3 在组件中使用国际化内容3.4 支持语言切换 四、支持类型安全4.1 添加类型支持4.2 自动加载语言文件 一、项目背景与功能概…

PhalApi 2.x:让PHP接口开发从“简单”到“极简”的开源框架

—— 专为高效开发而生&#xff0c;助你轻松构建高可用API接口 一、为什么选择PhalApi 2.x&#xff1f; 1.轻量高效&#xff0c;性能卓越 PhalApi 2.x 是一款专为接口开发设计的轻量级PHP框架&#xff0c;其核心代码精简但功能强大。根据开发者实测&#xff0c;在2核2G服务器…

Java 企业级应用:SOA 与微服务的对比与选择

企业级应用开发中&#xff0c;架构设计是决定系统可扩展性、可维护性和性能的关键因素。SOA&#xff08;面向服务的架构&#xff09;和微服务架构是两种主流的架构模式&#xff0c;它们各自有着独特的和设计理念适用场景。本文将深入探讨 SOA 和微服务架构的对比&#xff0c;并…

Zookeeper的典型应用场景?

大家好&#xff0c;我是锋哥。今天分享关于【Zookeeper的典型应用场景?】面试题。希望对大家有帮助&#xff1b; Zookeeper的典型应用场景? 1000道 互联网大厂Java工程师 精选面试题-Java资源分享网 ZooKeeper 是一个开源的分布式协调服务&#xff0c;主要用于管理和协调大…

数据分析不只是跑个SQL!

数据分析不只是跑个SQL&#xff01; 数据分析五大闭环&#xff0c;你做到哪一步了&#xff1f;闭环一&#xff1a;认识现状闭环二&#xff1a;原因分析闭环三&#xff1a;优化表现闭环四&#xff1a;预测走势闭环五&#xff1a;主动解读数据 数据思维&#xff1a;WHY-WHAT-HOW模…

Dify智能体平台源码二次开发笔记(4) - 多租户的SAAS版实现

前言 Dify 的多租户功能是其商业版的标准功能&#xff0c;我们应当尊重其盈利模式。只有保持良性的商业运作&#xff0c;Dify 才能持续发展&#xff0c;并为用户提供更优质的功能。因此&#xff0c;此功能仅限学习使用。 我们的需求是&#xff1a;实现类似 SaaS 版的账号隔离&a…

layui中transfer两个table展示不同的数据列

在项目的任务开发中需要达到transfer右侧table需要有下拉框可选择状态&#xff0c;左侧table不变 使用的layui版本为2.4.5&#xff0c;该版本没有对transfer可自定义数据列的配置&#xff0c;所以改动transfer.js中的源码 以下为transfer.js部分源码 也是transfer.js去render的…

【机器学习】机器学习笔记

1 机器学习定义 计算机程序从经验E中学习&#xff0c;解决某一任务T&#xff0c;进行某一性能P&#xff0c;通过P测定在T上的表现因经验E而提高。 eg&#xff1a;跳棋程序 E&#xff1a; 程序自身下的上万盘棋局 T&#xff1a; 下跳棋 P&#xff1a; 与新对手下跳棋时赢的概率…

STM32 BOOT设置,bootloader,死锁使用方法

目录 BOOT0 BOOT1的配置含义 bootloader使用方法 芯片死锁解决方法开发调试过程中&#xff0c;由于某种原因导致内部Flash锁死&#xff0c;无法连接SWD以及JTAG调试&#xff0c;无法读到设备&#xff0c;可以通过修改BOOT模式重新刷写代码。修改为BOOT01&#xff0c;BOOT10…

【Redis】string类型

目录 1、介绍2、底层实现【1】SDS【2】int编码【3】embstr编码【4】raw编码【5】embstr和raw的区别 3、常用指令【1】字符串基本操作&#xff1a;【2】批量操作【3】计数器【4】过期时间【5】不存在就插入 4、使用场景 1、介绍 string是redis中最简单的键值对形式&#xff0c;…