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

SwiftUI数独生成器运行报错:数组索引越界

数独游戏索引越界错误分析与修复

可能的错误原因

  • 视图初始化时访问空数组:你的EnigmaViewModel中grid初始值是空数组[],而SwiftUI视图会在generateSudoku调用前就开始渲染。如果视图中用了ForEach(0..<9)这类循环去访问grid[row][col],此时grid是空的,访问grid[row]会直接触发索引越界。
  • 生成器方法中的索引逻辑错误:SudokuGenerator的fillRemaining或removeKDigits方法可能存在索引超出0-8范围的情况:
    • fillRemaining递归过程中,计算下一个填充位置时可能错误地让i或j超过8;
    • removeKDigits随机选择单元格时,可能生成了0-8以外的索引(比如误用了1...9的范围)。

修复方法

1. 初始化视图模型的grid为合法的9x9数组

修改EnigmaViewModel的grid初始值,确保视图渲染时数组是合法的9x9结构:

class EnigmaViewModel: ObservableObject {
    // 初始化为9x9的空数独网格,而非空数组
    @Published var grid: [[Int]] = Array(repeating: Array(repeating: 0, count: 9), count: 9)

    let difficulty = Difficulty.easy

    func generateSudoku() {
        let generator = SudokuGenerator()
        self.grid = generator.generateGrid(k: 20)
    }
}

2. 检查并修正生成器中的索引逻辑

验证fillRemaining的边界处理

确保fillRemaining的递归终止条件和位置计算正确,示例参考:

func fillRemaining(i: Int, j: Int) -> Bool {
    var row = i
    var col = j
    
    // 移动到下一个位置的逻辑,确保row和col不超过8
    if col >= 9 {
        row += 1
        col = 0
        if row >= 9 {
            return true // 填充完成
        }
    }
    
    // 跳过对角线已填充的单元格
    if (row < 3 && col < 3) || (row >=3 && row <6 && col >=3 && col <6) || (row >=6 && col >=6) {
        return fillRemaining(i: row, j: col + 1)
    }
    
    // 尝试填充1-9的数字
    for num in 1...9 {
        if isSafe(row: row, col: col, num: num) {
            grid[row][col] = num
            if fillRemaining(i: row, j: col + 1) {
                return true
            }
            grid[row][col] = 0 // 回溯
        }
    }
    return false
}

核心是确保每次递归的row和col始终在0-8范围内。

修正removeKDigits的随机索引生成

确保随机选择的行和列是0到8的范围:

func removeKDigits(k: Int) {
    var count = k
    while count > 0 {
        let row = Int.random(in: 0..<9)
        let col = Int.random(in: 0..<9)
        
        // 避免重复移除同一个单元格
        if grid[row][col] != 0 {
            grid[row][col] = 0
            count -= 1
        }
    }
}

这里必须用0..<9而不是1...9,因为Swift数组索引从0开始。

3. 临时调试技巧

在访问grid的地方加安全判断,快速定位问题位置:

// 视图中访问grid时先检查边界
if row < grid.count && col < grid[row].count && grid[row][col] != 0 {
    // 执行逻辑
}

内容的提问来源于stack exchange,提问作者Richie

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 05:25:25