2012-04-11 1 views
0

Итак, у меня есть небольшая игра, написанная на питоне, если вы видели мой предыдущий вопрос, вы знаете, что это клоун «космических захватчиков».random "ValueError: list.remove (x): x not in list" error in pygame

Так почти все работает гладко прямо сейчас, за исключением случайной ошибки, возникающей из-за времени. Это совершенно случайно, это может произойти после того, как были выпущены некоторые пули, или это может вообще не произойти.

У меня есть этот код:

for bullet in bullets: 
     bullet.attack() 
     if bullet.posy<=-20: 
      bullet_draw=False 
     if bullet_draw==True: 
      bullet.draw() 
     for enemy in enemies: 
      if bullet.sprite.rect.colliderect(enemy.sprite.rect): 
       enemy.health-=1 
       bullets.remove(bullet) 
       bullet_draw=False 
      else: 
       bullet_draw=True 

Иногда он дает мне следующую ошибку.

Traceback (most recent call last): 
    File "\Programming\space invaders\space.py", line 280, in <module> 
    bullets.remove(bullet) 
ValueError: list.remove(x): x not in list 

Обратите внимание, что эта ошибка абсолютно случайна; даже если это не так, я не могу проследить его происхождение. Любая помощь в том, как его устранить?

+1

В общем, поймать ошибку, а затем использовать посмертный отладчик ('import pdb; pdb.post_mortem()') - это хороший способ разобраться. Во время разработки у меня обычно есть пункт try-except try-except вокруг точки входа моей программы, так что я могу сразу отлаживать даже непредвиденные проблемы. –

ответ

3

Ваша пуля поражает нескольких врагов. Вам необходимо break из цикла enemies.

+0

Извлечение элементов из списка, который выполняет итерация OP, также вызовет проблемы. – DSM

+0

@ DSM: Верно, но с этим легко справиться. 'для пули в пули [:]:' –

+0

Готово! Кстати, 'continue' идет сразу после' bullet_draw = True' с отступом в '' bullet in bullets'? – mechanicarts

4

Попробуйте изменить его на следующее:

for bullet in bullets[:]: # this is changed, iterating over a copy 
     bullet.attack() 
     if bullet.posy<=-20: 
      bullet_draw=False 
     if bullet_draw==True: 
      bullet.draw() 
     for enemy in enemies: 
      if bullet.sprite.rect.colliderect(enemy.sprite.rect): 
       enemy.health-=1 
       bullets.remove(bullet) 
       bullet_draw=False 
       break   # this is added, prevents multiple removes 
      else: 
       bullet_draw=True 

Обратите внимание на два замечания, которые я добавил, что показывают изменения, то break необходимо потому, что одна пуля может поражать несколько врагов, которые могли бы привести bullets.remove(bullet) называться дважды, что вызывает отслеживание, которое вы видите.

Первое изменение необходимо, так как удаление элементов из списка в процессе итерации может привести к неожиданным последствиям, поскольку в ходе итерации вы пропустите некоторые элементы. Следующий код иллюстрирует это:

>>> data = range(10) 
>>> for x in data: 
...  data.remove(x) 
... 
>>> data 
[1, 3, 5, 7, 9] 

Хотя код выглядит, как он должен удалить все элементы из списка, он только удаляет все остальные, поскольку индексы список меняются во время итерации.

Смежные вопросы