kerln888 发表于 2022-5-7 13:07:20

老版零基础学习PYTHON 37讲最后一题代码报错



我的代码如下:
import random

bound_x =
bound_y =

class Turtle():
    # 乌龟的属性:初始位置、体力初始值
    def __init__(self):
      self.x = random.randint(bound_x, bound_y)
      self.y = random.randint(bound_y, bound_y)
      self.healthy = 100
    def move(self):
      #随机4个移动方向
      direct = random.randint(1, 4)
      step = random.choice()
      if direct == 1:
            self.x += step
            print('小乌龟向上移动了{}步'.format(step))
      elif direct == 2:
            self.y += step
            print('小乌龟向右移动了{}步'.format(step))
      elif direct == 2:
            self.x -= step
            print('小乌龟向下移动了{}步'.format(step))
      else:
            self.y -= step
            print('小乌龟向左移动了{}步'.format(step))
      #超越边界往相反方向返回
      if self.x < bound_x:
            self.x = bound_x - (self.x - bound_x)
      elif self.x > bound_x:
            self.x = bound_x - (self.x - bound_x)
      if self.y < bound_y:
            self.y = bound_y - (self.y - bound_y)
      elif self.y > bound_y:
            self.y = bound_y - (self.y - bound_y)
      self.healthy -= 1
      print('小乌龟来到了{}这个位置,还剩{}生命值'.format((self.x, self.y), self.healthy))
      return (self.x, self.y)
    def eat(self):
      self.healthy += 20
      if self.healthy > 100:
            self.healthy = 100

class Fish():
    #鱼的属性:初始位置
    def __init__(self):
      self.x = random.randint(bound_x, bound_y)
      self.y = random.randint(bound_y, bound_y)
    def move(self, fish_num):
      direct = random.randint(1, 4)
      step = 1
      if direct == 1:
            self.x += step
            print('{}号小鱼向上移动了{}步'.format(fish_num, step))
      elif direct == 2:
            self.y += step
            print('{}号小鱼向右移动了{}步'.format(fish_num, step))
      elif direct == 2:
            self.x -= step
            print('{}号小鱼向下移动了{}步'.format(fish_num, step))
      else:
            self.y -= step
            print('{}号小鱼向左移动了{}步'.format(fish_num, step))
      if self.x < bound_x:
            self.x = bound_x - (self.x - bound_x)
      elif self.x > bound_x:
            self.x = bound_x - (self.x - bound_x)
      if self.y < bound_y:
            self.y = bound_y - (self.y - bound_y)
      elif self.y > bound_y:
            self.y = bound_y - (self.y - bound_y)
      print('{}号小鱼到了{}这个位置'.format(fish_num, (self.x, self.y)))
      return (self.x, self.y)

turtle = Turtle()
fish_list = []
for i in range(12):
    fish_list.append(Fish())

while True:
    if turtle.healthy == 0:
      print('小乌龟生命值耗尽了,游戏结束')
      break
    elif len(fish_list) == 0:
      print('小鱼吃完了!游戏结束')

    eat = turtle.move()
    for i in range(len(fish_list[:])):
      if fish_list.move(i) == eat:
            turtle.eat()
            fish_list.remove(fish_list)
            print('小乌龟吃了{}号小鱼,恢复到了{}生命'.format(i, turtle.healthy))

报错提示:
Traceback (most recent call last):
File "C:\Users\WL-GL-001-01\PycharmProjects\pythonProject\main.py", line 88, in <module>
    if fish_list.move(i) == eat:
IndexError: list index out of range

请问下导致出错的原因,以及需要如何修改。谢谢各位大神了

Twilight6 发表于 2022-5-7 13:22:04


因为你的 for 循环过程中,第一次执行到 for 循环就将 range 容器生成了,即在此次中途的 for 循环中不会再执行 range(len(fish_list[ i]))

而因为你在 for 循环中移除了 fish_list 原小鱼的列表,导致索引下标很可能会大于原 fish_list 的长度(因为你循环中移除了小鱼,原列表索引变小)

你可以将要移除的小鱼先临时存放在另一个列表,然后再依次移除,参考代码:
import random

bound_x =
bound_y =

class Turtle():
    # 乌龟的属性:初始位置、体力初始值
    def __init__(self):
      self.x = random.randint(bound_x, bound_y)
      self.y = random.randint(bound_y, bound_y)
      self.healthy = 100
    def move(self):
      #随机4个移动方向
      direct = random.randint(1, 4)
      step = random.choice()
      if direct == 1:
            self.x += step
            print('小乌龟向上移动了{}步'.format(step))
      elif direct == 2:
            self.y += step
            print('小乌龟向右移动了{}步'.format(step))
      elif direct == 2:
            self.x -= step
            print('小乌龟向下移动了{}步'.format(step))
      else:
            self.y -= step
            print('小乌龟向左移动了{}步'.format(step))
      #超越边界往相反方向返回
      if self.x < bound_x:
            self.x = bound_x - (self.x - bound_x)
      elif self.x > bound_x:
            self.x = bound_x - (self.x - bound_x)
      if self.y < bound_y:
            self.y = bound_y - (self.y - bound_y)
      elif self.y > bound_y:
            self.y = bound_y - (self.y - bound_y)
      self.healthy -= 1
      print('小乌龟来到了{}这个位置,还剩{}生命值'.format((self.x, self.y), self.healthy))
      return (self.x, self.y)
    def eat(self):
      self.healthy += 20
      if self.healthy > 100:
            self.healthy = 100

class Fish():
    #鱼的属性:初始位置
    def __init__(self):
      self.x = random.randint(bound_x, bound_y)
      self.y = random.randint(bound_y, bound_y)
    def move(self, fish_num):
      direct = random.randint(1, 4)
      step = 1
      if direct == 1:
            self.x += step
            print('{}号小鱼向上移动了{}步'.format(fish_num, step))
      elif direct == 2:
            self.y += step
            print('{}号小鱼向右移动了{}步'.format(fish_num, step))
      elif direct == 2:
            self.x -= step
            print('{}号小鱼向下移动了{}步'.format(fish_num, step))
      else:
            self.y -= step
            print('{}号小鱼向左移动了{}步'.format(fish_num, step))
      if self.x < bound_x:
            self.x = bound_x - (self.x - bound_x)
      elif self.x > bound_x:
            self.x = bound_x - (self.x - bound_x)
      if self.y < bound_y:
            self.y = bound_y - (self.y - bound_y)
      elif self.y > bound_y:
            self.y = bound_y - (self.y - bound_y)
      print('{}号小鱼到了{}这个位置'.format(fish_num, (self.x, self.y)))
      return (self.x, self.y)

turtle = Turtle()
fish_list = []
for i in range(12):
    fish_list.append(Fish())

while True:
    if turtle.healthy == 0:
      print('小乌龟生命值耗尽了,游戏结束')
      break
    elif len(fish_list) == 0:
      print('小鱼吃完了!游戏结束')
      break
    eat = turtle.move()
    temp = []                  # -------------------------------------------------------------------------增加了这里代码
    for i in range(len(fish_list[:])):
      if fish_list.move(i) == eat:
            turtle.eat()
            temp.append(fish_list)                  # -------------------------------------------------------------------------修改了这里代码
            print('小乌龟吃了{}号小鱼,恢复到了{}生命'.format(i, turtle.healthy))

    for i in temp:                     # -------------------------------------------------------------------------增加了这里代码
      fish_list.remove(i)

isdkz 发表于 2022-5-7 13:24:57

for i in range(len(fish_list[:])):       这里的 len(fish_list[:]) 计算好就固定了,

如果有小鱼被吃掉了,len(fish_list[:]) 也还是没有小鱼被吃掉前的数,

所以就超出索引了,这里直接迭代列表就好

import random

bound_x =
bound_y =

class Turtle():
    # 乌龟的属性:初始位置、体力初始值
    def __init__(self):
      self.x = random.randint(bound_x, bound_y)
      self.y = random.randint(bound_y, bound_y)
      self.healthy = 100
    def move(self):
      #随机4个移动方向
      direct = random.randint(1, 4)
      step = random.choice()
      if direct == 1:
            self.x += step
            print('小乌龟向上移动了{}步'.format(step))
      elif direct == 2:
            self.y += step
            print('小乌龟向右移动了{}步'.format(step))
      elif direct == 2:
            self.x -= step
            print('小乌龟向下移动了{}步'.format(step))
      else:
            self.y -= step
            print('小乌龟向左移动了{}步'.format(step))
      #超越边界往相反方向返回
      if self.x < bound_x:
            self.x = bound_x - (self.x - bound_x)
      elif self.x > bound_x:
            self.x = bound_x - (self.x - bound_x)
      if self.y < bound_y:
            self.y = bound_y - (self.y - bound_y)
      elif self.y > bound_y:
            self.y = bound_y - (self.y - bound_y)
      self.healthy -= 1
      print('小乌龟来到了{}这个位置,还剩{}生命值'.format((self.x, self.y), self.healthy))
      return (self.x, self.y)
    def eat(self):
      self.healthy += 20
      if self.healthy > 100:
            self.healthy = 100

class Fish():
    #鱼的属性:初始位置
    def __init__(self):
      self.x = random.randint(bound_x, bound_y)
      self.y = random.randint(bound_y, bound_y)
    def move(self, fish_num):
      direct = random.randint(1, 4)
      step = 1
      if direct == 1:
            self.x += step
            print('{}号小鱼向上移动了{}步'.format(fish_num, step))
      elif direct == 2:
            self.y += step
            print('{}号小鱼向右移动了{}步'.format(fish_num, step))
      elif direct == 2:
            self.x -= step
            print('{}号小鱼向下移动了{}步'.format(fish_num, step))
      else:
            self.y -= step
            print('{}号小鱼向左移动了{}步'.format(fish_num, step))
      if self.x < bound_x:
            self.x = bound_x - (self.x - bound_x)
      elif self.x > bound_x:
            self.x = bound_x - (self.x - bound_x)
      if self.y < bound_y:
            self.y = bound_y - (self.y - bound_y)
      elif self.y > bound_y:
            self.y = bound_y - (self.y - bound_y)
      print('{}号小鱼到了{}这个位置'.format(fish_num, (self.x, self.y)))
      return (self.x, self.y)

turtle = Turtle()
fish_list = []
for i in range(12):
    fish_list.append(Fish())

while True:
    if turtle.healthy == 0:
      print('小乌龟生命值耗尽了,游戏结束')
      break
    elif len(fish_list) == 0:
      print('小鱼吃完了!游戏结束')
      break                                           # 改了这里,小鱼吃完了也要 break

    eat = turtle.move()
    for fish in fish_list:                     # 改了这里
      if fish.move(i) == eat:                     # 改了这里
            turtle.eat()
            fish_list.remove(fish)                     # 改了这里
            print('小乌龟吃了{}号小鱼,恢复到了{}生命'.format(i, turtle.healthy))

kerln888 发表于 2022-5-7 13:40:19

Twilight6 发表于 2022-5-7 13:22
因为你的 for 循环过程中,第一次执行到 for 循环就将 range 容器生成了,即在此次中途的 for 循环中不会 ...

谢谢版主大大

kerln888 发表于 2022-5-7 13:43:07

isdkz 发表于 2022-5-7 13:24
for i in range(len(fish_list[:])):       这里的 len(fish_list[:]) 计算好就固定了,

如果有小鱼被吃 ...

谢谢,我主要是想把吃掉的是第几号小鱼统计出来,直接迭代列表的话应该怎么样才能达到这个效果呢??

isdkz 发表于 2022-5-7 13:51:38

kerln888 发表于 2022-5-7 13:43
谢谢,我主要是想把吃掉的是第几号小鱼统计出来,直接迭代列表的话应该怎么样才能达到这个效果呢??

可以用 enumerate

kerln888 发表于 2022-5-7 14:01:11

isdkz 发表于 2022-5-7 13:51
可以用 enumerate

多谢指教,实在是太感谢了
页: [1]
查看完整版本: 老版零基础学习PYTHON 37讲最后一题代码报错