Python日历拼图程序索引错误原因排查求助
Dragon Fjord A-Puzzle-A-Day拼图程序索引越界问题排查
我具备Java及Web开发经验,近期正在学习Python,为加深语言理解,开发了一款用于解决Dragon Fjord A-Puzzle-A-Day日历拼图的命令行程序。目前已完成棋盘与拼图块的创建,但在实现拼图块放置函数place()时遇到问题,出现索引错误。我选择使用numpy处理数组操作,认为列表嵌套也能实现类似效果,但核心问题并非numpy的使用,而是索引越界。以下是相关代码及报错信息:
import numpy as np # 创建空棋盘 board = np.zeros((7,7)) board[0:2,6]=9 board[6,4:7]=9 # 拼图块字典:键为编号,值为[拼图数组, 是否已使用(0未使用/1已使用)] pieces = {1: [np.array([[1,0],[1,0],[1,1],[0,1]]),0], 2: [np.array([[0,0,2],[2,2,2],[2,0,0]]),0], 3: [np.array([[3,3,3],[3,0,0],[3,0,0]]),0], 4: [np.array([[4,0],[4,4],[4,0],[4,0]]),0], 5: [np.array([[5,5,5],[5,5,5]]),0], 6: [np.array([[6,6],[6,6],[6,0]]),0], 7: [np.array([[0,0,0,7],[7,7,7,7]]),0], 8: [np.array([[8,0,8],[8,8,8]]),0]} # 放置拼图块到棋盘 def place(p,x,y): def overlap(p,x,y): for i in range(0,pieces[p][0].size): for j in range(0,pieces[p][0][0].size): print("j is {0}".format(j)) if board[x+i,y+j] != 0 and pieces[p][0][i,j] != 0: return True return False # 检查拼图是否未使用且不会重叠 if pieces[p][1] != 1 and not overlap(p,x,y): for i in range(0,pieces[p][0].size): for j in range(0,pieces[p][0][0].size): # 遍历行列替换棋盘对应位置 board[x+i,y+j]=pieces[p][0][i,j] pieces[p][1] = 1 # 向左旋转拼图块 def rotatel(p): pieces[p] = np.rot90(pieces[p]) # 向右旋转拼图块 # 暂时保留这个函数,后续可能有用 def rotater(p): rotatel(p) rotatel(p) rotatel(p) # 测试放置功能 print(board) place(1,1,1) print(board)
报错信息:
line 24, in overlap if board[x+i,y+j] != 0 and pieces[p][0][i,j] != 0: IndexError: index 7 is out of bounds for axis 0 with size 7
问题分析与修复方案
核心错误:遍历范围错误
你用pieces[p][0].size作为行的循环范围,但size是数组的总元素数(比如拼图1的数组是4×2,总元素数是8),这会让i从0循环到7,加上初始x=1后,x+i会达到8,超出棋盘7×7的索引范围(最大索引为6)。
正确做法是用shape属性获取数组的行、列数:pieces[p][0].shape[0]:获取拼图块的行数pieces[p][0].shape[1]:获取拼图块的列数
额外修复点
- 放置拼图时,只修改棋盘上拼图块非0的位置,避免覆盖棋盘原有边框(标记为9的区域)
rotatel()函数错误地替换了整个拼图块列表,应该只旋转数组部分,保留使用状态- 新增棋盘边界检查,防止拼图块超出棋盘范围
修复后的完整代码
import numpy as np # 创建空棋盘 board = np.zeros((7,7)) board[0:2,6]=9 board[6,4:7]=9 # 拼图块字典:键为编号,值为[拼图数组, 是否已使用(0未使用/1已使用)] pieces = {1: [np.array([[1,0],[1,0],[1,1],[0,1]]),0], 2: [np.array([[0,0,2],[2,2,2],[2,0,0]]),0], 3: [np.array([[3,3,3],[3,0,0],[3,0,0]]),0], 4: [np.array([[4,0],[4,4],[4,0],[4,0]]),0], 5: [np.array([[5,5,5],[5,5,5]]),0], 6: [np.array([[6,6],[6,6],[6,0]]),0], 7: [np.array([[0,0,0,7],[7,7,7,7]]),0], 8: [np.array([[8,0,8],[8,8,8]]),0]} # 放置拼图块到棋盘 def place(p,x,y): piece_arr = pieces[p][0] piece_rows, piece_cols = piece_arr.shape def overlap(): for i in range(piece_rows): for j in range(piece_cols): # 先检查索引是否在棋盘范围内 if x+i >=7 or y+j >=7: return True if board[x+i,y+j] != 0 and piece_arr[i,j] != 0: return True return False # 检查拼图是否未使用且不会重叠、超出棋盘 if pieces[p][1] != 1 and not overlap(): for i in range(piece_rows): for j in range(piece_cols): if piece_arr[i,j] != 0: board[x+i,y+j] = piece_arr[i,j] pieces[p][1] = 1 # 向左旋转拼图块 def rotatel(p): # 只旋转数组部分,保留使用状态 pieces[p][0] = np.rot90(pieces[p][0]) # 向右旋转拼图块 def rotater(p): for _ in range(3): rotatel(p) # 测试放置功能 print("初始棋盘:") print(board) place(1,1,1) print("\n放置拼图1后的棋盘:") print(board)
内容的提问来源于stack exchange,提问作者Grunka Bunka
相关产品推荐
相关产品推荐

