Python贪吃蛇双人大战-升级版

在玩了几天贪吃蛇游戏之后,(代码可参考我之前写的 Python贪吃蛇双人大战),家里小朋友提出了新的需求(用户反馈)如下:

  1. 豆子不能出现在豆子上。
  2. 豆子不能出现在蛇身上。
  3. 要显示得分,方便看出来谁的蛇比较长。
  4. 如果蛇头撞到另一条蛇,自己挂掉,变成豆子
  5. 蛇变成的豆子被吃了之后不重新生成
  6. 燃烧自己身体可以加速,每次燃烧身体减少一格,速度提升至两倍

趁着是周末,赶紧实现一下新需求,以满足小朋友的期望。

豆子不出现在重复的位置

为了实现豆子出现位置不与已有的豆子重复,也不与蛇所在位置重复,修改了豆类的generate函数如下:

    def generate(self, snake1, snake2):while self.curNum < self.totalNum:x = random.randrange(0,SCREEN_WIDTH/GRID_SIZE)y = random.randrange(0,SCREEN_HEIGHT/GRID_SIZE)newBeanPos = [int(x*GRID_SIZE),int(y*GRID_SIZE)]#检查豆子位置是否重复isBeanRepeated = Falsefor bean in self.beans: #豆子不能与豆子位置重复if bean.pos == newBeanPos:isBeanRepeated = Truebreakfor pos in snake1.segments: #豆子不能与蛇位置重复if pos == newBeanPos:isBeanRepeated = Truebreakfor pos in snake2.segments: #豆子不能与蛇位置重复if pos == newBeanPos:isBeanRepeated = Truebreak      #新生成的豆子在不重复的地方if not isBeanRepeated:self.beans.append(Bean(self.color, newBeanPos))self.curNum = self.curNum + 1

因为要判断蛇位置,所以把蛇作为参数传进去了,增加了两个参数。函数中每次生成豆子的位置之后进行判断,不重复再增加。
当然,因为改了函数接口,所以主循环中调用的地方也要增加相对应的参数,相关代码如下:

    # 初始化豆子yellowBeans = Beans(YELLOW, BEAN_NUM)yellowBeans.generate(snake1, snake2)
        # 如果豆子被吃掉,则重新生成豆子,否则蛇长度减少一格if yellowBeans.beEaten(snake1.headPos):yellowBeans.generate(snake1, snake2)else:snake1.pop()if yellowBeans.beEaten(snake2.headPos):yellowBeans.generate(snake1, snake2)else:snake2.pop()

显示得分

显示得分这个功能比较简单,就用蛇增加的长度表示得分即可,而蛇的长度就是蛇类中segments的长度。于是创建一个函数getLen直接返回segments的长度。

    def getLen(self):return len(self.segments)

在主循环中创建分数显示层,设置其字体大小如下:

    # 分数显示层字体大小scoreFont = pygame.font.Font(None, int(32*GRID_SIZE/20))

并在刷新时增加分数层的刷新:

        # 绘制刷新playSurface.fill(BLACK) # 绘制pygame显示层yellowBeans.show(playSurface)snake1.show(playSurface)snake2.show(playSurface)# 显示分数scoreSurf = scoreFont.render('P1 Score:{}    vs    P2 Score:{}'.format(snake1.getLen()-3, snake2.getLen()-3), True, WHITE)scoreRect = scoreSurf.get_rect()scoreRect.midtop = (SCREEN_WIDTH/2, 0)playSurface.blit(scoreSurf, scoreRect)pygame.display.flip()   # 刷新pygame显示层

当然,为了显示分数,需要最上面一行不产生豆子,所以修改豆类generate函数中的y值如下:

y = random.randrange(1,SCREEN_HEIGHT/GRID_SIZE)

蛇撞挂掉变豆子

这个功能相对而言就复杂一些了,同时考虑到蛇变成的豆子被吃了之后不重新生成,于是重新定义了一个蛇豆类如下:

class SnakeBeans:def __init__(self, snake):self.color = NORMAL_BEAN_COLORself.beans = []for pos in snake.segments:self.beans.append(Bean(NORMAL_BEAN_COLOR, pos))def beEaten(self, snakePos):for bean in self.beans:if bean.beEaten(snakePos):self.beans.remove(bean)return Truereturn Falsedef show(self, playSurface):for bean in self.beans:pygame.draw.rect(playSurface,self.color,Rect(bean.pos[0],bean.pos[1],GRID_SIZE,GRID_SIZE))

因为蛇豆不需要重生,所以比较简单,能被吃就可以了。

为了实现蛇撞挂掉,修改了蛇类的 moveAndAdd 函数,增加了检查是否撞到另一条蛇代码,传入另一条蛇作为参数,返回是否撞到。

    def moveAndAdd(self, snake=[]):# 根据方向移动蛇头的坐标if self.direction == 1:self.headPos[0] += GRID_SIZEif self.direction == -1:self.headPos[0] -= GRID_SIZEif self.direction == -2:self.headPos[1] -= GRID_SIZEif self.direction == 2:self.headPos[1] += GRID_SIZE#检查蛇头是否撞到另一条蛇身if snake == []:self.segments.insert(0,list(self.headPos)) # 在蛇头插入一格return FalseisSnakeHit = Falsefor pos in snake.segments:if self.headPos == pos:isSnakeHit = Truebreakif not isSnakeHit:self.segments.insert(0,list(self.headPos)) # 在蛇头插入一格return isSnakeHit

于是在主循环中就可以判断是否撞到,撞到则爆豆子,自己再重生:

            if snake1.moveAndAdd(snake2): #撞到了另一条蛇身snake1Beans = SnakeBeans(snake1)snake1.respawn()continue

然后这时候发现重生出问题了,屏幕上东西太多,随机位置重生容易冲突,所以决定单独提取一个函数出来判断是否有空位置,如下:

def isEmptyInArea(area, normalBeanss=[], snakeBeanss=[], snakes=[]):''' area是位置的列表'''for pos in area:if normalBeanss != []:for nbs in normalBeanss:for nb in nbs.beans:if nb.pos == pos:return Falseif snakeBeanss != []:for sbs in snakeBeanss:if sbs != []:for sb in sbs.beans:if sb.pos == pos:return Falseif snakes != []:for snake in snakes:for snakePos in snake.segments:if snakePos == pos:return Falsereturn True

输入参数area是位置的列表,normalBeanss是普通豆子的列表,snakeBeanss是蛇豆的列表,snakes是蛇的列表。这个函数思路很简单,就是拿area中的一个点一个点去判断是否跟其他几个列表中的位置冲突。
有了这个函数之后,一些代码就可以重写了,于是把蛇类的respawn函数改写如下,提取了一个generate函数出来,在初始化函数中也能用。

    def __init__(self, color, headColor, ctrlKeys):self.color = colorself.headColor = headColorself.ctrlKeys = ctrlKeys #按[上,下,左,右]的顺序self.segments = []self.generate()def generate(self):x = random.randrange(SNAKE_INIT_POS_MARGIN, SCREEN_WIDTH/GRID_SIZE-SNAKE_INIT_POS_MARGIN)y = random.randrange(SNAKE_INIT_POS_MARGIN, SCREEN_HEIGHT/GRID_SIZE-SNAKE_INIT_POS_MARGIN)self.direction = random.choice([-2,2,-1,1]) #([-2,2,-1,1]) # 方向[-2,2,-1,1]分别表示[上,下,左,右]self.headPos = [int(x*GRID_SIZE), int(y*GRID_SIZE)]self.segments.clear()self.segments.insert(0, list(self.headPos))for i in range(SNAKE_INIT_LEN-1):self.moveAndAdd()  def respawn(self, normalBeanss=[], snakeBeanss=[], snakes=[]):self.generate()while not isEmptyInArea(self.segments, normalBeanss, snakeBeanss, snakes):self.generate()

燃烧加速

最后来实现燃烧自己身体来加速的功能。给蛇类增加两个成员变量:

        self.vel = SNAKE_VEL_SLOWself.velCount = 0

修改之前的changeDirection函数为handleKey,增加了加速键的处理,速度分两档SNAKE_VEL_FAST和SNAKE_VEL_SLOW,并设置了加速的时间SNAKE_ACC_TIME:

    def handleKey(self, pressKey):directions = [-2,2,-1,1] #([-2,2,-1,1]) # 方向[-2,2,-1,1]分别表示[上,下,左,右]for direct, key in zip(directions, self.ctrlKeys[:4]):if key == pressKey and direct + self.direction != 0:self.direction = directif pressKey == self.ctrlKeys[4]  and self.vel != SNAKE_VEL_FAST: #按下了加速键if self.getLen() > SNAKE_INIT_LEN:self.pop()                 #燃烧自己self.vel = SNAKE_VEL_FAST  #来加速self.velCount = SNAKE_ACC_TIME

初始化时需要修改,首先需要增加加速按键:

    ctrlKeys1 = [ord('w'),ord('s'),ord('a'),ord('d'),ord('g')]ctrlKeys2 = [K_UP,K_DOWN,K_LEFT,K_RIGHT,ord('m')]

然后增加辅助变量:

    snake1VelCount = 1snake2VelCount = 1

主循环中涉及到蛇运动处理的地方都加上判断前提,如:

        if snake1VelCount > 1:if snake1.moveAndAdd(snake2): #撞到了另一条蛇身snake1Beans = SnakeBeans(snake1)snake1.respawn([normBeans],[snake1Beans,snake2Beans],[snake2])continue

最后增加辅助变量的处理,以实现加速功能:

        if snake1VelCount > 1:  if snake1.vel == SNAKE_VEL_FAST:snake1VelCount = 2else:snake1VelCount = 1else:snake1VelCount = snake1VelCount + 1

至此,就可以和我家小朋友再次一起愉快的玩耍了

Python贪吃蛇双人大战-升级版相关推荐

  1. Python贪吃蛇双人大战-魔法豆登场

    Python贪吃蛇双人大战-魔法豆登场 时隔两月之后,家里的小朋友再次对我之前改写的贪吃蛇游戏(过程可参考我之前写的 Python贪吃蛇双人大战 和 Python贪吃蛇双人大战-升级版,代码可以到此处 ...

  2. Python贪吃蛇小游戏_完整源码免费分享

    文章目录 Python 贪吃蛇小游戏 1. 导包 2. 配置初始化参数 3. 主函数及运行主体 4. 画食物的函数 5. 画贪吃蛇的函数 6. 画网格的函数(非必选,觉得多余的可以忽略此项) 7. 操 ...

  3. python小游戏代码大全-python贪吃蛇游戏代码

    本文实例为大家分享了python贪吃蛇游戏的具体代码,供大家参考,具体内容如下 贪吃蛇游戏截图: 首先安装pygame,可以使用pip安装pygame: pip install pygame 运行以下 ...

  4. python贪吃蛇源码_Python:游戏:贪吃蛇(附源码)

    Python:游戏:贪吃蛇(附源码) 发布时间:2018-09-05 09:59, 浏览次数:1295 , 标签: Python 贪吃蛇是个非常简单的游戏,适合练手. 首先分析一下这个游戏 1.蛇怎么 ...

  5. python代码大全-python贪吃蛇游戏代码

    本文实例为大家分享了python贪吃蛇游戏的具体代码,供大家参考,具体内容如下 贪吃蛇游戏截图: 首先安装pygame,可以使用pip安装pygame: pip install pygame 运行以下 ...

  6. c语言联机游戏,C/C++ 游戏 贪吃蛇双人对战版

    贪吃蛇双人对战版--C语言 最近写的,用于交最后一次结构化程序设计课的作业,闲暇之余传到网上,仅供参考,新手上路,请多指教. 话不多说,先附上下载链接.http://download.csdn.net ...

  7. 用javascript+jquery编写的小游戏-贪吃蛇(双人对战版)

    前言 这是我在多年前初学jquery, 并结合javascript, 编写的一个小游戏.那洋洋洒洒几千行的js代码时刻提醒着我"不忘初心!". 效果演示 代码 引入文件 由于用到了 ...

  8. Python贪吃蛇游戏

    Python贪吃蛇来啦! 源码奉上,直接拿走~ #!/usr/bin/env python # -*- coding: utf-8 -*- # author:Wangdali time:2021年1月 ...

  9. python小游戏代码大全-【程序源代码】python贪吃蛇小游戏

    关键字:python 游戏 贪吃蛇 正文 | 内容 在网络还不发达,没有平板电脑和手机的童年;电视机里的动画片和小游戏曾经陪伴我们度过了欢乐的时光.扫雷.贪吃蛇.俄罗斯方块.58坦克大战.超级玛丽.魂 ...

  10. python 贪吃蛇小游戏代码_10分钟再用Python编写贪吃蛇小游戏

    Python编写贪吃蛇 前不久我们公众号发布了一篇C++编写贪吃蛇小游戏的推文,反响空前.看来大家对这类简单易上手小游戏还是很喜爱的. 恰逢2018年IEEE Spectrum编程语言排行榜新鲜出炉, ...

最新文章

  1. Vivado和Quartus ii 中工程存档(Archive project)及打开
  2. 用javascript 禁止右键,禁止复制,禁止粘贴
  3. 两数之和 II - 输入有序数组
  4. easiest approach for improving writing skills for ielts
  5. C#复习笔记(3)--C#2:解决C#1的问题(可空值类型)
  6. 手机站的view.php,织梦网站文章内容页动态地址plus/view.php路径修改
  7. java伪代码生成器_JAVA单例模式的实现伪代码
  8. 按功能说明计算机中有哪些类型的寄存器?
  9. 3137102432_施少兵_实验2
  10. 综述|线结构光中心提取算法研究
  11. maven 构建spring boot + mysql 的基础项目
  12. gethostbyname
  13. ThinkPad T430i黑苹果Yosemite 10.10.3成功显卡驱动
  14. 计算机毕业设计ssm+vue基本微信小程序的购物商城系统
  15. 安装包及教程:仿真工具Multisim12.0 简体中文汉化版 安装包及详细安装教程(含安装包和汉化包百度云盘链接)
  16. 炫彩的按钮渐变动画——css3
  17. 英语发音规则---P字母
  18. 最难学的七大编程语言,VB 第一,Python垫底,看你学的排第几
  19. 乒乓球比赛赛程_这家律所再次摘得业余乒乓球赛事冠军,为何结缘乒乓?
  20. react-antd table树形数据默认展开行实现以及自定义图标实现及踩坑(defaultExpandedRowKeys,expandedRowKeys)

热门文章

  1. LeetCode 图解 | 237.删除链表中的节点
  2. 通过拉勾网分析数据分析职位现状
  3. 2513: 小勇学分数(公约数问题)
  4. 「 神器 」强大的系统清理工具
  5. A计划 骑士救公主迷宫
  6. python爬取虾米音乐_【个人】爬虫实践,利用xpath方式爬取数据之爬取虾米音乐排行榜...
  7. React Antd4 CRA / Next.js / Vite 按需加载组件的 CSS / Less
  8. java 证书错误_java – SSL证书错误:certificate_unknown
  9. php拆分excel,PHPExcel合并与拆分单元格的方法
  10. 计算机如何把表格分成两排,wps表格怎么拆分单元格,excel单元格拆分两列