Pygame居中网格点击报错:IndexError列表索引越界问题排查
问题分析与解决方案
核心问题原因
- 鼠标坐标未转换为网格相对坐标:当前直接用窗口全局坐标计算行列,但网格是从
gridFrameX和gridFrameY位置开始绘制的,导致点击网格区域时,计算出的gridRow/gridCol与实际网格行列不匹配,甚至超出网格尺寸范围。 - 未限制点击范围:点击网格外区域时,计算出的行列会超出
gridPuzzle的索引范围,直接访问就会触发IndexError。
修改步骤
1. 转换鼠标坐标为网格内部相对坐标
获取鼠标位置后,先减去网格的起始坐标,得到网格内的相对位置,再用这个相对位置计算行列:
x_rel = x - gridFrameX y_rel = y - gridFrameY gridCol = x_rel // blockSize gridRow = y_rel // blockSize
2. 增加点击有效性判断
只有当点击位置确实在网格范围内时,才执行瓦片切换操作,避免越界访问:
if 0 <= x_rel < gridFrame and 0 <= y_rel < gridFrame: if 0 <= gridRow < gridSize and 0 <= gridCol < gridSize: gridPuzzle[gridRow][gridCol] = 1 - gridPuzzle[gridRow][gridCol]
3. 修复递归重置问题(额外优化)
原代码按R键会递归调用drawGrid(),导致多个循环嵌套,改为直接重置gridPuzzle即可:
if event.key == pygame.K_r: gridPuzzle = [[0] * gridSize for _ in range(gridSize)] gridPuzzle[0][0] = 1
4. 修正全局变量访问
quit()函数中需要声明running为全局变量,否则无法正确终止主循环:
def quit(): global running running = False pygame.quit()
修改后的完整代码
import pygame pygame.init() pygame.font.init() colorBlack = (0, 0, 0); colorWhite = (255, 255, 255); colorRed = (255, 0, 0) winWidth = 1280; winHeight = 720; FPS = 30 winDisplay = pygame.display.set_mode((winWidth, winHeight)) FPSClock = pygame.time.Clock() running = True def drawGrid(): blockSize = 47 # 单个网格块像素尺寸 gridSize = 10 # 网格行列数(10x10) gridFrame = 479 # 网格框架总像素尺寸 gridFrameX = 501 # 网格框架X起始坐标 gridFrameY = 221 # 网格框架Y起始坐标 gridFrameRect = (gridFrameX, gridFrameY, gridFrame, gridFrame) # 网格框架矩形 gridSolution = [[0] * gridSize for _ in range(gridSize)] # 网格答案数组 gridPuzzle = [[0] * gridSize for _ in range(gridSize)] # 网格谜题数组 gridPuzzle[0][0] = 1 # 初始化第一个单元格为红色 while running: for event in pygame.event.get(): if event.type == pygame.QUIT: quit() if event.type == pygame.KEYDOWN: if event.key == pygame.K_ESCAPE: quit() if event.key == pygame.K_r: # 重置网格,替代递归调用 gridPuzzle = [[0] * gridSize for _ in range(gridSize)] gridPuzzle[0][0] = 1 if event.type == pygame.MOUSEBUTTONDOWN: x, y = pygame.mouse.get_pos() print("鼠标位置: ", x, y) # 转换为网格内部相对坐标 x_rel = x - gridFrameX y_rel = y - gridFrameY # 判断点击是否在网格范围内 if 0 <= x_rel < gridFrame and 0 <= y_rel < gridFrame: gridRow = y_rel // blockSize gridCol = x_rel // blockSize # 确保行列索引有效 if 0 <= gridRow < gridSize and 0 <= gridCol < gridSize: gridPuzzle[gridRow][gridCol] = 1 - gridPuzzle[gridRow][gridCol] print("切换网格单元格: ", gridRow, gridCol) # 绘制左侧和顶部黑色区域 pygame.draw.rect(winDisplay, colorBlack, (0, 0, 501, winHeight)) pygame.draw.rect(winDisplay, colorBlack, (501, 0, 772, 221)) # 绘制网格单元格 for gameRow in range(gridSize): for gameCol in range(gridSize): rect = (gridFrameX + gameCol * blockSize, gridFrameY + gameRow * blockSize, blockSize, blockSize) pygame.draw.rect(winDisplay, colorBlack, rect, 1) # 绘制单元格边框 if gridPuzzle[gameRow][gameCol] == 1: pygame.draw.rect(winDisplay, colorRed, rect) # 填充红色 else: pygame.draw.rect(winDisplay, colorWhite, rect) # 填充白色 # 绘制网格框架边框 pygame.draw.rect(winDisplay, colorBlack, gridFrameRect, 1) pygame.display.update() FPSClock.tick(FPS) def quit(): global running running = False pygame.quit() if __name__ == "__main__": drawGrid()
内容的提问来源于stack exchange,提问作者kbrocks100
相关产品推荐
相关产品推荐

