为什么“i”变量会奇怪地递增?[关闭]

Why is the 'i' variable incrementing weirdly? [closed]

提问人:yanasf 提问时间:10/3/2023 最后编辑:yanasf 更新时间:10/3/2023 访问量:91

问:


这个问题似乎与帮助中心定义的范围内的编程无关。

上个月关闭。

给定一个具有有效解决方案的 9x9 数独网格。

我正在尝试编写一种方法来验证数独“框”(在本例中为 3x3 并且位于整个数独拼图内部)中(换句话说,检查重复项或超出范围的值)。我希望 3x3 网格内的每个索引都与其他值一起检查,看看这些值是否相等,如果相等,则 3x3 将无效。但是,我注意到(如果我没记错的话)“i”变量正在以一种奇怪的方式递增。首次调用 for 循环时,'i' 为 0,然后下一个增量 'i' 也是 0,最后一个增量 'i' 为 2。不知道为什么会这样。请让我知道我做错了什么

public boolean isValidBox(int row, int col) {
         for (int i = 0; i < 3; i++) {
             for (int j = 0; j < 3; j++) {
                 for (int k = 0; k < 3; k++) {
                     for (int l = 0; l < 3; l++) {
                         if (grid[row + i][col + j] == grid[row + k][col + l] && i != k && j != l) {
                             return false;
                         }
                     }
                 }
             }
         }
          return true;
    }

我希望代码进行 81 次检查,换句话说,我期望这一行中的代码

if (grid[row + i][col + j] == grid[row + k][col + l] && i != k && j != l)

运行 81 次,但它没有这样做,我认为它运行了 243 次;81*3 更多次。

非常感谢。

Java 数独 嵌套 for-loop

评论

2赞 Locke 10/3/2023
我的猜测是,迭代次数的计算方式可能存在问题,导致多个调用相加。
1赞 Hovercraft Full Of Eels 10/3/2023
@Locke:啊,我的错。谢谢。
2赞 Luatic 10/3/2023
背后的逻辑似乎是不正确的。如果一个数字出现两次,则该框无效。为此,您不需要 , 您需要 or ,所以我认为这应该是 ,否则将允许在同一行/列中具有相同的数字(尽管可以说如果您有另一个检查行和列的函数,这无关紧要)。grid[row + i][col + j] == grid[row + k][col + l] && i != k && j != li != kj != li != ki != lgrid[row + i][col + j] == grid[row + k][col + l] && (i != k || j != l)
0赞 user207421 10/3/2023
它正在运行 81 次。没有两条路可走。如果您不这么认为,请提供您的证据或理由。

答:

0赞 Locke 10/3/2023 #1

看起来您拥有的代码除了@Luatic指出的逻辑问题之外没有任何问题。您用于测量迭代次数的代码似乎可能是您所看到的问题的罪魁祸首。

如果您担心迭代次数和一般性能,可以尝试其他选项。例如,您可以切换到不重复比较的实现,例如仅执行 36 次迭代的实现。公平的警告,我没有执行任何基准测试。

boolean isValidBox(int row, int col) {
    for (int i = 0; i < 8; i++) {
        int iRow = (i / 3) + row;
        int iCol = (i % 3) + col;

        for (int j = i + 1; j < 9; j++) {
            int jRow = (j / 3) + row;
            int jCol = (j % 3) + col;

            if (grid[iRow][iCol] == grid[jRow][jCol]) {
                return false;
            }
        }
    }

    return true;
}

更好的解决方案是在更新单元格时仅检查重复项,因此您只需执行一次传递即可搜索单元格的新值。

0赞 Reilas 10/3/2023 #2

"...我正在尝试编写一种方法来验证数独“框”(在本例中为 3x3 并且位于整个数独拼图内部)中(换句话说,检查重复项或超出范围的值)。..."

作为参考,以下问题对此问题有一些很好的答案。
StackOverflow – Java 数独方块 3x3 检查有效性

"...我注意到......“i”变量以一种奇怪的方式递增。首次调用 for 循环时,'i' 为 0,然后下一个增量 'i' 也是 0,最后一个增量 'i' 为 2。不知道为什么会这样。请让我知道我做错了什么......”

按如下方式查看数独网格。

0 0 0 1 1 1 2 2 2
0 0 0 1 1 1 2 2 2
0 0 0 1 1 1 2 2 2
3 3 3 4 4 4 5 5 5
3 3 3 4 4 4 5 5 5
3 3 3 4 4 4 5 5 5
6 6 6 7 7 7 8 8 8
6 6 6 7 7 7 8 8 8
6 6 6 7 7 7 8 8 8

转换为封闭的“框”的左上角索引。
其中,您可以迭代 3 个步骤,3 次,以评估价值

boolean valid(int r, int c, int value) {
    Function<Integer, Integer> f
        = x -> switch (x) {
            case 0, 1, 2 -> 0;
            case 3, 4, 5 -> (x / 3) + 2;
            case 6, 7, 8 -> (x / 3) + 4;
            default -> -1;
        };
    r = f.apply(r);
    c = f.apply(c);
    for(int i = r, j; i < r + 3; i++)
        for(j = c; j < c + 3; j++)
            if(grid[i][j] == value) return false;
    return true;
}

下面是一个示例,使用维基百科中的网格。

double[][] grid = {
    { 5, 3, 0, 0, 7, 0, 0, 0, 0 },
    { 6, 0, 0, 1, 9, 5, 0, 0, 0 },
    { 0, 9, 8, 0, 0, 0, 0, 6, 0 },
    { 8, 0, 0, 0, 6, 0, 0, 0, 3 },
    { 4, 0, 0, 8, 0, 3, 0, 0, 1 },
    { 7, 0, 0, 0, 2, 0, 0, 0, 6 },
    { 0, 6, 0, 0, 0, 0, 2, 8, 0 },
    { 0, 0, 0, 4, 1, 9, 0, 0, 5 },
    { 0, 0, 0, 0, 8, 0, 0, 7, 9 }
};

输出

valid(0, 2, 4) = true
valid(0, 2, 5) = false