敌方子弹撞墙触发ValueError: list.remove(x): x not in list错误求助
问题原因
敌方子弹会在单次update循环中被两次调用delete方法,导致第二次执行self.list.remove(self)时,子弹已经不在目标列表中,抛出ValueError: list.remove(x): x not in list:
- 第一步:执行
bullet.move()时,若子弹出界(y坐标超出±300),会调用delete()将子弹从bullets列表移除; - 第二步:后续的墙体碰撞检测中,该子弹对象仍存在(仅被隐藏),如果距离墙体小于15,会再次调用
delete(),此时子弹已不在列表,触发报错。
玩家子弹未出现该问题,是因为其飞行轨迹很少同时满足「出界」和「碰撞敌人」的条件,不会触发重复删除。
解决方案
给Bullet类增加存活状态标记,避免重复执行删除逻辑,同时在所有触发删除的环节先检查状态:
修改Bullet类
class Bullet(Turtle): def __init__(self, player, list): super().__init__() self.speed(0) self.ht() self.pu() self.color("white") self.goto(player.xcor(), player.ycor()) self.setheading(player.heading()) self.forward(40) self.list = list self.st() self.alive = True # 新增:标记子弹存活状态 def move(self): if not self.alive: # 已死亡的子弹跳过移动逻辑 return self.forward(15) if self.ycor()>300 or self.ycor()< -300: self.delete() def delete(self): if not self.alive: # 避免重复执行删除操作 return self.ht() self.alive = False self.list.remove(self)
修改敌方子弹的碰撞检测逻辑
在检测墙体碰撞前,先判断子弹是否存活:
# check for collision with a wall for wall in walls[:]: if bullet.alive and bullet.distance(wall)<15: wall.strike() bullet.delete()
可选优化:统一玩家子弹的处理逻辑
为了避免后续出现类似问题,玩家子弹的循环建议也使用切片复制列表,并增加存活状态检查:
# move bullets fired by the player for bullet in player.rounds[:]: # 用切片复制列表,避免列表修改干扰循环 if not bullet.alive: continue bullet.move() # check for collision with an enemy for alien in enemies: if bullet.distance(alien)<20: bullet.delete() alien.delete(enemies)
这样就能彻底解决重复删除导致的报错,同时让子弹的状态管理更严谨。
内容的提问来源于stack exchange,提问作者Yin
相关产品推荐
相关产品推荐

