我正在制作一个生成数独谜题的程序。我试图使用回溯算法来执行此操作,但我的程序无法正常工作。该程序只是无限运行,永远不会返回解决方案。我不知道它只是一个小问题,还是我误解了如何编写回溯算法。
package sudoku;
import java.util.Random;
public class Puzzle {
// 9x9 puzzle
private int puzzle[][] = new int[9][9];
// generate a completely solved sudoku board
public int[][] generate() {
Random gen = new Random();
// add each number to the board square by square
for (int y = 0; y < 9; y++) {
for (int x = 0; x < 9; x++) {
// generate random number 1-9
int num = gen.nextInt(9) + 1;
int count = 0;
boolean valid = false;
while (valid == false) {
// check if number is valid
if (checkRow(num, x) && checkCol(num, y)
&& checkSection(num, x, y)) {
// add number to the board
puzzle[x][y] = num;
// exit loop, move on to next square
valid = true;
} else {
// try next number
if (num == 9) {
num = 1;
} else {
num++;
}
// increase counter.
count++;
// if counter reached 9, then all numbers were tried and
// none were valid, begin backtracking
if (count == 9) {
// go back 1 square
if (x == 0) {
x = 8;
y--;
} else {
x--;
}
// empty square
puzzle[x][y] = 0;
//reset count
count = 0;
}
}
}
}
}
return puzzle;
}
// check each element of the row for num, if num is found return false
private boolean checkRow(int num, int row) {
for (int i = 0; i < 9; i++) {
if (puzzle[row][i] == num) {
return false;
}
}
return true;
}
// check each element of the column for num, if num is found return false
private boolean checkCol(int num, int col) {
for (int i = 0; i < 9; i++) {
if (puzzle[i][col] == num) {
return false;
}
}
return true;
}
// check each element of the section for num, if num is found return false
private boolean checkSection(int num, int xPos, int yPos) {
int[][] section = new int[3][3];
section = getSection(xPos, yPos);
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
if (section[i][j] == num)
return false;
}
}
return true;
}
// return the 3x3 section the given coordinates are in
private int[][] getSection(int xPos, int yPos) {
int[][] section = new int[3][3];
int xIndex = 3 * (xPos / 3);
int yIndex = 3 * (yPos / 3);
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
section[i][j] = puzzle[xIndex + i][yIndex + j];
}
}
return section;
}
}
答案 0 :(得分:1)
可能会发生许多问题。我将举一个例子。
回溯不起作用的主要原因是因为你没有做回溯。你只返回树中的一个状态,回溯意味着你检查一个子树的所有可能性然后(如果没有有效)你忽略那个子树,无论它有多高。
让我们看看。你的方法是&#34;将所有数字排成一行,并希望广场完成。如果处理当前方块时出错,请清除前一个方格&#34;。
一开始没问题,获取第一行不会导致错误。但想想你完成前8行的可能性,有类似的东西:
1
2
3
----
4
5
6
---
79
832|179|456
x
x
没有有效值。你的算法有什么作用?回去尝试改变6!不出所料,这将以6替换6结束,并再次尝试将值设置为x
。
我在互联网上找到的Sudokus生成器没有回溯,只需采用有效的解决方案并对其进行一系列更改,所有更改都会带来有效的解决方案(有关详细信息,请咨询谷歌)。
如果你想使用回溯,你应该在每一步扫描数据是否仍然可以解决(或者至少,那不是&#34;破坏&#34;)。并且有办法不重复不可解决的组合。
此外,试图按顺序排列数字似乎(这是一种观点)在开始时添加一个过于强大的约束。填充前两行很容易,但它会调整整个解决方案(注意填充第一行不会影响它!:-D)。
答案 1 :(得分:0)
我不认为这是解决问题的好方法;遗憾的是,我没有为你提供解决方案,但我确实看到count == 9
,你改变x and y
,这不一定是好事。但是,您没有提供终止while(!valid)
循环的方法。您需要将valid
更改为true
才能实际回溯;但是,这不会使该方法有效。