简体   繁体   English

如何在我的代码中修复“IndexError:列表索引超出范围”?

[英]How to fix “IndexError: List index is out of range” in my code?

I am quite new to Python, and I wanted to test out a tilemap system.我对 Python 很陌生,我想测试一个瓷砖地图系统。 When I try to load the tiles, i get the error message IndexError: list index out of range .当我尝试加载图块时,我收到错误消息IndexError: list index out of range What do I need to do in order to solve this issue, and others like it in the future?为了解决这个问题,我需要做些什么,以及其他人将来喜欢它? Exact error:确切的错误:

Traceback (most recent call last):
  File "N:/Python/Projects/Projects/First Topdown/First Topdown.py", line 114, in <module>
    pygame.draw.rect(screen, colors[tilemap[row][column]], (column*tilesize, row*tilesize, tilesize, tilesize))
IndexError: list index out of range

I have heard that it means I am trying to access a value which is none or empty.我听说这意味着我正在尝试访问一个none或空的值。 Here is the part of the code that is about the tilemap .这是关于tilemap的代码部分。 Without the last drawing bit, the rest works fine.没有最后一个绘图位,rest 工作正常。 (It's not a lot of other code, just movement.) (这不是很多其他代码,只是运动。)

import pygame

pygame.init()

tilesize = 64
mapwidth = 16
mapheight = 13
screen = pygame.display.set_mode((mapwidth*tilesize, mapheight*tilesize))


pygame.display.set_caption("Aspen")

WALLTOP = 0
WALLBOT = 1
GRASS = 2
wallTop = (128, 128, 128)
wallBot = (210, 105, 30,)
grass =   (50, 205, 50)

colors = {
WALLTOP : wallTop,
WALLBOT: wallBot,
GRASS : grass
}

tilemap = [
            [WALLTOP, WALLTOP, WALLTOP, WALLTOP, WALLTOP, WALLTOP, WALLTOP, WALLTOP, WALLTOP, WALLTOP, WALLTOP, WALLTOP, WALLTOP, WALLTOP, WALLTOP, WALLTOP,
            WALLTOP, WALLBOT, WALLBOT, WALLBOT, WALLBOT, WALLBOT, WALLBOT, WALLBOT, WALLBOT, WALLBOT, WALLBOT, WALLBOT, WALLBOT, WALLBOT, WALLBOT, WALLTOP,
            WALLTOP, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, WALLTOP,
            WALLTOP, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, WALLTOP,
            WALLTOP, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, WALLTOP,
            WALLTOP, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, WALLTOP,
            WALLTOP, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, WALLTOP,
            WALLTOP, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, WALLTOP,
            WALLTOP, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, WALLTOP,
            WALLTOP, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, WALLTOP,
            WALLTOP, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, WALLTOP,
            WALLTOP, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, GRASS, WALLTOP,
            WALLTOP, WALLTOP, WALLTOP, WALLTOP, WALLTOP, WALLTOP, WALLTOP, WALLTOP, WALLTOP, WALLTOP, WALLTOP, WALLTOP, WALLTOP, WALLTOP, WALLTOP, WALLTOP]
]


running = True
while running:

    screen.fill((64, 64, 64))

    for row in range(mapheight):
        for column in range(mapwidth):
            pygame.draw.rect(screen, colors[tilemap[row][column]], (column*tilesize, row*tilesize, tilesize, tilesize))

    pygame.display.update()

You're getting the IndexError because you've only defined one row in your tilemap , but the outer for loop supplies row indices from 0 to mapheight-1 because of this statement:您收到IndexError是因为您只在tilemap中定义一行,但是由于以下语句,外部for循环提供了从0mapheight-1row索引:

for row in range(mapheight):

To avoid that error, try changing it to:为避免该错误,请尝试将其更改为:

for row in range(len(tilemap)):

Update更新

I think I've figured out what you're trying to do.我想我已经弄清楚你想要做什么了。 As I said previously, the IndexError is because the number of rows in tilemap didn't match the number you were trying to display with the nested for loops.正如我之前所说, IndexError是因为tilemap中的行数与您尝试使用嵌套for循环显示的行数不匹配。

Below I've fixed the way tilemap is defined so it has the proper number of row and columns (and also streamlined a few other definitions and added some event processing to the display loop to allow the script to be gracefully shutdown instead of running in an infinite loop).下面我已经修复了tilemap的定义方式,因此它具有适当数量的行和列(并且还简化了一些其他定义,并向显示循环添加了一些事件处理,以允许脚本正常关闭而不是在无限循环)。

import pygame

pygame.init()

tilesize = 64
mapwidth, mapheight = 16, 13

screen = pygame.display.set_mode((mapwidth*tilesize, mapheight*tilesize))

pygame.display.set_caption("Aspen")

WALLTOP, WALLBOT, GRASS = range(3)

wallTop = (128, 128, 128)
wallBot = (210, 105, 30,)
grass =   (50, 205, 50)

colors = {
    WALLTOP : wallTop,
    WALLBOT : wallBot,
    GRASS   : grass
}

tilemap = [
    [WALLTOP, WALLTOP, WALLTOP, WALLTOP, WALLTOP, WALLTOP, WALLTOP, WALLTOP, WALLTOP, WALLTOP, WALLTOP, WALLTOP, WALLTOP, WALLTOP, WALLTOP, WALLTOP],
    [WALLTOP, WALLBOT, WALLBOT, WALLBOT, WALLBOT, WALLBOT, WALLBOT, WALLBOT, WALLBOT, WALLBOT, WALLBOT, WALLBOT, WALLBOT, WALLBOT, WALLBOT, WALLTOP],
    [WALLTOP, GRASS,   GRASS,   GRASS,   GRASS,   GRASS,   GRASS,   GRASS,   GRASS,   GRASS,   GRASS,   GRASS,   GRASS,   GRASS,   GRASS,   WALLTOP],
    [WALLTOP, GRASS,   GRASS,   GRASS,   GRASS,   GRASS,   GRASS,   GRASS,   GRASS,   GRASS,   GRASS,   GRASS,   GRASS,   GRASS,   GRASS,   WALLTOP],
    [WALLTOP, GRASS,   GRASS,   GRASS,   GRASS,   GRASS,   GRASS,   GRASS,   GRASS,   GRASS,   GRASS,   GRASS,   GRASS,   GRASS,   GRASS,   WALLTOP],
    [WALLTOP, GRASS,   GRASS,   GRASS,   GRASS,   GRASS,   GRASS,   GRASS,   GRASS,   GRASS,   GRASS,   GRASS,   GRASS,   GRASS,   GRASS,   WALLTOP],
    [WALLTOP, GRASS,   GRASS,   GRASS,   GRASS,   GRASS,   GRASS,   GRASS,   GRASS,   GRASS,   GRASS,   GRASS,   GRASS,   GRASS,   GRASS,   WALLTOP],
    [WALLTOP, GRASS,   GRASS,   GRASS,   GRASS,   GRASS,   GRASS,   GRASS,   GRASS,   GRASS,   GRASS,   GRASS,   GRASS,   GRASS,   GRASS,   WALLTOP],
    [WALLTOP, GRASS,   GRASS,   GRASS,   GRASS,   GRASS,   GRASS,   GRASS,   GRASS,   GRASS,   GRASS,   GRASS,   GRASS,   GRASS,   GRASS,   WALLTOP],
    [WALLTOP, GRASS,   GRASS,   GRASS,   GRASS,   GRASS,   GRASS,   GRASS,   GRASS,   GRASS,   GRASS,   GRASS,   GRASS,   GRASS,   GRASS,   WALLTOP],
    [WALLTOP, GRASS,   GRASS,   GRASS,   GRASS,   GRASS,   GRASS,   GRASS,   GRASS,   GRASS,   GRASS,   GRASS,   GRASS,   GRASS,   GRASS,   WALLTOP],
    [WALLTOP, GRASS,   GRASS,   GRASS,   GRASS,   GRASS,   GRASS,   GRASS,   GRASS,   GRASS,   GRASS,   GRASS,   GRASS,   GRASS,   GRASS,   WALLTOP],
    [WALLTOP, WALLTOP, WALLTOP, WALLTOP, WALLTOP, WALLTOP, WALLTOP, WALLTOP, WALLTOP, WALLTOP, WALLTOP, WALLTOP, WALLTOP, WALLTOP, WALLTOP, WALLTOP],
]

running = True
while running:

    screen.fill((64, 64, 64))

    for row in range(mapheight):
        for column in range(mapwidth):
            pygame.draw.rect(screen, colors[tilemap[row][column]], (column*tilesize, row*tilesize, tilesize, tilesize))

    # Process user-events.
    for event in pygame.event.get():
        if event.type == pygame.QUIT:  # User clicked to close window.
            running = False
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_ESCAPE: # Press escape key to quit.
                running = False

    pygame.display.update()

Ok I finally understood what you are doing.好的,我终于明白你在做什么了。

You tried to do a second slice of your tilemap, even though your tilemap is one dimensional.即使您的 tilemap 是一维的,您也尝试对您的 tilemap 进行第二个切片。 For multidimensional arrays, it's best to use numpy arrays imo.对于多维 arrays,最好使用 numpy arrays imo。 You'll see what I mean when you print out the tmap in my code, it's much more readable.当您在我的代码中打印出 tmap 时,您会明白我的意思,它更具可读性。 Also, since python works with indents, it's a good idea to organize long function calls by separating different arguments to separate lines.此外,由于 python 与缩进一起使用,因此通过将不同的 arguments 分隔为单独的行来组织长 function 调用是一个好主意。 Othewise you get a really unreadable long line in your code.否则,您的代码中会出现非常难以阅读的长行。

import pygame
import numpy as np

pygame.init()

# Define base values for tiles
tsize, width, height = 64,16,13

# Set the stage with an empty 2D array full of zeroes
# Create the tilemap dynamically from width and height.
tmap = np.zeros((height,width),dtype=int)

# defines the screen I guess?
screen = pygame.display.set_mode((width*tsize, height*tsize))
pygame.display.set_caption("Asspain")

# You can now change the tilemap manually.
# You have three unique rows, so you can
# just make lists of those and later insert
# them into your np.array
r1 = [1]*width

r2 = [1]
r2.extend([2]*14)
r2.extend([1])

r3 = [1]
r3.extend([0]*14)
r3.extend([1])

# turn your lists into np.arrays so they work
# with your tmap.
r1, r2, r3 = np.array(r1),np.array(r2),np.array(r3)

# insert the rows at the appropreate positions
# mind you, indexing works a bit different in
# np.arrays than in python builtin lists.
tmap[0] = r1.copy()
tmap[1] = r2.copy()
tmap[2:12] = r3.copy()
tmap[12] = r1.copy()

# You now have a nice and readable tmap.
# You can make the map creation process
# as manual as you want, I just used shortcuts
# based on symmetry.
print(tmap)

# Now you can just iterate over every element
# via double iteration, or using indices.
# I've heard iterating over indices using range
# is always faster.

# define colormap
cmap = {0:(50, 205, 50),
        1:(128, 128, 128),
        2:(210, 105, 30,)}

# this is unneccessary, but it's good to know
# that numpy arrays also have a len() like
# attribute called shape.
width, heigth = tmap.shape[0], tmap.shape[1]

# Gameloop
while True:

    # Is this the default color of a tile?
    # Do you need that?
    screen.fill((64, 64, 64))

    for row in range(width):
        for col in range(heigth):
            pygame.draw.rect(screen, 
                             cmap[tmap[row][col]],
                             (col*tsize,
                              row*tsize,
                              tsize,
                              tsize))
    pygame.display.update()

EDIT: I noticed that you do a lot of dictionary slices, which are very slow.编辑:我注意到你做了很多字典切片,非常慢。 If you do not need to repeatedly slice a dictionary inside the game loop (ie the map doesn't change), don't.如果您不需要在游戏循环中重复切片字典(即 map 不会更改),请不要。 I've written a bit of extra code, which produces the same tmap array as above as a template for your tiles, but this time, I'm also casting an array, which maps color triplets to these positions.我已经编写了一些额外的代码,它会生成与上面相同的tmap数组作为图块的模板,但是这一次,我还要转换一个数组,它将颜色三元组映射到这些位置。

This way you can create your whole map once using fast numpy arrays, which utilize dtype typecasting of your array, while still benefitting from the readibility of the previously specified tmap.通过这种方式,您可以使用快速 numpy arrays 一次创建整个 map,它利用阵列的 dtype 类型转换,同时仍受益于先前指定的可读性。

import numpy as np
import matplotlib.pyplot as plt

tsize, width, height = 64,16,13
tmap = np.zeros((height,width),dtype=int)
cmap = np.zeros((height,width,4),dtype=int)

r1 = [1]*width

r2 = [1]
r2.extend([2]*14)
r2.extend([1])

r3 = [1]
r3.extend([0]*14)
r3.extend([1])

r1, r2, r3 = np.array(r1),np.array(r2),np.array(r3)

tmap[0] = r1.copy()
tmap[1] = r2.copy()
tmap[2:12] = r3.copy()
tmap[12] = r1.copy()

cdct = {0:np.array((50, 205, 50, 200),dtype=int),
        1:np.array((128, 128, 128, 200),dtype=int),
        2:np.array((210, 105, 30, 200),dtype=int)}

for posy, row in enumerate(tmap):
    for posx, col in enumerate(row):
        cmap[posy,posx] = cdct[col].copy()

fig, ax = plt.subplots()
plt.axis('off')

ax.imshow(cmap)

As you can see, matplotlib can easily visualise X,Y,Z arrays, which the imshow() function can read as a bitmap. As you can see, matplotlib can easily visualise X,Y,Z arrays, which the imshow() function can read as a bitmap. X are the rows, Y are the columns and Z are the color triplets. X 是行,Y 是列,Z 是颜色三元组。 I actually made Z four elements long to toggle transparency with the fourth element.实际上,我将 Z 设为四个元素,以便用第四个元素切换透明度。 This way you can create your bitmap once as a background and then just iterate directly over the color quadruples, without doing 16*13 slow dictionary slices at every iteration of the while loop.这样,您可以创建一次 bitmap 作为背景,然后直接在颜色四元组上进行迭代,而无需在 while 循环的每次迭代中执行 16*13 慢速字典切片。 The plotting, obviously, is just a visual demonstration of what it will look like and is a nifty little tool for modelling your game map.显然,绘图只是它外观的视觉演示,并且是一个漂亮的小工具,用于为您的游戏 map 建模。

And because it uses typecasted numpy arrays and avoids a lot of slow operations, it should be lightning fast compared to before.而且因为它使用了类型转换的 numpy arrays 并且避免了很多缓慢的操作,因此与以前相比应该快如闪电。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何修复 IndexError:列出此代码的索引超出范围 - How to fix IndexError: list index out of range for this code 如何在下面的代码中修复“IndexError:list index out of range” - How to fix “IndexError: list index out of range” in the following piece of code 如何使用 CNN 代码修复 Python “IndexError: list index out of range” - How to fix Python “IndexError: list index out of range” with CNN code 如何解决“ IndexError:列表索引超出范围” - How to fix “IndexError: list index out of range” 当代码缺失值时,如何修复Web抓取Python代码“ IndexError:列表索引超出范围” - How to fix web scraping Python code “IndexError: list index out of range” when the code hits missing values IndexError:列出索引超出或范围修复和 ValueError - IndexError: List index out or range fix and ValueError 如何修复错误 IndexError:列表索引超出范围 - How to fix errors IndexError: list index out of range 如何修复&#39;IndexError:列表索引超出范围&#39;错误 - How to fix 'IndexError: list index out of range' error 如何修复Python中的“ IndexError:列表分配索引超出范围”错误? - How to fix “IndexError: list assignment index out of range” error in Python? 如何修复IndexError:列表索引超出范围代理 - How to fix IndexError: list index out of range proxy
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM