Python实现贪吃蛇三
上篇文章Python实现贪吃蛇一,实现了一个贪吃蛇的基础版本。后面第二篇文章Python实现贪吃蛇二修改了一些不足,但最近发现还有两点需要优化:
1、生成食物的时候有概率和记分牌重合
2、游戏缺少暂停功能
先看生成食物的时候有概率和记分牌重合的问题。在游戏过程中,有时吃掉一个食物后,发现“没有”生成新的食物。实际上是食物生成的位置和记分牌重合了,被挡住了。这种情况很影响游戏体验,并且尝试去吃掉记分牌下面的食物时很容易撞墙。针对上面问题,在生成新的食物的时候,增加是否与记分牌重合的校验,如果重合,重新生成食物,直到符合要求。修改后的代码片段如下:
def _check_food(self):""" 检查新生成的食物是否不与蛇身及记分牌重合 """food = self.foodfood.rect.x = round(random.randrange(20, self.settings.screen_width - self.settings.snake_width * 2) / 20.0) * 20.0food.rect.y = round(random.randrange(20, self.settings.screen_height - self.settings.snake_height * 2) / 20.0) * 20.0for snake in self.snakes:if snake.rect.colliderect(food.rect) or self.sb.score_rect.colliderect(food.rect):return Falsereturn True
再看游戏暂停功能。 有时正在游戏过程中,尤其是得分比较高的时候,有事需要离开,这时候没有游戏暂停功能的话,只能结束游戏,体验不太好。如何增加暂停功能,思路其实比较简单:在游戏状态类里增加一个游戏暂停状态的属性,当按下“空格”键的时候,将这个属性值取反。同时游戏主循环里增加游戏暂停状态的判断,如果是暂停状态游戏不再刷新,如果不是暂停状态,游戏正常刷新。这样,就实现了游戏暂停功能。相关代码片段:
class GameStats:""" 跟踪游戏的统计信息 """def __init__(self, ai_game):""" 初始化统计信息 """self.settings = ai_game.settingsself.reset_stats()# 游戏刚启动时处于非活动状态self.game_active = False# 游戏暂停状态self.game_pause = Falsedef reset_stats(self):""" 初始化在游戏运行期间可能变化的统计信息 """self.score = 0def run_game(self):""" 开始游戏的主循环 """while True:self._check_events()if self.stats.game_active and not self.stats.game_pause:if self.settings.update_count > 500: #控制游戏速度self._update_snakes()self._check_edges()self.settings.update_count = 0self.settings.update_count += self.settings.game_speedself._update_screen()
修改后主程序类(gluttonous_snake.py)的完整代码:
import sys
import timeimport pygame
import randomfrom 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 GameSoundclass 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 / 2snake.y = self.settings.screen_height / 2 + snake_number * self.settings.snake_heightsnake.rect.x = snake.xsnake.rect.y = snake.yself.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 = 0self.sb.prep_score()self.settings.snake_direction = 'up'self.settings.update_count = 0self.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_SPACE:self.stats.game_pause = not self.stats.game_pauseelif event.key == pygame.K_q:sys.exit()def _change_speed(self, add):# 改变蛇的移动速度if (self.settings.game_speed + add) > 0:self.settings.game_speed += adddef _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()breakdef _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.foodif 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 Trueelse:return Falsedef _update_food(self):""" 更新食物 """while True:if self._check_food():returndef _check_food(self):""" 检查新生成的食物是否不与蛇身及记分牌重合 """food = self.foodfood.rect.x = round(random.randrange(20, self.settings.screen_width - self.settings.snake_width * 2) / 20.0) * 20.0food.rect.y = round(random.randrange(20, self.settings.screen_height - self.settings.snake_height * 2) / 20.0) * 20.0for snake in self.snakes:if snake.rect.colliderect(food.rect) or self.sb.score_rect.colliderect(food.rect):return Falsereturn Truedef _create_snake_head(self, x, y):""" 创建蛇头 """snake = Snake(self)if self.settings.snake_direction == 'up':snake.x = xsnake.y = y - self.settings.snake_heightelif self.settings.snake_direction == 'down':snake.x = xsnake.y = y + self.settings.snake_heightelif self.settings.snake_direction == 'right':snake.x = x + self.settings.snake_widthsnake.y = yelif self.settings.snake_direction == 'left':snake.x = x - self.settings.snake_widthsnake.y = ysnake.rect.x = snake.xsnake.rect.y = snake.yself._check_eat_self(snake)self.snakes.insert(0, snake)def run_game(self):""" 开始游戏的主循环 """while True:self._check_events()if self.stats.game_active and not self.stats.game_pause:if self.settings.update_count > 500: #控制游戏速度self._update_snakes()self._check_edges()self.settings.update_count = 0self.settings.update_count += self.settings.game_speedself._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()
相关文章:
Python实现贪吃蛇三
上篇文章Python实现贪吃蛇一,实现了一个贪吃蛇的基础版本。后面第二篇文章Python实现贪吃蛇二修改了一些不足,但最近发现还有两点需要优化: 1、生成食物的时候有概率和记分牌重合 2、游戏缺少暂停功能 先看生成食物的时候有概率和记分牌重合的…...
Docker 中多个容器之间的通信
在 Docker 中,多个容器之间的通信可以通过以下几种主要方式实现,具体选择取决于网络需求、隔离性及管理复杂度: 一、自定义 Bridge 网络(推荐) 通过创建自定义的 Docker 网络,容器可以加入同一网络并通过容…...
AI大模型学习九:Sealos cloud+k8s云操作系统私有化一键安装脚本部署完美教程
一、说明 Sealos是一款基于Kubernetes(K8s)的云操作系统发行版,它将K8s以及常见的分布式应用如Docker、Dashboard、Ingress等进行了集成和封装,使得用户可以在不深入了解复杂的K8s底层原理的情况下,快速搭建起一个…...
详解关于VS配置好Qt环境之后但无法打开ui界面
目录 找到Qt安装目录中designer.exe的路径 找到vs中的解决方案资源管理器 右键ui文件,找到打开方式 点击添加 然后把前面designer.exe的路径填到程序栏中,点击确定 然后设置为默认值,并点击确定 当在vs中配置好Qt环境之后,但…...
Python Cookbook-6.5 继承的替代方案——自动托管
任务 你需要从某个类或者类型继承,但是需要对继承做一些调整。比如,需要选择性地隐藏某些基类的方法,而继承并不能做到这一点。 解决方案 继承是很方便的,但它并不是万用良药。比如,它无法让你隐藏基类的方法或者属…...
【深度学习与大模型基础】第9章-条件概率以及条件概率的链式法则
简单理解条件概率 条件概率就是在已知某件事发生的情况下,另一件事发生的概率。用数学符号表示就是: P(A|B) 在B发生的前提下,A发生的概率。 计算机例子:垃圾邮件过滤 假设你写了一个程序来自动判断邮件是否是垃圾邮件…...
STM32-FreeRTOS的详细配置
配置FreeRTOS 原文链接:https://ydamooc.github.io/posts/c9defcd/ 1.1 下载FreeRTOS 打开FreeRTOS官网:https://www.freertos.org/ 点击下载,并且选择"FreeRTOS 202212.01"版本,再点击Download按钮下载官方的资源包…...
行为检测技术指南
以下是行为检测技术的全面技术指南,涵盖核心技术原理、应用场景及发展趋势: 一、核心行为检测技术分类 1. 基于计算机视觉的行为检测 目标检测算法 通过目标定位与分类识别行为,典型算法包括: YOLO系列(YOLOv5/v8):实时性强,适用于视频流中的动作识别(如摔倒、抽烟检…...
视觉自回归图像生成:基于多模态大模型的万字深度梳理
目前利用多模态大模型进行图像生成主要有以下两种形式: LLM作为condtioner:利用MLLM依据用户输入的text prompt来生成条件信息,条件信息被注入到下游生成模型进行更精细化的生成控制。这种形式通常需要外接一个额外专门的多模态生成模型&…...
openssh离线一键升级脚本分享(含安装包)
查看当前的版本 [rootmyoracle ~]#ssh -V相关安装包下载地址 openssh下载地址:http://ftp.openbsd.org/pub/OpenBSD/OpenSSH/portable/openssl下载地址:https://www.openssl.org/source/zlib下载地址:http://www.zlib.net/今天演示从7.4升级…...
音视频之H.265/HEVC预测编码
H.265/HEVC系列文章: 1、音视频之H.265/HEVC编码框架及编码视频格式 2、音视频之H.265码流分析及解析 3、音视频之H.265/HEVC预测编码 预测编码是视频编码中的核心技术之一。对于视频信号来说,一幅图像内邻近像素之间有着较强的空间相关性,相邻图像之…...
Python异步编程入门:Async/Await实战详解
引言 在当今高并发的应用场景下,传统的同步编程模式逐渐暴露出性能瓶颈。Python通过asyncio模块和async/await语法为开发者提供了原生的异步编程支持。本文将手把手带你理解异步编程的核心概念,并通过实际代码案例演示如何用异步爬虫提升10倍效率&#…...
设计模式每日硬核训练 Day 13:桥接模式(Bridge Pattern)完整讲解与实战应用
🔄 回顾 Day 12:装饰器模式小结 在 Day 12 中,我们学习了装饰器模式(Decorator Pattern): 强调在不改变原类结构的前提下,动态为对象增强功能。通过“包装对象”实现运行时组合,支…...
库洛游戏一面+二面
目录 一面 1. ArrayList和LinkedList的区别,就是我在插入和删除的时候他们在时间复杂度上有什么区别 2. hashmap在java的底层是怎么实现的 3. 红黑树的实现原理 4. 红黑树的特点 5. 为什么红黑树比链表查询速度快 6. 在java中字符串的操作方式有几种 7. Stri…...
前端面试-Vue篇
核心概念 Vue 3的响应式原理与Vue 2有何本质区别?Vue中虚拟DOM的diff算法优化策略有哪些?Vue组件间通信方式有哪些?适用场景分别是什么?Vue的生命周期钩子在Composition API中如何替代?Vue的模板编译过程是怎样的&…...
XSS攻击(反射型、存储型、dom型、PDF、SWF、SVG)
一、XSS攻击是什么 XSS是恶意攻击者往 Web 页面里插入恶意可执行网页脚本代码,当用户浏览该页之时,嵌入其中 Web 里面的脚本代码会被执行,从而可以达到攻击者盗取用户信息或其他侵犯用户安全隐私的目的。 二、XSS分类 反射型XSS 常见情况是…...
C复习(主要复习)
指针和数组 指针数组是一个数组,数组的每个元素都是指针。它适用于需要存储多个指针的场景,如字符串数组。数组指针是一个指针,指向一个数组。它适用于需要传递整个数组给函数或处理多维数组的场景。 函数指针:函数指针的定义需要…...
Python及C++中的集合
1. Python 中的集合(set) 1.1 特性 无序性:集合中的元素没有顺序,不能通过索引访问。唯一性:集合中的元素不能重复,如果尝试添加重复的元素,集合会自动忽略。可变性:集合是可变的&…...
Ubuntu24.04搭建ESP8266_RTOS_SDK V3.4开发环境
【本文发布于https://blog.csdn.net/Stack_/article/details/147194686,未经允许不得转载,转载须注明出处】 需要有Linux使用基础,自行准备 1、VM17 Pro (自行搜索教程安装) 2、ubuntu-24.04-desktop-amd64 ࿰…...
数据仓库分层存储设计:平衡存储成本与查询效率
数据仓库分层存储不仅是一个技术问题,更是一种艺术:如何在有限的资源下,让数据既能快速响应查询,又能以最低的成本存储? 目录 一、什么是数据仓库分层存储? 二、分层存储的体系架构 1. 数据源层(ODS,Operational Data Store) 2. 数据仓库层(DW,Data Warehouse)…...
matlab求和∑函数方程编程?
matlab求和∑函数方程编程? 一 题目:求下列函数方程式的和 二:代码如下: >> sum_result 0; % 初始化求和变量 for x 1:10 % 设…...
基于Java+MySQL实现的(Web)科研资讯推送系统
科研资讯推送系统 技术选型 核心框架:SpringBoot 数据库层:springdatajpa 安全框架:Shiro 数据库连接池:Druid 缓存:Ehcache 部署 阿里云学生机:ecs.n4.small Tomcat:9.0 JDK:1.8 数据库:MySQL8.0 操作系统:CentOS…...
PHP弱类型hash比较缺陷
目录 0x00 漏洞原因 0x01 利用方法 0x02 [BJDCTF2020]Easy MD5 1 利用md5($password,true)实现SQL注入 PHP md5弱类型比较 数组绕过 0x00 漏洞原因 1、在进行比较的时候,会先将两边的变量类型转化成相同的,再进行比较 2、0e在比较的时候会将其认…...
asm汇编源代码之-汉字点阵字库显示程序源代码下载
汉字点阵字库显示程序 源代码下载 文本模式下显示16x16点阵汉字库内容的程序(标准16x16字库需要使用CHGHZK转换过后才能使用本程序正常显示) 本程序需要调用file.asm和string.asm中的子程序,所以连接时需要把它们连接进来,如下 C:\> tlink showhzk file string 调用参…...
Excel 中让表格内容自适应列宽和行高
Excel 中让表格内容自适应列宽和行高 目录 Excel 中让表格内容自适应列宽和行高自适应列宽自适应行高在Excel中让表格内容自适应列宽和行高,可参考以下操作: 自适应列宽 方法一:手动调整 选中需要调整列宽的列(如果是整个表格,可点击表格左上角行号和列号交叉处的三角形全…...
从 Vue 到 React:深入理解 useState 的异步更新
目录 从 Vue 到 React:深入理解 useState 的异步更新与函数式写法1. Vue 的响应式回顾:每次赋值立即生效2. React 的状态更新是异步且批量的原因解析 3. 函数式更新:唯一的正确写法4. 对比 Vue vs React 状态更新5. React useState 的核心源码…...
Java使用ANTLR4对Lua脚本语法校验
文章目录 什么是ANTLR?第一个例子ANTLR4 的工作流程Lua脚本语法校验准备一个Lua Grammar文件maven配置生成Lexer Parser Listener Visitor代码新建实体类Lua语法遍历器语法错误监听器单元测试 参考 什么是ANTLR? https://www.antlr.org/ ANTLR (ANothe…...
vue3.2 + element-plus 实现跟随input输入框的弹框,弹框里可以分组或tab形式显示选项
效果 基础用法(分组选项) 高级用法(带Tab栏) <!-- 弹窗跟随通用组件 SmartSelector.vue --> <!-- 弹窗跟随通用组件 --> <template><div class"smart-selector-container"><el-popove…...
Vue 2.0和3.0笔记
Vue 3 关于组件 今天回顾了下2.0关于组件的内容,3.0定义组件的方式多了一种就是通过单文件组件(Single-File Component)的方式将Vue的模板,逻辑和样式放到一个文件中,2.0则不同,它是将模板放到一个属性中…...
Windows VsCode Terminal窗口使用Linux命令
背景描述: 平时开发环境以Linux系统为主,有时又需要使用Windows系统下开发环境,为了能像Linux系统那样用Windows VsCode,Terminal命令行是必不可少内容。 注:Windows11 VsCode 1.99.2 下面介绍,如何在V…...
