python - I keep getting "ValueError: list.remove(x): x not in list" when looping through nested lists -
this question has answer here:
i trying make simple version of space invaders, keep running same error
valueerror: list.remove(x): x not in list
trying remove invaders once they've been hit.
here code.
def killenemies(bullets, enemies): bullet in bullets: x in enemies: y in x: if bullet.top <= y.bottom , bullet.top >= y.top: if bullet.left >= y.left , bullet.right <= y.right: x.remove(y) bullets.remove(bullet)
the problem occurs when if statements true, , console says error occurs in last line
here rest of code
import pygame, sys 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 n in enemies: x = 0 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): bullet in bullets: x in enemies: y in x: if bullet.top <= y.bottom , bullet.top >= y.top: if bullet.left >= y.left , bullet.right <= y.right: x.remove(y) bullets.remove(bullet) def movebullets(bullets): bullet in bullets: bullet.top -= 15 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 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)
you should not try , mutate list while iterating on it. source of issues.
for simple example, try running:
some_list = [1,2,3,4] x in some_list: some_list.remove(x) print(some_list) # prints [2, 4]
obviously not expected outcome - perhaps expect entire list empty.
the solution either use list comprehension create new list required elements, or make copy of list iterate over. if go route of creating copy, simple as:
def killenemies(bullets, enemies): bullet in bullets[:]: x in enemies: y in x[:]: if bullet.top <= y.bottom , bullet.top >= y.top: if bullet.left >= y.left , bullet.right <= y.right: x.remove(y) bullets.remove(bullet)
note list[:]
creates shallow copy of list, , hence underlying objects in original list , copied list should same.
the other issue having in logic of for
loops. each bullet, iterating on multiple enemies, , need break out of 2 inner loops once each bullet 'spent'. written, seems trying remove each bullet multiple times. suggest code refactoring in order here:
def killenemies(bullets, enemies): bullet in bullets[:]: iterenemies(bullets, bullet, enemies) def iterenemies(bullets, bullet, enemies): x in enemies: y in x[:]: if bullet.top <= y.bottom , bullet.top >= y.top: if bullet.left >= y.left , bullet.right <= y.right: x.remove(y) bullets.remove(bullet) return
Comments
Post a Comment