贪吃蛇“大作战”(三)

例程实操与分析



  在之前的两篇博客中分别通过面向过程和面向对象的编程思想分析介绍了来自sunny开始学坏的贪吃蛇例程,今天的博客将通过运行这个贪吃蛇例程来了解各行代码的作用,同时通过“找茬”的方式深入分析了解贪吃蛇的运行机制并改善这个例程。

  下面是这个贪吃蛇例程的代码:

 1 import os,random
 2 sw=[[5,5]]
 3 #lc=[[0,0],[0,1],[0,2],[0,3],[0,4],[0,5],[0,6]]
 4 lc=[[5,i] for i in range(10)]
 5 s=‘‘
 6 for x in range(500):
 7   w=len(lc)-1
 8   li = [([‘○‘] * 20) for i in range(20)]
 9   a=input(‘请输入wasd控制:‘)
10   if a==‘‘:
11      a=s
12   if a==‘w‘:
13       lc.append([lc[w][0]-1,lc[w][1]])
14       del lc[0]
15       s=‘w‘
16   if a==‘s‘:
17       lc.append([lc[w][0]+1,lc[w][1]])
18       del lc[0]
19       s=‘s‘
20   if a==‘a‘:
21      lc.append([lc[w][0],lc[w][1]-1])
22      del lc[0]
23      s=‘a‘
24   if a==‘d‘:
25      lc.append([lc[w][0],lc[w][1]+1])
26      del lc[0]
27      s=‘d‘
28   if lc[w] in sw:
29         lc.insert(0,[lc[0][0],lc[0][1]-1])
30         del sw[0]
31         sw.append([random.randint(0,19),random.randint(0,19)])
32   for i in lc:li[i[0]][i[1]]=‘●‘
33   for w in sw:li[w[0]][w[1]]=‘◆‘
34   os.system(‘clear‘)
35   for i in li:print(‘‘.join(i))

  然后,我们来运行这个例程代码,看看运行结果:

  

  根据这个结果可知:例程代码在运行到第九行后停止运行,并提示我们输入“w”"s""a""d"四个字符中的一个,接下来的条件选择结构会判断我们输入的内容执行不同的语句;我们可以不输入内容执行或输入这四个字符以外的内容执行试试:

  

  从结果可以看到,输入"w""s""a""d"四个字符之外的字符也可以开启游戏,这对一个正常的游戏逻辑来说显然是个漏洞。回到代码看看,if语句与最后的四行代码是在同一个层级的,也就是if执行完后肯定会执行最后四行语句(最后四行语句的作用就是在命令行中渲染出蛇、食物和草地三个对象),这就造成了无论输入什么指令都会“开始游戏”(渲染出地图);我们可以通过修改行号为10和11的代码来解决这个漏洞(bug)。修改后的代码如下(增加了一个else语句):

import os,random
sw=[[5,5]]
#lc=[[0,0],[0,1],[0,2],[0,3],[0,4],[0,5],[0,6]]
lc=[[5,i] for i in range(10)]
s=‘‘
for x in range(500):
  w=len(lc)-1
  li = [([‘○‘] * 20) for i in range(20)]
  a=input(‘请输入wasd控制:‘)
#  if a==‘‘:
#     a=s
  if a==‘w‘:
      lc.append([lc[w][0]-1,lc[w][1]])
      del lc[0]
      s=‘w‘
  elif a==‘s‘:
      lc.append([lc[w][0]+1,lc[w][1]])
      del lc[0]
      s=‘s‘
  elif a==‘a‘:
     lc.append([lc[w][0],lc[w][1]-1])
     del lc[0]
     s=‘a‘
  elif a==‘d‘:
     lc.append([lc[w][0],lc[w][1]+1])
     del lc[0]
     s=‘d‘
  else:
    print("输入指令错误!")
    exit()
  if lc[w] in sw:
        lc.insert(0,[lc[0][0],lc[0][1]-1])
        del sw[0]
        sw.append([random.randint(0,19),random.randint(0,19)])
  for i in lc:li[i[0]][i[1]]=‘●‘
  for w in sw:li[w[0]][w[1]]=‘◆‘
  os.system(‘clear‘)
  for i in li:print(‘‘.join(i))

  这样处理后,就可以控制玩家输入的指令,消除错误指令带来的Bug,,引导玩家正确地享受游戏。

  

  通过上面的游戏效果可以看出,在游戏的初始,食物“◆”就在贪吃蛇的腹内了,这样显然不符合正常逻辑,我们要避免这种Bug的出现,即禁止食物出现在贪吃蛇的身体中。在之后食物的随机生成时,同样禁止这种情况出现。可以通过差集的方式简单解决这个Bug。

import os,random
sw=[[5,5]]
#lc=[[0,0],[0,1],[0,2],[0,3],[0,4],[0,5],[0,6]]
lc=[[5,i] for i in range(10)]
s=‘‘
grass = [[x,y] for x in range(20) for y in range(20)]  #将地图坐标化,以坐标点组合的形式表示地图
field_sw = [var for var in grass if var not in lc]     #以差集的方式得到食物随机出现的范围(滤除贪吃蛇的坐标集)

if sw[0] in lc:                            #if语句检测食物是否在贪吃蛇内部
  del sw[0]                                #删除原有坐标
  sw.append(random.choice(field_sw))       #在贪吃蛇身体之外随机生成一个食物出现坐标
  print("Have Changed!")                   #测试用 

for x in range(500):
  w=len(lc)-1
  li = [([‘○‘] * 20) for i in range(20)]
  a=input(‘请输入wasd控制:‘)
#  if a==‘‘:
#     a=s
  if a==‘w‘:
      lc.append([lc[w][0]-1,lc[w][1]])
      del lc[0]
      s=‘w‘
  elif a==‘s‘:
      lc.append([lc[w][0]+1,lc[w][1]])
      del lc[0]
      s=‘s‘
  elif a==‘a‘:
     lc.append([lc[w][0],lc[w][1]-1])
     del lc[0]
     s=‘a‘
  elif a==‘d‘:
     lc.append([lc[w][0],lc[w][1]+1])
     del lc[0]
     s=‘d‘
  else:
    print("输入指令错误!")
    exit()
  if lc[w] in sw:
        lc.insert(0,[lc[0][0],lc[0][1]-1])

        field_sw = [var for var in grass if var not in lc]  #以差集滤除贪吃蛇的坐标集
        del sw[0]
        sw.append(random.choice(field_sw))                  #在不包含贪吃蛇的坐标集中随机生成食物坐标

  for i in lc:li[i[0]][i[1]]=‘●‘
  for w in sw:li[w[0]][w[1]]=‘◆‘
  os.system(‘clear‘)
  for i in li:print(‘‘.join(i))

  再看看运行结果:
  

  这样看着是不是舒服多了,游戏也变得合理了。

  好了,一个通过命令行简单实现的贪吃蛇游戏就是这样。上面初始化的贪吃蛇太长了,我们修改下参数再运行看看,顺便让食物离贪吃蛇近一点。

import os,random
sw=[[5,7]]
#lc=[[0,0],[0,1],[0,2],[0,3],[0,4],[0,5],[0,6]]
lc=[[5,i] for i in range(5)]
s=‘‘

  看看效果

  

  

  是不是已经很有贪吃蛇的感觉了,只是用命令行来实现这个游戏终究太过“机械”,每次贪吃蛇的前进都需要我们敲入指令然后整个地图重新“渲染”一次,这样感觉会很不“友好”。之后的博客会通过面向对象的方式来同样实现一个贪吃蛇游戏,并调用另一些相关的模块,让游戏界面更美观,人机交互方式更“友好”

  

原文地址:https://www.cnblogs.com/3fman/p/9210092.html

时间: 2024-10-06 14:33:48

贪吃蛇“大作战”(三)的相关文章

贪吃蛇大作战的一点感悟

春节过罢,闲来无事,玩了两日贪吃蛇大作战,之前玩过球球大作战,感觉球球大作战玩法比较多,也比较难入门.而贪吃蛇大作战就简单多了,就两个原则:1不断地吃食物,让自己长大.2尽量避免撞到别人身上,以致于死亡.抱着这样的原则,我就开始了自己的贪吃之路. 刚开始的时候是小心翼翼地吃游戏自带的豆豆,也不敢去击杀别人,还经常撞到别人身上,所以更加小心地玩,自己长大了才敢去围追堵截别人,这样不知不觉居然就能玩到9000多长度了.接着再玩下去就有点心急了,一方面是有前边的经验,感觉也不太难嘛,另一方面想更快地打

贪吃蛇大作战canvas实现(手机触屏操作)--地图逻辑

//html部分 <!DOCTYPE html><html><head lang="en"> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no"> <title>贪吃蛇大作战</titl

贪吃蛇“大作战”(四)

创建真正的游戏 之前演示的贪吃蛇游戏是以python命令行的形式模拟实现的,今天博客的主题就是是创建一个真正的贪吃蛇游戏,其摆脱了命令行的限制,界面更加美观,人机交互更加方便,可以让玩家有更好的游戏体验. 那么,要如何将贪吃蛇游戏做的更好.一个真正的游戏是通过图形用户界面GUI(Graphical User Interface)来展示的.在python中,要做一个GUI有多种选择,简单的就是easygui模块,进阶版的就是tkinter模块.wxPython模块等:当然,还有些模块虽然不是专门做

贪吃蛇“大作战”(五)

创建真正的游戏(续) 在上一篇博客介绍了pygame模块的安装,并开始通过pygame模块来创建贪吃蛇游戏.在上篇博客中我创建了一个窗体,贪吃蛇游戏将在窗体中运行.同时简单编写了一个退出窗体的事件应对机制,今天的博客将深入学习pygame模块,并一步一步"勾勒"出完整的贪吃蛇游戏. 上篇博客贪吃蛇代码编写到创建贪吃蛇游戏的窗体: import pygame #导入pygame模块 from pygame.locals import * #导入pygame模块中常用的函数和常量,如表示全

贪吃蛇“大作战”(二)

从对象出发看贪吃蛇 在上一篇博客中,我通过逐行分析代码对贪吃蛇的运行机制做了一个简要的介绍:逐行分析后可以看出这个贪吃蛇例程的编写范式更突出面向过程:该例程先是预设食物和贪吃蛇的位置参数,然后通过选择逻辑判断外部命令的值,根据不同的值做出不同的动作,最后在地图上将之前的动作"渲染",达到贪吃蛇"前进"的效果:如此下来,一步一步地根据"看得到的逻辑"实现了贪吃蛇的运行机制. 现在,我从面向对象的编程思维来对这个贪吃蛇运行机制做一个分析.从下面这幅图

java小游戏贪吃蛇大作战:来一起回顾童年回忆!

Java小项目之贪吃蛇 跪求关注,祝关注我的人都:身体健康,财源广进,福如东海,寿比南山,早上贵子,从不掉发! 贪吃蛇,绝对是很多朋友的童年记忆.几乎没有人会说没玩过这款小游戏,因为不管在小灵通手机,直板手机,还是半智能手机,甚至是现在的5G手机,都能看见这款游戏的身影.虽然游戏一直在进化,画面,风格,操作方式越来越精细,但是游戏本质的玩法是没变的,例如蛇不断变大,碰到墙壁会死亡等设定.这篇文章来分享java小游戏贪吃蛇:部分代码展示:这个贪吃蛇小游戏,玩法和操控,都是比较完善的,大家感兴趣的可

贪吃蛇大作战游戏攻略

1.不去人群密集的地方 2.长大之后想要啥就有啥 3.跑马圈地,长大之后,要让身体占据更大的空间 4.不抢食物,头只在身体内运动,只有当外部空间比较大时再进行领土扩张 5.不抢食物,而是要围住食物之后慢慢吃. 6.对于进入身体内部的蛇,要压缩之,不停地围绕它转圈,每转一圈就压缩一点空间. 7.勿贪小利,要从地形上取胜,而不要注重一星半点的食物.要鲸吞小蛇,而不要与它们正面交锋 8.不行险,不侥幸,稳,慢.活着是第一要务,活着是一切之根本. 9.慎终如始,则无败事.

Java课程设计---贪吃蛇大作战

目录 一.团队课程设计博客链接 二.个人负责模块和任务说明 三.自己的代码提交记录截图 四.自己负责模块或任务详细说明 五.课程设计感想 一.团队课程设计博客链接 二.个人负责模块和任务说明 1.负责实现闯关模式 2.负责实现挑战模式 3.串联GUI与信息代码 4.实现排行榜功能 三.自己的代码提交记录截图 四.自己负责模块或任务详细说明 这是挑战模式的时间线程 this.thread = new Thread(() -> { while (start) { if (count == 0) {

Expo大作战(三十一)--expo sdk api之Payments(expo中的支付),翻译这篇文章傻逼了,完全不符合国内用户,我只负责翻译大家可以略过!

简要:本系列文章讲会对expo进行全面的介绍,本人从2017年6月份接触expo以来,对expo的研究断断续续,一路走来将近10个月,废话不多说,接下来你看到内容,讲全部来与官网 我猜去全部机翻+个人修改补充+demo测试的形式,对expo进行一次大补血!欢迎加入expo兴趣学习交流群:597732981 [之前我写过一些列关于expo和rn入门配置的东i西,大家可以点击这里查看:从零学习rn开发] 相关文章: Expo大作战(一)--什么是expo,如何安装expo clinet和xde,xd