遍历列表修改触发ValueError,子弹与障碍物碰撞逻辑修复
遍历列表删除元素触发ValueError,使用[:]切片仍无效的解决方法
问题场景
我需要实现子弹与障碍物碰撞时销毁两者的逻辑,尝试用[:]切片遍历列表避免修改原列表导致的遍历问题,但运行时在self.bullets.remove(bullet)处触发错误:
ValueError: list.remove(x): x not in list
最初的核心循环代码:
for bullet in self.bullets[:]: bullet.update(self.bullet_speed, self.bullets) for obstacle in game.obstacle_manager.obstacles[:]: if bullet.rect.colliderect(obstacle.rect): game.obstacle_manager.obstacles.remove(obstacle) self.bullets.remove(bullet) bullet_flag = True break if bullet_flag: break
完整的update函数代码:
def update(self, game): bullet_flag = False if game.player.type == WEAPON_TYPE: if self.bullet_step%5 == 0: self.bullets.append(Bullet(game.player)) self.bullet_step += 1 for bullet in self.bullets[:]: bullet.update(self.bullet_speed, self.bullets) for obstacle in game.obstacle_manager.obstacles[:]: if bullet.rect.colliderect(obstacle.rect): game.obstacle_manager.obstacles.remove(obstacle) self.bullets.remove(bullet) bullet_flag = True break if bullet_flag: break
问题原因
虽然使用self.bullets[:]生成了列表副本进行遍历,但代码中直接对原列表self.bullets执行remove操作,当子弹已被从原列表移除后,后续逻辑可能再次尝试删除该元素,或者切片副本与原列表状态不同步,最终触发"元素不在列表中"的错误。
解决方案
创建独立的辅助列表aux作为原列表的副本,遍历该辅助列表时仅修改副本,最后将原列表self.bullets替换为修改后的辅助列表,避免直接操作原列表引发的冲突。
最终完整代码:
def update(self, game): bullet_flag = False aux = self.bullets[:] # 创建原列表的辅助副本 if game.player.type == WEAPON_TYPE: if self.bullet_step%5 == 0: aux.append(Bullet(game.player)) # 新增子弹直接添加到辅助列表 self.bullet_step += 1 for bullet in aux: bullet.update(self.bullet_speed, self.bullets) for obstacle in game.obstacle_manager.obstacles[:]: if bullet.rect.colliderect(obstacle.rect): game.obstacle_manager.obstacles.remove(obstacle) aux.remove(bullet) bullet_flag = True break if bullet_flag: break self.bullets = aux # 将原列表替换为修改后的辅助列表
内容的提问来源于stack exchange,提问作者F. André
相关产品推荐
相关产品推荐

