鱼C论坛

 找回密码
 立即注册
查看: 1238|回复: 1

[学习笔记] 第37讲中的思考

[复制链接]
发表于 2020-3-5 02:15:24 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
       问题来源于python课后作业的  第037讲:类和对象:面向对象
还是再上一下图(文章最下方):

题中给的指示是:“当乌龟和鱼坐标重叠,乌龟吃掉鱼,乌龟体力增加20
这样我们就可以理解为,不论任何时候,只要乌龟和鱼碰面,就会发生鱼被吃掉这种情况

大家做过这个题的相信已经看过答案了,我就不再把全部的代码放上,只放部分答案了:
  1. turtle = Turtle()
  2. fish = []
  3. for i in range(10):
  4.     new_fish = Fish()
  5.     fish.append(new_fish)

  6. while True:
  7.     if not len(fish):
  8.         print("鱼儿都吃完了,游戏结束!")
  9.         break
  10.     if not turtle.power:
  11.         print("乌龟体力耗尽,挂掉了!")
  12.         break

  13.     pos = turtle.move()
  14.     # 在迭代器中删除列表元素是非常危险的,经常会出现意想不到的问题,因为迭代器是直接引用列表的数据进行引用
  15.     # 这里我们把列表拷贝给迭代器,然后对原列表进行删除操作就不会有问题了^_^
  16.     for each_fish in fish[:]:
  17.         if each_fish.move() == pos:
  18.             # 鱼儿被吃掉了
  19.             turtle.eat()
  20.             fish.remove(each_fish)
  21.             print("有一条鱼儿被吃掉了...")
复制代码



       首先,我要说的是,“# 在迭代器中删除列表元素是非常危险的,经常会出现意想不到的问题,因为迭代器是直接引用列表的数据进行引用,# 这里我们把列表拷贝给迭代器,然后对原列表进行删除操作就不会有问题了^_^”,这两句话是宝藏,还有这个处理的方法:for each_fish in fish[:]:,一定要拿小本本记下来。

       回到正题,我想说这段标准答案的代码实际上是有个漏洞在里面:

           我们先跟着代码的顺序理一下思路,生成实例对象turtle之后,用for循环生成10个Fish类的实例对象,存放在列表fish中。while循环中先判断了跳出条件,紧接着“ pos = turtle.move()”,小乌龟迈出了它的第一步,再进入for循环中,小鱼儿们也开始move,判断如果坐标重合,就被吃掉,这看起来没有什么问题。但是我突然就想到一个问题,万一小鱼儿落地成盒怎么办??小鱼儿和乌龟的生成位置都是随机的,十条小鱼儿一出生就和刚刚出生的小乌龟碰上也是有可能的!
          想到这里,我们再来看这段代码,实际上已经忽略了这个问题。小鱼儿落地金身,没有被直接吃掉,而是走了一步之后再被看看是不是还这么倒霉。所以,我认为严谨地来讲,确实应该考虑到小鱼儿“落地成盒”的问题(毕竟是吃鸡常有的事=_=)


         我的答案是在看标准答案之前写的,所以考虑进了这一点,也顺利的解决了,代码奉上:
  1. import random as r
  2. legal_x = [0, 10]
  3. legal_y = [0, 10]

  4. class Turtle():
  5.     def __init__(self):
  6.         self.hp = 100                                              #乌龟的生命值
  7.         self.x = r.randint(legal_x[0], legal_x[1])      #随机初始位置
  8.         self.y = r.randint(legal_x[0], legal_x[1])

  9.         
  10.     def move(self):
  11.         self.hp -= 1                                                #乌龟移动消耗体力
  12.         up_down = r.randint(-1, 1)
  13.         left_right = r.randint(-1, 1)
  14.         step = r.randint(1,2)
  15.         self.x += left_right * step                            #上下左右移动
  16.         self.y += up_down * step
  17.                                                    
  18.         if self.x < legal_x[0]:                                     #判断是否越界
  19.             self.x = -self.x
  20.         if self.x > legal_x[1]:
  21.             self.x = 2*legal_x[1] - self.x

  22.         if self.y < legal_y[0]:
  23.             self.y = -self.y
  24.         if self.y > legal_y[1]:
  25.             self.y = 2*legal_y[1] - self.y
  26. ##        print('我是小乌龟,我现在的位置是',(self.x, self.y))
  27. ##        print('='*80)
  28.         return (self.x, self.y)


  29.     def eat(self):                                                      #乌龟进食
  30.         self.hp += 20
  31.         
  32.         if self.hp >= 100:
  33.             self.hp = 100
  34.         print('&#10084;'*30)
  35.         print('hahaha,我吃到鱼了,我现在的体力是【%d】:'%self.hp)
  36.         return self.hp



  37. class Fish():
  38.     def __init__(self):
  39.         self.x = r.randint(legal_x[0], legal_x[1])      #随机初始位置
  40.         self.y = r.randint(legal_x[0], legal_x[1])


  41.     def move(self):
  42.         up_down = r.randint(-1, 1)
  43.         left_right = r.randint(-1, 1)
  44.       
  45.         self.x += left_right                                      #上下左右移动
  46.         self.y += up_down
  47.                                                    
  48.         if self.x < legal_x[0]:                                     #判断是否越界
  49.             self.x = -self.x
  50.         if self.x > legal_x[1]:
  51.             self.x = 2*legal_x[1] - self.x

  52.         if self.y < legal_y[0]:
  53.             self.y = -self.y
  54.         if self.y > legal_y[1]:
  55.             self.y = 2*legal_y[1] - self.y

  56. ##        print('我是小鱼儿,我现在的位置是',(self.x, self.y))
  57. ##        print('='*80)
  58.         return (self.x, self.y)
  59.    



  60. turtle = Turtle()                                                   #创造鱼和乌龟
  61. fishes = []
  62. for i in range(10):                                      
  63.     fish = Fish()
  64.    
  65.     fishes.append(fish)

  66. while True:
  67.     turtle_site = (turtle.x, turtle.y)                          #乌龟的位置
  68.     fishes_site = []                                                #鱼群的位置
  69.    
  70.     for each in fishes:                                             #更新鱼群位置
  71.         fishes_site.append((each.x, each.y))

  72.     times = fishes_site.count(turtle_site)              #搜集一次吃掉几条鱼
  73.     if times > 0:
  74.         for i in range(times):
  75.             kill = fishes_site.index(turtle_site)
  76.             fishes_site.pop(kill)                                   #鱼被吃掉后,更新对象列表和鱼群位置
  77.             fishes.pop(kill)

  78.             turtle.hp = turtle.eat()
  79.             print('现在还有【%d】条小鱼儿,我要把它们都吃光!'%len(fishes))
  80.    
  81.     turtle.move()
  82.     for each in fishes:
  83.         each.move()

  84.     if turtle.hp <= 0:
  85.         print('-'*80)
  86.         print('小乌龟被累死了!')
  87.         print('游戏结束!')
  88.         break

  89.     if len(fishes) == 0:
  90.         print('-'*80)
  91.         print('小乌龟把鱼都吃光了!')
  92.         print('游戏结束!')
  93.         break
复制代码


       在我的代码中,我用了两个列表,一个(fishes)存放Fish类的实例对象,另一个(fishes_site)存放每一个实例对象的x,y坐标组成的元组,当然他们的索引值也是一一对应,便于操作。我考虑到,万一小乌龟中大奖了,十条小鱼同时落地成盒,那岂不是美哉!所以先用了count()方法,判断一次能吃到几条鱼,然后以这个次数(times),当做for循环的条件。我的判断是否能吃掉鱼放在了小乌龟和小鱼儿move之前,所以如果落地成盒发生,则第一时间就能发现并且执行。但这样做同样我也用了比较笨的方法,用index()方法找到被吃的那条小鱼,然后用这个下标在两个列表中都把它删除。如果大佬们能更简单地解决,请在下面留言,我将非常欢迎!

      最后,我想问问大家,为什么我用自己的代码和答案跑了好多次,一直都是小乌龟被累死,这也太惨了,不知道你们是不是和我一样的情况。最后欢迎大家和我交流,如果哪位鱼油能指出我的代码的纰漏或者不足,我将万分感谢!!
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2020-11-13 16:58:00 | 显示全部楼层
我也是一直累死,都是不超过五次
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-5-13 15:41

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表