我使用pygame在python中编写这段代码,在屏幕上显示对象,然后检测碰撞并在发生碰撞时删除对象。
每次发生碰撞时,如果我的代码都是这样编写的,我会收到此错误:
代码:
for i in range(len(asteroids)):
asteroidObj = asteroids[i]
asteroidObj['rect'] = pg.Rect((asteroidObj['x'],
asteroidObj['y'],
asteroidObj['width'],
asteroidObj['height']))
screen.blit(asteroidObj['surf'], asteroidObj['rect'])
asteroidObj['x']+= asteroidObj['xChange']
asteroidObj['y']+= asteroidObj['yChange']
if asteroidObj['rect'].colliderect(shipObj['rect']):
del asteroids[i]
错误:
asteroidObj = asteroids[i]
IndexError: list index out of range
但是,如果我将for循环更改为:
for i in range(len(asteroids)-1, -1, -1):
代码按预期工作,我不再收到错误。
其中一个循环从项目0-49迭代,另一个循环从49-0迭代,所以我很困惑为什么一个有效,一个没有。有谁知道为什么会这样?
答案 0 :(得分:2)
它只能反向运行,因为您要从列表中删除元素。
例如,假设您有50个小行星,因此您的列表从0到49.小行星range(len(asteroids))
发生碰撞,您将其从列表中删除。现在您的列表长度为49(范围从0到48),但i==49
已经过评估,在下一次迭代中您将拥有new_asteroids = []
for asteroidObj in asteroids:
# Do your stuff here...
if not asteroidObj['rect'].colliderect(shipObj['rect']):
new_asteroids.append(asteroidObj)
asteroids = new_asteroids
,但不再有元素49。当你删除之前的48时它变成了新的48。
如你所知,反过来是一种解决问题的方法,但我建议避免从列表中间删除元素,因为它是O(n)操作。我会做类似的事情:
input_imgs