java - java中的谜题求解器的递归回溯

标签 java

只要我开始编码,就会非常上瘾。所以我尝试制作解谜游戏的新挑战。我快要完成它了,但卡住了。

主要有2个方法:puzzleSolver和check

我已经在所有情况下测试了检查方法,并且效果很好。

所以唯一的问题是解决方法,我不知道它出了什么问题。

请查看我的代码并帮助我。

非常感谢。

我将解释下面的规则。

规则:

1.每行每列中没有 3 个连续值(1 和 2)。

2.每行和每列包含相同数量的值。

如果网格[6][6]。每行和每列将有 3 个 1 和 3 个 2。

但不能有 3 个 1 或 2 彼此相邻。

示例:

grid[2][2]
0 1
1 0
Solution:
2 1
1 2

grid[2][2]
1 1
0 0
Unsolvable
It violated rule number 2. 
grid[4][4]
[0, 2, 2, 1]
[0, 2, 1, 2]
[2, 1, 0, 1]
[2, 0, 0, 0]
solution: 
[1, 2, 2, 1]
[1, 2, 1, 2]
[2, 1, 2, 1]
[2, 1, 1, 2]

grid[4][4]
[0, 2, 2, 2] <- violated rule number 2
[0, 2, 1, 2]
[2, 1, 0, 1]
[2, 0, 0, 0]
Unsolvable

grid[6][6]
[0, 0, 1, 1, 1, 0] <- violated rule #1
[0, 0, 0, 1, 0, 0]
[2, 2, 2, 0, 0, 0] <-violated rule #1
[0, 0, 0, 1, 0, 0]
[0, 1, 2, 0, 0, 0]
[0, 2, 0, 1, 0, 0]
Unsolvable

这是我的输入网格:

public static void main(String[] args) {
        int[][] grid = { { 0, 1 }, { 1, 0 } };
        int[][] grid1 = { { 0, 2, 2, 1 }, { 0, 2, 1, 2 }, { 2, 1, 0, 1 }, { 2, 0, 0, 0 } };
        int[][] grid2 = { { 0, 2, 2, 0 }, { 0, 0, 0, 0 }, { 0, 2, 0, 0 }, { 0, 0, 0, 1 } };
        int[][] grid3 = { { 0, 0, 1, 0, 2, 2 }, { 0, 0, 2, 0, 0, 0 }, { 0, 0, 1, 0, 0, 0 }, { 0, 0, 0, 2, 0, 0 },
                { 2, 0, 1, 0, 0, 0 }, { 0, 0, 2, 1, 2, 0 } };

它在某些情况下有效,但并非全部,我不知道为什么

OUTPUT
Fail to find solution
[0, 2, 2, 0]
[0, 0, 0, 0]
[0, 2, 0, 0]
[0, 0, 0, 1]
false
Solution should have:
1, 2, 2, 1
2, 1, 1, 2
1, 2, 1, 2
2, 1, 2, 1

这是我的代码

Solve 方法将运行所有行和列,并使用 check 方法来决定放置哪个值

public static boolean puzzleSolve(int[][] grid) {

        for (int row = 0; row < grid.length; row++) {
            // column start from 0 and increasing as going down
            for (int col = 0; col < grid.length; col++) {
                // start at 0, 0
                if (grid[row][col] == 0) { // if value =0, will be replaced with n
                    for (int n = 1; n < 3; n++) { // n =1 or n=2
                        grid[row][col] = n; // place n=1 then check condition
                        if (check(grid)) {
                            grid[row][col] = n;// if true, replace 0 with n

                            if (solve(grid)) { // check whole grid if violated rules
                                return true;
                            }
                        }
                    }
                    // System.out.println("No solution");
                    return false; // fail in replacing
                }
            }
        }
        // print out solved grid if succeed
        System.out.println("solution: ");
        for (int i = 0; i < grid.length; i++) {
            System.out.println(Arrays.toString(grid[i]));
        }
        return true; // success
    }
//end code

我有检查方法来检测任何违规行为,并且在任何情况下都运行良好。 我知道解决方法有问题,但找不到它。

最佳答案

在伪代码中,您的解决方案如下所示:

for each cell with value zero
    for each allowed value
        place value in cell
        check if it's a solution

演练如果单元格中全部为零会发生什么情况。第一个单元格将被赋予值 1,然后是 2,这两个值都不能解决整个网格(因为仍然有零)。因此,它会在整个网格中移动第二个单元格,依此类推,使每个单元格的值均为 2。在这种情况下,它显然找不到解决方案。

这里的第一个问题是您实际上没有进行任何递归或回溯。

正确的解决方案可能如下所示:

solve (grid, position):
    if position is past end and grid is solved
        yah!
    else
        for each allowed value
            place value in position on grid
            call solve(grid, next position)

这是递归(因为它调用自身)和回溯,因为如果它找不到解决方案,它会返回到先前的位置(在调用堆栈中位于其上方)并尝试新值。

因此,实际的解决方案可能类似于:

private void findSolutions(int[][] grid, int col, int row) {
    if (row == grid.length && isSolved(grid)) {
        printSolution(grid);
    } else {
        for (int v = 1; v <= 2; v++) {
            grid[row][col] = v;
            if (col == grid[row].length) {
                findSolutions(grid, 0, row + 1);
            } else {
                findSolutions(grid, col + 1, row + 1);
            }
        }
    }
}

关于java - java中的谜题求解器的递归回溯,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61720883/

相关文章:

java - 如何使用hibernate查询具有嵌套对象集合的对象

java - 安装河马 CMS : NullPointerException with essentials webapp

java - 国家边界坐标数据

Java 连接被拒绝

java - android中可扩展 ListView 中的图像图标

java - java 中数据计数的最佳实践

Java String "1603"到 float 16.03

java - 如何在 MAC 上使用 Java 为 iPhone 自动化设置 Appium?

Java 正则表达式接受除所有破折号之外的任何字符串

java - 禁用库的日志输出