[英]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.