簡體   English   中英

java 中解謎器的遞歸回溯

[英]Recursive Backtracking for puzzle solver in java

只要讓我開始編碼,它就會非常上癮。 所以我嘗試制作解謎者的新挑戰。 我越來越接近完成它,但被卡住了。

有兩種主要方法: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)

這是遞歸的(因為它調用自己)和回溯,因為如果它找不到解決方案,它會返回到以前的 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);
            }
        }
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM