You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

问题分析与修复方案

  1. 核心错误:遍历范围错误
    你用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]:获取拼图块的列数
  2. 额外修复点

    • 放置拼图时,只修改棋盘上拼图块非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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 11:42:22