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

非递归数独求解器:行/列唯一候选值提取函数问题排查

解决你的非递归数独求解器问题

嘿,我来帮你拆解下当前遇到的问题,包括循环退出的合法性,还有行检查代码的逻辑漏洞:

关于修改循环变量强制退出的合法性

首先明确:这种写法语法上是合法的,C语言允许在循环体内直接修改循环变量的值,比如你把a=10、z=10来跳出嵌套循环,编译器不会报错。但这种写法非常不推荐——可读性太差了,别人(甚至几个月后的你自己)看代码时,得花很久才能搞懂你是在刻意跳出循环,而且很容易不小心写出逻辑bug。更清晰的替代方案是:

  • 用标志位配合break:比如定义一个found_match变量,一旦找到匹配就设为1,然后在外层循环判断这个标志位来退出。
  • 或者用goto:在嵌套循环的场景下,goto其实是行业内可接受的写法,比乱改循环变量清晰得多(比如goto end_row_check;直接跳到循环外的标签位置)。

你的行检查代码的核心问题

现在看你写的verifyequalsolutions函数,逻辑是要找当前空白格(i,j)的候选值中,同行其他空白格完全没有的那个值,但代码里有几个关键错误:

  1. 循环边界错了:你用k<9和z<9,但数独候选值是1-9,这会直接漏掉候选值9的检查!应该改成k<=9和z<=9。
  2. 候选值的判断逻辑颠倒:你现在的代码是只要当前z对应的候选值不匹配,就给rowsolution赋值,但后面的z可能还会找到匹配项,这样会错误地把还没验证完的候选值当成结果。正确的逻辑应该是:先假设当前候选值是唯一的,然后遍历同行所有空白格,如果发现任何一个空白格有这个候选值,就标记为不唯一,停止检查;如果遍历完都没找到,这个候选值才是我们要的。
  3. 循环嵌套的顺序混乱:你先遍历候选值的索引,再遍历同行列,再遍历其他空白格的候选值,这个顺序会导致逻辑重复且容易出错。应该先遍历当前单元格的每个候选值,再针对每个候选值去检查同行的其他空白格。

修正后的行检查代码示例

我帮你重写了行检查的逻辑,可读性和正确性都更好:

int verifyequalsolutions(int sudoku[9][9], int solutions[9][9][9], int i, int j) {
    // 遍历当前单元格的所有候选值(1到9)
    for (int candidate = 1; candidate <= 9; candidate++) {
        // 先默认这个候选值在同行其他空白格中是唯一的
        int is_unique = 1;
        
        // 检查同行的每一个单元格
        for (int col = 0; col < 9; col++) {
            // 跳过自己,并且只检查空白格(sudoku[i][col]为0的情况)
            if (col == j || sudoku[i][col] != 0) {
                continue;
            }
            
            // 检查这个空白格的候选值里是否包含当前candidate
            for (int z = 1; z <= 9; z++) {
                if (solutions[i][col][z] == candidate) {
                    // 找到匹配,说明这个候选值不唯一
                    is_unique = 0;
                    break; // 跳出内层候选值检查循环
                }
            }
            
            // 如果已经确定不唯一,直接跳出同行检查循环
            if (!is_unique) {
                break;
            }
        }
        
        // 如果这个候选值在同行其他空白格中唯一,返回它
        if (is_unique) {
            printf("for [%d][%d] i found something in the row!: %d\n", i, j, candidate);
            return candidate;
        }
    }
    
    // 没有找到符合条件的候选值
    return 0;
}

后续扩展到列和3*3宫的建议

等行检查没问题后,你可以用同样的逻辑扩展列和宫的检查:

  • 列检查:遍历当前列的每一行row,跳过row == i的情况,检查空白格的候选值是否包含当前候选值。
  • 3*3宫检查:先计算当前单元格所在宫的起始坐标:start_row = (i / 3) * 3,start_col = (j / 3) * 3,然后遍历宫的3x3范围内的所有单元格,跳过自己,检查空白格的候选值。

最终,你需要把行、列、宫的检查结合起来——只有当某个候选值在行、列、宫的其他空白格中都不存在时,才返回这个值。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 08:24:50