简体   繁体   中英

Recursive Backtracking for puzzle solver in java

Just get my hand on coding and it is very addicted. So I try new challenge in making puzzle solver. I am getting so close to finish it but get stuck.

There are 2 main methods: puzzleSolver and check

I have tested check method with all cases and it is working very well.

So the only problem is solve method and I dont know whats wrong with it.

Please look at my code and help me out.

Very appreciate.

I will explain the rules below.

RULES:

1.No 3 consecutive values (1 and 2) in each row and column.

2.Each row and column contains the same amount of values.

If grid[6][6]. Each row and column will have 3 of 1s and 3 of 2s.

But cannot have 3 of 1s or 2s next each other.

Example:

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

This is my input grid:

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 } };

It works in some cases but not all and I dont know why

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

Here is my code

Solve method will run all row and column and uses check method to decide which value to be placed

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

I have check method to detect any violations and it work well in any cases. I know there is something wrong in solve method but cannot find it.

In, pseudocode, your solution reads like:

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

Walkthrough what happens if you have all zeroes in you cells. The first cell will be given value 1, then 2, neither of which solve the whole grid (because there are still zeroes). So it moves the second cell and so on throughout the grid, leaving each cell with value 2. It obviously won't find a solution in that situation.

Your first issue here is that you actually aren't doing any recursion or backtracking.

A correct solution will likely look like:

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)

That's recursive (because it calls itself) and backtracking because if it can't find a solution it returns to a previous position (above it in the call stack) and tries a new value.

So an actual solution might look something like:

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);
            }
        }
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM