2012-04-11 3 views
0

So habe ich ein kleines Spiel in Python geschrieben, wenn Sie meine vorherige Frage sah Sie wissen, es ist ein "Space Invaders" -Klon.random "ValueError: list.remove (x): x nicht in der Liste" Fehler in pygame

Es läuft also fast alles glatt, abgesehen von einem zufälligen Fehler, der hin und wieder herausspringt. Dies ist völlig zufällig, es kann vorkommen, nachdem einige Kugeln abgefeuert wurden, oder es kann überhaupt nicht vorkommen.

Ich habe diesen Code:

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 

Manchmal es gibt mir die folgende Fehlermeldung.

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 

Bitte beachten Sie, dass dieser Fehler völlig zufällig ist; auch wenn es nicht ist, kann ich seinen Ursprung nicht verfolgen. Irgendwelche Hilfe, wie man es beseitigt?

+1

Im Allgemeinen ist es eine gute Methode, den Fehler zu finden und dann den Post-Mortem-Debugger zu verwenden ('import pdb; pdb.post_mortem()'). Während der Entwicklung habe ich normalerweise eine catch-all-try-except-Klausel um den Einstiegspunkt meines Programms herum, so dass ich selbst unvorhersehbare Probleme sofort debuggen kann. –

Antwort

3

Ihre Kugel trifft mehrere Feinde. Sie müssen break aus der enemies Schleife.

+0

Das Entfernen von Elementen aus einer Liste, über die das OP iteriert, führt ebenfalls zu Problemen. – DSM

+0

@DSM: Das stimmt, aber das ist einfach zu handhaben. 'für Kugel in Kugeln [:]:' –

+0

Fertig! Übrigens, der 'continue' geht direkt nach 'bullet_draw = True' eingerückt unter 'für bullet in bullets' oder? – mechanicarts

4

Versuchen Sie es mit dem folgenden Wechsel:

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 

Beachten Sie die beiden Kommentare, die ich, dass die Änderungen zeigen hinzugefügt, ist die break notwendig, da eine einzige Kugel mehrere Gegner treffen könnte, die bullets.remove(bullet) verursachen würde aufgerufen werden zweimal, was die Rückverfolgung verursacht, die Sie sehen.

Die erste Änderung ist erforderlich, da das Entfernen von Elementen aus einer Liste beim Iterieren zu unerwarteten Konsequenzen führen kann, da Sie während der Iteration einige Elemente überspringen. Der folgende Code veranschaulicht dies:

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

Auch wenn der Code sieht aus wie es jedes Element aus der Liste entfernen sollte, es entfernt nur alle anderen, weil die Liste Indizes während der Iteration ändern.

Verwandte Themen