Python元组超出范围

时间:2012-11-21 01:00:22

标签: python tuples

我一直收到错误IndexError:元组超出范围,我希望你们能帮助我完成我的程序

MIN_ROW = 0
MAX_ROW = 3
MIN_COLUMN = 0
MAX_COLUMN = 19

问题似乎在第7行持续存在

def display(theMap):
r = 0
c = 0
print("PLAYER MAP")
for r in range (0, (MAX_ROW + 1), 1):
    for c in range (0, (MAX_COLUMN + 1), 1):
        print(theMap[r][c])   #this line
    print()
print()

def loadMap():
theMap = []
for r in range(0,(MAX_ROW+1), 1):
    theMap.append([])
    for c in range(0,(MAX_COLUMN+1), 1):
        theMap[r].append(" ")
#           0    1    2    3    4    5    6    7    8    9   10   11    12   13   14   15   16    17   18   19 
map  [0] =   "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J"
map  [1] =   "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-"
map  [2] =   "|r|","| |", "| |", "| |", "| |", "| |", "| |", "| |", "| |", "| |", "|" 
map  [3] =   "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-"
return theMap

所以我不确定我的元组是如何超出范围但是希望你们能指出并帮助我

2 个答案:

答案 0 :(得分:3)

使用显式循环编写内容通常会导致难以调试的问题。这就是为什么Python不会强迫你这样做,实际上鼓励你不要:

def display(theMap):
    print("PLAYER MAP")
    for row in theMap:
        for col in row:
            print(col)
        print()
    print()

这仍然不是你想要的,因为print(col)会打印换行符。您不希望每个单元格都在自己的行上,您希望单元格之间有空格,并且每行都需要自己的行。为此,您必须改为print(col, end=' ')

或者更简单:

def display(theMap):
    print("PLAYER MAP")
    for row in theMap:
        print(' '.join(row))
    print()

或者,更简洁 - 但可能不那么简单:

def display(theMap):
    print("PLAYER MAP")
    print('\n'.join(' '.join(row) for row in theMap))
    print()

您可以通过一次创建Map来改进Map,而不是创建空行,然后替换它们。例如:

def loadMap():
    return [
        ("0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J"),
        ("-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-"),
        ("|r|","| |", "| |", "| |", "| |", "| |", "| |", "| |", "| |", "| |", "|"),
        ("-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-")]

一般来说,每当你发现自己在Python中编写for i in range(something)时,你就会做一些不必要的事情,而你最终会调试它。

现在,您可以争辩说这种风格并没有“捕捉错误”。但是使用显式循环执行操作只会捕获一些错误,并以一种非常难以调试的方式捕获它们。如果你知道你的先决条件,你通常可以更简单明了地写出来:

theMap = loadMap()
assert(all(len(row) == len(theMap[0]) for row in theMap))

另外,如果您知道测试用例的输出应该是什么,那么您可以编写用于验证输出的单元测试。

无论如何,即使解决了所有这些问题,你仍然会遇到一些问题。例如,除了第2行比其他行短几列之外,该行中的各列是其他行中的3倍,因此它根本不会排列。但是一旦你运行它,就应该更容易调试视觉内容。

退后一步,你显然会通过第2行推进'r'。事实上,你可能需要代表地图的是宽度和当前位置:

def display(mapWidth, playerPosition):
    print('PLAYER MAP')
    # Display the first line. This is the header, with a label for each of the
    # mapWidth columsn, with a space between each label, and an extra space at
    # the start, like ' 0 1 2 3 4'. The ' '.join(s) creates a new string by 
    # putting a space between each element of s. The '012...XYZ'[:mapWidth] 
    # just takes the first mapWidth characters of the longer string. 
    print(' ' + ' '.join('0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'[:mapWidth]))

    # Display the second line. This is just a '-' for each column, with a space
    # between each, and an extra space at the start, like ' - - - - -'. The join
    # works the same as above; the '-' * mapWidth creates a string with mapWidth
    # copies of '-'.
    print(' ' + ' '.join('-' * mapWidth))

    # Display the third line. This is the trickiest. This is cell for each column,
    # where the first playerPosition cells are '| |', the playerPositionth is 
    # '|r|', and the rest are again '| |', with no space between them. It seemed
    # simpler to treat this as a group of playerPosition+1 '|' characters with 
    # spaces between, an 'r' character, and a group of mapWidth-playerPosition
    # '|' characters with spaces between again, but there are various different 
    # ways of printing something equivalent. The only new thing here is the 
    # end='' keyword argument--without that, each print ends with a newline.
    print(' '.join('|' * (playerPosition + 1)), end='')
    print('r', end='')
    print(' '.join('|' * (mapWidth - playerPosition)))

    # Fourth line, same as the second.
    print(' ' + ' '.join('-' * mapWidth))
    print()

根据您对join方法,print函数等的熟悉程度,您可能会发现这更容易阅读:

def display(mapWidth, playerPosition):
    print('PLAYER MAP')
    print(' ' + ' '.join('0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'[:mapWidth]))
    print(' -' * mapWidth)
    print(' '.join('|' * (playerPosition + 1)) +
          'r' +
          ' '.join('|' * (mapWidth - playerPosition)))
    print(' -' * mapWidth)
    print()

值得思考的原因是,例如' ' + ' '.join('-' * 8)' -' * 8是一回事。

另一种做出棘手的第三行的方法是:

   # Print mapWidth '|' characters, each followed by a ' ', except for the one
   # at the player position, which is followed by an 'r'. Then we still need one
   # more '|' at the end.
   print(''.join('|' + (' ' if i != playerPosition else 'r') 
                 for i in range(mapWidth) + '|')

我认为这是最容易用英语解释的,但是将它翻译成Python需要生成器表达式和三元if表达式,这两种表达式你可能都不想学习 - 最终结果是甚至是Python开发人员可能不想阅读的经验。

当然,如果有疑问,你可以随时把事情分成不同的行,甚至是单独的函数,以使它们更具可读性:

    cellsBeforePlayer = '| ' * playerPosition
    cellsWithPlayer = cellsBeforePlayer + '|r|'
    cellsToEnd = cellsWithPlayer + '| ' * (mapWidth - playerPosition)
    print(cellsToEnd)

无论如何,这些都做同样的事情:

>>> display(MAX_COLUMN - MIN_COLUMN + 1, 3)
PLAYER MAP
 0 1 2 3 4 5 6 7 8 9 A B C D E F G H I J
 - - - - - - - - - - - - - - - - - - - -
| | | |r| | | | | | | | | | | | | | | | |
 - - - - - - - - - - - - - - - - - - - -

除非那些MIN_COLUMNMAX_COLUMN值是要求的一部分,否则我将再次使用单个COLUMNS=20变量,它避免了另一个常见的一对一错误(函数调用中的+ 1,在需要时很容易忘记包含,或者在不需要时添加错误。)

或者,如果地图宽度是固定的,那就更简单了:

def display(playerPosition):
    print('PLAYER MAP')
    print(' ' + ' '.join('0123456789ABCDEFGHIJ'))
    print(' -' * 20)
    print(' '.join('|' * (playerPosition + 1)) +
          'r' +
          ' '.join('|' * (20 - playerPosition)))
    print(' -' * 20)
    print()

无论如何,这样做的优势超出了display的简单性,而且根本不需要loadMap来移动播放器,而不是:

theMap[2][playerPosition] = '| |'
playerPosition += stepsMoved
theMap[2][playerPosition] = '|r|'
display(theMap)

你这样做:

playerPosition += stepsMoved
display(playerPosition)

您的整个游戏状态从一个复杂的列表列表减少到一个整数。

答案 1 :(得分:1)

map[2]似乎与其他行的格式不同。这意味着它没有20个要迭代的元素。那会导致你看到的错误。

此外,map()是内置函数,因此您可能需要选择其他名称以避免混淆。

在这种情况下,你应该避免使用索引遍历地图,并且反正迭代元组

def display(the_map):
    print("PLAYER MAP")
    for row in the_map:
        for cell in row:
            print(cell)
        print()
    print()

或者

def display(the_map):
    print("PLAYER MAP")
    for row in the_map:
        print(''.join(row))
    print()

编辑:现在有更多信息,这里有一个更简单明确的方式来实现你的地图

def display(the_map):
    print(the_map[0].replace("", " "))
    print(the_map[1].replace("", " "))
    print(the_map[2].replace("", "|"))
    print(the_map[3].replace("", " "))

the_map = ["0123456789ABCDEFGHIJ",
           "--------------------",
           "r                   ",
           "--------------------"]
display(the_map)