for循环的索引未正确迭代

时间:2019-01-09 20:05:23

标签: python python-3.x

我有一个for循环,该循环应该迭代等于数组长度的次数。循环运行正确的次数,但是索引没有正确增加。

我尝试用i = i + 1手动递增i,但这似乎并没有改变任何东西。

room = [['x','x','x','x','x'],['x','.','.','.','x'],['x','.','.','.','x'],['x','.','.','.','x'],['x','x','x','x','x']]
entities = []

class Entity:
    def __init__(self, x_pos, y_pos):
        self.x_pos = x_pos
        self.y_pos = y_pos

        self.new_x_pos = x_pos
        self.new_y_pos = y_pos
    def Move(self, x_move, y_move):
        self.new_y_pos = self.y_pos + y_move
        self.new_x_pos = self.x_pos + x_move
        if self.CheckCollision(self) is True:
            print("collision")
        if self.CheckCollision(self) is False:
            self.new_x_pos = self.x_pos
            self.new_y_pos = self.y_pos
    def CheckCollision(self, entity1):
        for i in range(len(entities)-1):
            #this loop here. It runs twice, but the value of i is zero for both iterations
            entity = entities[i]
            print(i)
            if entity1.new_y_pos == entity.y_pos:
                if entity1.new_x_pos == entity.x_pos:
                    return True
                    break
            else:
                return False
calipso = Entity(1, 1)
entities.append(calipso)
joseph = Entity(3,2)
entities.append(joseph)
print(entities)
calipso.Move(1,1)

print(calipso.x_pos, calipso.y_pos, sep=' ')

我希望我增加for循环的每次迭代,因此对于第一次迭代,i === 0,对于第二次迭代,i === 1。目前,两次迭代的i === 0,我不知道为什么。

2 个答案:

答案 0 :(得分:1)

for循环存在一些问题。首先,如果y位置匹配,但x值不匹配,则什么也不会发生。但是,除非出现这种情况,否则for循环将始终在第一次迭代后退出,因为如果位置重合,则会调用return True(顺便说一下,由于return True,您不会之后就不需要break了。否则,它将返回False

因此在Move内,CheckCollision被调用两次,每个if语句一次,这就是i被打印两次,0两次的原因。

要解决此问题,您必须让CheckCollision返回False for循环,以便它检查所有实体以确保它不会碰撞任何东西。

要考虑的最后一件事是,您永远不要检查entity1entity没有引用同一对象。在某些情况下会导致实体与自身发生碰撞!在没有完全修改方法本身以使其与其他答案相同的情况下,要解决的唯一选项是将每种id附加到某种唯一的entity,但要修改方法(与其他答案一样)绝对是更好的选择。

从风格上讲,类的方法名称应始终以小写字母开头(因此您的方法应为movecheckCollision等)。

编辑:在这种情况下,i永远也不会进入1。这是因为len(entities)2,所以for循环将从01,不包括结尾,所以无论它停止了什么在第一次迭代之后。但是,如果您有更多的实体,则会遇到上述问题。

答案 1 :(得分:1)

我已经重构了您的代码,以便checkCollision方法按照我认为的含义工作。查看代码中的注释。我更改了方法的名称,以小写字母开头。

class Entity:
    def __init__(self, x_pos, y_pos):
        self.x_pos = x_pos
        self.y_pos = y_pos
        self.new_x_pos = x_pos
        self.new_y_pos = y_pos

    def move(self, x_move, y_move):
        self.new_x_pos = self.x_pos + x_move
        self.new_y_pos = self.y_pos + y_move
        if self.checkCollision() is True:
            # We don't update x_pos and y_pos here since collision means entity shouldn't move
            print("collision")
            return False
        else: # You need to use ELSE here so that you don't end up calling checkCollision twice
            # if checkCollision returned a False, then we can update the position of entity
            self.x_pos = self.new_x_pos
            self.y_pos = self.new_y_pos
            return True

    def checkCollision(self):
        for entity in entities:
            # Iterate through every entity other than self and see if their position is the same as self's possible new position
            if entity != self and entity.x_pos == self.new_x_pos and entity.y_pos == self.new_y_pos:
                return True
        # Return false if no collision occurs after checking through every entity     
        return False

calipso = Entity(1, 1)
entities.append(calipso)
joseph = Entity(3,2)
entities.append(joseph)

calipso.move(1,1) # successful move
print(calipso.x_pos, calipso.y_pos, sep=' ') # prints 2 2 after succesful move
calipso.move(1,0) # collision with joseph, fails
print(calipso.x_pos, calipso.y_pos, sep=' ') # prints 2 2, calipso did not move