2017-08-15 4 views
1

Je suis en train de faire une version simple des envahisseurs de l'espace, je continue à courir dans la même erreurJe continue à obtenir « ValueError: list.remove (x): x pas dans la liste » lors du bouclage des listes imbriquées

ValueError: list.remove(x): x not in list

en essayant de supprimer les envahisseurs une fois qu'ils ont été touchés.

Voici le code.

def killEnemies(bullets, enemies): 
    for bullet in bullets: 
     for x in enemies: 
      for y in x: 
       if bullet.top <= y.bottom and bullet.top >= y.top: 
        if bullet.left >= y.left and bullet.right <= y.right: 
         x.remove(y) 
         bullets.remove(bullet) 

Le problème se produit uniquement lorsque l'instruction if sont vraies, et la console indique que l'erreur se produit dans la dernière ligne

Voici le reste du code

import pygame, sys 
from pygame.locals import * 


pygame.init() 

FPS = 30 
fpsClock = pygame.time.Clock() 

DISPLAYSURF = pygame.display.set_mode((800, 660), 0, 32) 
pygame.display.set_caption('Space Invaders') 

white = (255, 255, 255) 
black = (0, 0, 0) 
shipx = 50 
shipy = 630 
DISPLAYSURF.fill(black) 

timer = fpsClock.tick() 
time = 0 
direction = '' 
bullets = [] 
bulletx = shipx + 25 
bullety = shipy - 50 
enemies = [[], [], [], [], [], [], []] 
shields = [] 


def drawEnemies(enemies): 
    y = 0 
    for n in enemies: 
     x = 0 
     for f in range(7): 
      enemy = pygame.draw.rect(DISPLAYSURF, white, (30 + x, 40 + y, 75, 20)) 
      n.append(enemy) 
      x += 110 
     y += 30 
    return enemies 

def killEnemies(bullets, enemies): 
    for bullet in bullets: 
     for x in enemies: 
      for y in x: 
       if bullet.top <= y.bottom and bullet.top >= y.top: 
        if bullet.left >= y.left and bullet.right <= y.right: 
        x.remove(y) 
        bullets.remove(bullet) 


def moveBullets(bullets): 
    for bullet in bullets: 
     bullet.top -= 15 
    for b in bullets: 
     pygame.draw.rect(DISPLAYSURF, white, b) 

while True: 


    if direction == 'left': 
     shipx -= 8 
     bulletx -= 8 
    elif direction == 'right': 
     shipx += 8 
     bulletx += 8 


    for event in pygame.event.get(): 
     if event.type == QUIT: 
      pygame.quit() 
      sys.exit() 

     key = pygame.key.get_pressed() 

     if key[K_LEFT]: 
      direction = 'left' 
     elif key[K_RIGHT]: 
      direction = 'right' 
     elif key[K_SPACE]: 
      bullet = pygame.draw.line(DISPLAYSURF, white, (bulletx, bullety), (bulletx, bullety - 25), 2) 
      bullets.append(bullet) 

     if event.type == KEYUP: 
      direction = '' 

    time += timer   
    DISPLAYSURF.fill(black) 
    pygame.draw.polygon(DISPLAYSURF, white, ((shipx, shipy), (shipx + 25, shipy - 50), (shipx + 50, shipy)), 1) 
    drawEnemies(enemies) 
    moveBullets(bullets) 
    killEnemies(bullets, enemies) 
    pygame.display.update() 
    fpsClock.tick(FPS) 
+0

post complet erreur – Nabin

+1

On dirait que nous n'affichons le code complet, ou nous avons besoin du plein rétrolien. Mes sentiments sont que vous modifiez la liste en la répétant, cela pourrait être un gros problème. –

+0

Ceci est une bonne question, mais pas un titre très utile pour quelqu'un qui tente de résoudre ce scénario similaire à l'avenir. – Nabin

Répondre

1

Vous devriez N'essayez pas de faire muter une liste pendant que vous l'itérez. C'est la source de vos problèmes.

Pour un exemple très simple, essayez d'exécuter:

some_list = [1,2,3,4] 
for x in some_list: 
    some_list.remove(x) 
print(some_list) # Prints [2, 4] 

évidemment pas le résultat escompté - peut-être vous attendez toute la liste soit vide.

La solution consiste soit à utiliser une liste de compréhension pour créer une nouvelle liste avec uniquement les éléments requis, soit à faire une copie de la liste à parcourir. Si vous allez l'itinéraire de créer une copie, c'est aussi simple que:

def killEnemies(bullets, enemies): 
    for bullet in bullets[:]: 
     for x in enemies: 
      for y in x[:]: 
       if bullet.top <= y.bottom and bullet.top >= y.top: 
        if bullet.left >= y.left and bullet.right <= y.right: 
         x.remove(y) 
         bullets.remove(bullet) 

Notez le list[:] crée une copie superficielle de la liste, et par conséquent les objets sous-jacents dans la liste initiale et la liste copiée doit être même.

Le numéro autre que vous rencontrez est dans la logique des boucles for. Pour chaque balle, vous itérez plusieurs ennemis et vous devez sortir des deux boucles internes une fois que chaque balle est «dépensée». Comme écrit, il semble que vous essayez d'enlever chaque balle plusieurs fois. Je suggère un code refactoring est en ordre ici:

def killEnemies(bullets, enemies): 
    for bullet in bullets[:]: 
     iterEnemies(bullets, bullet, enemies) 

def iterEnemies(bullets, bullet, enemies): 
    for x in enemies: 
     for y in x[:]: 
      if bullet.top <= y.bottom and bullet.top >= y.top: 
       if bullet.left >= y.left and bullet.right <= y.right: 
        x.remove(y) 
        bullets.remove(bullet) 
        return 
+0

J'ai toujours la même erreur, pourrait-il y avoir un autre problème avec le code? – zacksc

+0

Ajout d'infos supplémentaires. J'espère que cela t'aides. On dirait que vous avez aussi des problèmes avec la mise à jour des ennemis une fois qu'ils sont détruits, mais je vais laisser ça à vous de résoudre. ;) –