如何避免IndexError

时间:2012-04-03 06:19:46

标签: python

一点背景:

我正在写一个基于小词的迷宫游戏,从一个由X,O和F组成的简单迷宫开始。

我的迷宫是代表迷宫本身的列表,其中X是墙,O是开放点,F是终点线。

我正在尝试编写一个函数,该函数获取迷宫的名称和用户的当前位置,并返回该位置(N,S,E或W)的所有合法移动的列表。

这是我的练习迷宫和功能。

def get_legal_directions(maze, position):
    x = position[0]
    y = position[1]
    legal = []
    if maze[x-1][y] == 'O' or maze[x-1][y] == 'F':
        legal.append('N')
    if maze[x+1][y] == 'O' or maze[x+1][y] == 'F':
        legal.append('S')  
    if maze[x][y+1] == 'O' or maze[x][y+1] == 'F':
        legal.append('E')
    if maze[x][y-1] == 'O' or maze[x][y-1] == 'F':
        legal.append('W')
    return legal


>>> maze1 = [['X', 'X', 'X', 'X', 'X'], ['X', 'O', 'X', 'F', 'X'], ['X', 'O', 'X', 'O', 'X'], ['X', 'O', 'O', 'O', 'X'], ['X', 'X', 'X', 'X', 'X'], ['X', 'X', 'X', 'X', 'X']]
>>>

输入:get_legal_directions(maze1, (1,1))

输出:['S']

所以函数在这里似乎正常工作,但是当我在另一个函数中使用该函数以便用户与迷宫交互时,我得到了这个:

def interact():
    maze = raw_input('Maze File: ')
    x = maze[0]
    y = maze[1]
    pos = (1,1)
    history = [pos]
    while 1:
        print 'You are at position', pos
        command = raw_input('Command: ')
        if command == 'Q':
            com = raw_input('Are you sure you want to quit? [y] or [n]: ')
            if com =='y':
                print 'Thank you for playing - Goodbye!'
                break
            else: continue
        elif command == 'L':
            get_legal_directions(maze, pos)
        else: print 'invalid command'

我得到以下内容:

>>> interact()

Maze File: maze1

You are at position (1, 1)

Command: L

"   if maze[x-1][y] == 'O' or maze[x-1][y] == 'F':
IndexError: string index out of range"

我写if语句的方式有问题还是别的?感谢任何可以提供帮助的人。

如何让命令L调用函数get_legal_directions()

4 个答案:

答案 0 :(得分:3)

这使迷宫成为一个字符串:

maze = raw_input('Maze File: ')

您的函数需要一个列表列表。

答案 1 :(得分:1)

目前,你正在读一个字符串。

所以你得到:

maze = 'maze1'

而不是你可能期望的那样:

maze = maze1 = [['X', 'X', 'X', 'X', 'X']...

我想你想在提示符下输入变量的名称,并将其变成该变量的内容。

所以你正在读一个字符串,但是你想让它作为Python代码运行。您可以使用eval来执行此操作,例如:

maze = eval(raw_input('Maze File: '))

但这不是很安全,因为您的用户可以在那里粘贴任何Python代码。

也许最好是要求迷宫号码,你可以验证:

mazes = []
mazes.append([['X', 'X', 'X', 'X', 'X'], ['X', 'O', 'X', 'F', 'X'], ['X', 'O', 'X', 'O', 'X'], ['X', 'O', 'O', 'O', 'X'], ['X', 'X', 'X', 'X', 'X'], ['X', 'X', 'X', 'X', 'X']])

maze_number = raw_input('Maze Number: ')
maze = mazes[int(maze_number)]

答案 2 :(得分:0)

我不确定你打算做什么。您正在读取变量maze1的名称,然后尝试通过变量对其进行索引?这绝对不行。

一种可能的解决方案是使用eval,正如其他人指出的那样。正如您已经了解的那样,eval不安全并且可能存在安全问题。另一种更安全的方法是使用输入的字符串将全局变量作为字典来处理,该字符串应作为变量进行求值。

以下是更改后代码的示例

当前

maze = raw_input('Maze File: ')

建议

max_try=3
while True:
    try:
        maze = globals()[raw_input('Maze File: ')]
        break
    except KeyError:
        print "Wrong Input"
        max_try-=1
        if not max_try:
            print "Time Out"
            return

答案 3 :(得分:0)

interact()的第一行是:

maze = raw_input('Maze File: ')

当您进行测试运行时,在提示符下键入“maze1”。因此,maze现已设置为"maze1"

x = maze[0] #x is set to 'm'
y = maze[1] #y is set to 'a'

依此类推。

对于您的测试运行,请更改interact(),使其接受参数maze

def interact(mazeData):
    maze = mazeData[:]
    ...
    ...

然后从解释器中调用它:

>>> maze1 = [['X', 'X' ... ... ]]

>>> interact(maze1)
...
...

另请注意,只要您使用位于迷宫远端的位置,函数get_legal_directions()就会返回索引错误。假设你给(10, 5)作为位置,你的迷宫是10x10。第二个if语句将尝试访问maze[x + 1]maze[11]将超出列表范围。此外,您发送给函数的某些位置参数(position = 0)将给出负索引。这不会生成错误,但会访问列表中的最后一项,这也不是您想要的。您需要添加某种边缘检测,以便get_legal_directions()知道它何时位于迷宫的边缘并且会相应地采取行动。