Python不断返回列表索引超出范围?

时间:2015-03-06 06:12:48

标签: python

我有以下类来检查游戏中所有可用的移动 - 基本上它的作用是返回任何放置的块(w或b)的所有8个方向上的数组位置,并删除当前被aw占用的那些或b阻止 -

class Game():    
 def _available_moves(self):
        ''' generate available moves '''
        self.board = [['','','','','',''],['','','','','',''],['','','b','w','',''],['','','w','b','',''],['','','','','',''],['','','','','','']]
        potential_moves = []
        player = "w"
        second_player = "b"
        for row_num in range(0,len(self.board)):
            for col_num in range(0,len(self.board[row_num])):
                if(self.board[row_num][col_num]==second_player):
                    potential_moves.append([row_num-1,col_num])
                    potential_moves.append([row_num+1,col_num])
                    potential_moves.append([row_num,col_num+1])
                    potential_moves.append([row_num,col_num-1])
                    potential_moves.append([row_num+1,col_num+1])
                    potential_moves.append([row_num-1,col_num+1])
                    potential_moves.append([row_num+1,col_num-1])
                    potential_moves.append([row_num-1,col_num-1])
        print(potential_moves)                    
        for move in range(0,len(potential_moves)):
            move_1 = potential_moves[move][0]
            move_2 = potential_moves[move][1]
            if(self.board[move_1][move_2]=="w" or self.board[move_1][move_2]=="b"):
                del potential_moves[move]
            move_1 = ""
            move_2 = ""
        return potential_moves

这不断给我IndexError: list index out of range但是当我在控制台中尝试时,没有任何错误:

>>> potential_moves = [[2, 4], [4, 4], [3, 5], [3, 3], [4, 5], [2, 5], [4, 3], [2, 3], [3, 3], [5, 3], [4, 4], [4, 2], [5, 4], [3, 4], [5, 2], [3, 2]]
>>> for move in range(0,len(potential_moves)):
            move_1 = potential_moves[move][0]


>>> move_1
3

我认为for循环中的“move”索引是搞乱它的 - 但我不确定。

完整的追溯显示在下面

Traceback (most recent call last):
  File "C:/Users/Karan/Desktop/othello.py", line 202, in <module>
    run_game()
  File "C:/Users/Karan/Desktop/othello.py", line 199, in run_game
    othello._do_turn()
  File "C:/Users/Karan/Desktop/othello.py", line 119, in _do_turn
    self._make_move(current_turn,_translate_move(user_turn_input))
  File "C:/Users/Karan/Desktop/othello.py", line 155, in _make_move
    if([move_row, move_col] in self._available_moves()):
  File "C:/Users/Karan/Desktop/othello.py", line 141, in _available_moves
    move_1 = potential_moves[move][0]
IndexError: list index out of range

该功能在第121-148行,大约(为可读性做了一些改动)

编辑:

我根据建议更新了代码,更改为:

for move in range(0,len(potential_moves)):
    if(self.board[potential_moves[move][0]][potential_moves[move][1]]=="w" or self.board[potential_moves[move][0]][potential_moves[move][1]]=="b"):
        del potential_moves[move]
        potential_moves.append("")
print(potential_moves)
return potential_moves

但现在我的错误更加奇怪了?

    if(self.board[potential_moves[move][0]][potential_moves[move][1]]=="w" or self.board[potential_moves[move][0]][potential_moves[move][1]]=="b"):
IndexError: string index out of range

2 个答案:

答案 0 :(得分:2)

如果我查看您的代码,我会看到一个可能导致您遇到问题的主要因素:

if(self.board[move_1][move_2]=="w" or self.board[move_1][move_2]=="b"):
    del potential_moves[move]

当您从列表中删除某个对象时,您会将列表缩短一个......但在for循环开始时不会更新。

for move in range(0,len(potential_moves)):

此循环获得列表的长度for循环开始之前。这意味着如果您在循环范围内更改列表的大小,您将在for循环完成之前到达列表的末尾。

控制台中没有出现这种情况的原因是您的控制台示例中没有del语句。我愿意打赌,如果你添加了那部分就会得到完全相同的错误。

解决此问题的一种可能方法是,只要删除某些内容,就可以将None个对象附加到列表的末尾,然后在完成for循环后从列表中删除这些对象。< / p>

答案 1 :(得分:2)

我不确定删除元素的更大目的,但如果你按长度循环遍历列表,当你通过删除元素来修改列表时,超出界限是有道理的。

换句话说,在这个块中:

for move in range(0,len(potential_moves)):
    move_1 = potential_moves[move][0]
    move_2 = potential_moves[move][1]
    if(self.board[move_1][move_2]=="w" or self.board[move_1][move_2]=="b"):
        del potential_moves[move]
    move_1 = ""
    move_2 = ""

您在开始时“锁定”循环中的迭代次数,然后修改列表。

我怀疑删除这个项目并不是你想要的,但没有更多的背景,很难说什么可能更合适。

如果 确实 想要删除列表中的元素,您可以按照以下更安全的方式迭代它:

for (move,(move_1, move_2)) in enumerate(potential_moves):
    if(self.board[move_1][move_2]=="w" or self.board[move_1][move_2]=="b"):
        del potential_moves[move]

这将尊重当前元素的删除。

编辑:

为了好玩,可以使用in重写:

for (move,(move_1, move_2)) in enumerate(potential_moves):
    if(self.board[move_1][move_2] in ["w", "b"]):
        del potential_moves[move]