鱼C论坛

 找回密码
 立即注册
查看: 816|回复: 6

[已解决]老版零基础学习PYTHON 37讲最后一题代码报错

[复制链接]
发表于 2022-5-7 13:07:20 | 显示全部楼层 |阅读模式

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

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

x


我的代码如下:
import random

bound_x = [0, 10]
bound_y = [0, 10]

class Turtle():
    # 乌龟的属性:初始位置、体力初始值
    def __init__(self):
        self.x = random.randint(bound_x[0], bound_y[1])
        self.y = random.randint(bound_y[0], bound_y[1])
        self.healthy = 100
    def move(self):
        #随机4个移动方向
        direct = random.randint(1, 4)
        step = random.choice([1, 2])
        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[0]:
            self.x = bound_x[0] - (self.x - bound_x[0])
        elif self.x > bound_x[1]:
            self.x = bound_x[1] - (self.x - bound_x[1])
        if self.y < bound_y[0]:
            self.y = bound_y[0] - (self.y - bound_y[0])
        elif self.y > bound_y[1]:
            self.y = bound_y[1] - (self.y - bound_y[1])
        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[0], bound_y[1])
        self.y = random.randint(bound_y[0], bound_y[1])
    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[0]:
            self.x = bound_x[0] - (self.x - bound_x[0])
        elif self.x > bound_x[1]:
            self.x = bound_x[1] - (self.x - bound_x[1])
        if self.y < bound_y[0]:
            self.y = bound_y[0] - (self.y - bound_y[0])
        elif self.y > bound_y[1]:
            self.y = bound_y[1] - (self.y - bound_y[1])
        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[i].move(i) == eat:
            turtle.eat()
            fish_list.remove(fish_list[i])
            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[i].move(i) == eat:
IndexError: list index out of range

请问下导致出错的原因,以及需要如何修改。谢谢各位大神了
最佳答案
2022-5-7 13:22:04

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

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

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

bound_x = [0, 10]
bound_y = [0, 10]

class Turtle():
    # 乌龟的属性:初始位置、体力初始值
    def __init__(self):
        self.x = random.randint(bound_x[0], bound_y[1])
        self.y = random.randint(bound_y[0], bound_y[1])
        self.healthy = 100
    def move(self):
        #随机4个移动方向
        direct = random.randint(1, 4)
        step = random.choice([1, 2])
        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[0]:
            self.x = bound_x[0] - (self.x - bound_x[0])
        elif self.x > bound_x[1]:
            self.x = bound_x[1] - (self.x - bound_x[1])
        if self.y < bound_y[0]:
            self.y = bound_y[0] - (self.y - bound_y[0])
        elif self.y > bound_y[1]:
            self.y = bound_y[1] - (self.y - bound_y[1])
        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[0], bound_y[1])
        self.y = random.randint(bound_y[0], bound_y[1])
    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[0]:
            self.x = bound_x[0] - (self.x - bound_x[0])
        elif self.x > bound_x[1]:
            self.x = bound_x[1] - (self.x - bound_x[1])
        if self.y < bound_y[0]:
            self.y = bound_y[0] - (self.y - bound_y[0])
        elif self.y > bound_y[1]:
            self.y = bound_y[1] - (self.y - bound_y[1])
        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[i].move(i) == eat:
            turtle.eat()
            temp.append(fish_list[i])                    # -------------------------------------------------------------------------修改了这里代码
            print('小乌龟吃了{}号小鱼,恢复到了{}生命'.format(i, turtle.healthy))

    for i in temp:                     # -------------------------------------------------------------------------增加了这里代码
        fish_list.remove(i)
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2022-5-7 13:22:04 | 显示全部楼层    本楼为最佳答案   

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

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

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

bound_x = [0, 10]
bound_y = [0, 10]

class Turtle():
    # 乌龟的属性:初始位置、体力初始值
    def __init__(self):
        self.x = random.randint(bound_x[0], bound_y[1])
        self.y = random.randint(bound_y[0], bound_y[1])
        self.healthy = 100
    def move(self):
        #随机4个移动方向
        direct = random.randint(1, 4)
        step = random.choice([1, 2])
        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[0]:
            self.x = bound_x[0] - (self.x - bound_x[0])
        elif self.x > bound_x[1]:
            self.x = bound_x[1] - (self.x - bound_x[1])
        if self.y < bound_y[0]:
            self.y = bound_y[0] - (self.y - bound_y[0])
        elif self.y > bound_y[1]:
            self.y = bound_y[1] - (self.y - bound_y[1])
        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[0], bound_y[1])
        self.y = random.randint(bound_y[0], bound_y[1])
    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[0]:
            self.x = bound_x[0] - (self.x - bound_x[0])
        elif self.x > bound_x[1]:
            self.x = bound_x[1] - (self.x - bound_x[1])
        if self.y < bound_y[0]:
            self.y = bound_y[0] - (self.y - bound_y[0])
        elif self.y > bound_y[1]:
            self.y = bound_y[1] - (self.y - bound_y[1])
        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[i].move(i) == eat:
            turtle.eat()
            temp.append(fish_list[i])                    # -------------------------------------------------------------------------修改了这里代码
            print('小乌龟吃了{}号小鱼,恢复到了{}生命'.format(i, turtle.healthy))

    for i in temp:                     # -------------------------------------------------------------------------增加了这里代码
        fish_list.remove(i)
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-5-7 13:24:57 | 显示全部楼层
for i in range(len(fish_list[:])):       这里的 len(fish_list[:]) 计算好就固定了,

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

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

bound_x = [0, 10]
bound_y = [0, 10]

class Turtle():
    # 乌龟的属性:初始位置、体力初始值
    def __init__(self):
        self.x = random.randint(bound_x[0], bound_y[1])
        self.y = random.randint(bound_y[0], bound_y[1])
        self.healthy = 100
    def move(self):
        #随机4个移动方向
        direct = random.randint(1, 4)
        step = random.choice([1, 2])
        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[0]:
            self.x = bound_x[0] - (self.x - bound_x[0])
        elif self.x > bound_x[1]:
            self.x = bound_x[1] - (self.x - bound_x[1])
        if self.y < bound_y[0]:
            self.y = bound_y[0] - (self.y - bound_y[0])
        elif self.y > bound_y[1]:
            self.y = bound_y[1] - (self.y - bound_y[1])
        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[0], bound_y[1])
        self.y = random.randint(bound_y[0], bound_y[1])
    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[0]:
            self.x = bound_x[0] - (self.x - bound_x[0])
        elif self.x > bound_x[1]:
            self.x = bound_x[1] - (self.x - bound_x[1])
        if self.y < bound_y[0]:
            self.y = bound_y[0] - (self.y - bound_y[0])
        elif self.y > bound_y[1]:
            self.y = bound_y[1] - (self.y - bound_y[1])
        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))
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

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

谢谢版主大大
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2022-5-7 13:43:07 | 显示全部楼层
isdkz 发表于 2022-5-7 13:24
for i in range(len(fish_list[:])):       这里的 len(fish_list[:]) 计算好就固定了,

如果有小鱼被吃 ...

谢谢,我主要是想把吃掉的是第几号小鱼统计出来,直接迭代列表的话应该怎么样才能达到这个效果呢??
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

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

可以用 enumerate
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2022-5-7 14:01:11 | 显示全部楼层
isdkz 发表于 2022-5-7 13:51
可以用 enumerate

多谢指教,实在是太感谢了
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

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

本版积分规则

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

GMT+8, 2024-11-18 10:30

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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