Java 我的回溯算法有什么问题?
我正在开发一个生成数独谜题的程序。我试图使用回溯算法来实现这一点,但我的程序不起作用。程序只是无限运行,永远不会返回解决方案。我不知道这只是一个小问题,还是我误解了如何编写回溯算法Java 我的回溯算法有什么问题?,java,algorithm,sudoku,backtracking,Java,Algorithm,Sudoku,Backtracking,我正在开发一个生成数独谜题的程序。我试图使用回溯算法来实现这一点,但我的程序不起作用。程序只是无限运行,永远不会返回解决方案。我不知道这只是一个小问题,还是我误解了如何编写回溯算法 package sudoku; import java.util.Random; public class Puzzle { // 9x9 puzzle private int puzzle[][] = new int[9][9]; // generate a completely s
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;
}
}
package数独;
导入java.util.Random;
公共类难题{
//9x9拼图
私有整数拼图[][]=新整数[9][9];
//生成一个完全解决的数独板
公共int[][]生成(){
Random gen=新的Random();
//将每个数字逐方块添加到电路板上
对于(int y=0;y<9;y++){
对于(int x=0;x<9;x++){
//生成随机数1-9
int num=gen.nextInt(9)+1;
整数计数=0;
布尔有效=假;
while(valid==false){
//检查号码是否有效
if(检查行(num,x)&检查列(num,y)
&&检查部分(数字、x、y)){
//把数字加到黑板上
拼图[x][y]=num;
//退出循环,进入下一个方块
有效=真;
}否则{
//试试下一个号码
如果(num==9){
num=1;
}否则{
num++;
}
//增加计数器。
计数++;
//若计数器达到9,那个么所有的数字都会被试过并且
//无效,请开始回溯
如果(计数=9){
//返回1平方米
如果(x==0){
x=8;
y--;
}否则{
x--;
}
//空方
拼图[x][y]=0;
//重置计数
计数=0;
}
}
}
}
}
回归难题;
}
//检查行的每个元素的num,如果找到num,则返回false
私有布尔校验行(int num,int row){
对于(int i=0;i<9;i++){
如果(拼图[行][i]==num){
返回false;
}
}
返回true;
}
//检查列中每个元素的num,如果找到num,则返回false
私有布尔校验列(int num,int col){
对于(int i=0;i<9;i++){
如果(拼图[i][col]==num){
返回false;
}
}
返回true;
}
//检查节的每个元素的num,如果找到num,则返回false
专用布尔检查部分(int num、int xPos、int yPos){
int[][]节=新int[3][3];
section=getSection(xPos、yPos);
对于(int i=0;i<3;i++){
对于(int j=0;j<3;j++){
如果(第[i][j]节)=num)
返回false;
}
}
返回true;
}
//返回给定坐标所在的3x3截面
私有int[][]getSection(int xPos,int yPos){
int[][]节=新int[3][3];
int xIndex=3*(xPos/3);
int-yIndex=3*(yPos/3);
对于(int i=0;i<3;i++){
对于(int j=0;j<3;j++){
[i][j]=拼图[xIndex+i][yIndex+j];
}
}
返回段;
}
}
可能会发生许多问题。我只举一个例子
回溯不起作用的主要原因是您没有进行回溯。您只返回树中的一个状态,回溯意味着您检查子树的所有可能性,然后(如果没有有效的子树)忽略该子树,不管它有多高
让我看看。你的方法是“把所有的数字排成一行,并希望平方完成。如果处理当前平方有错误,请清除前一个”
开始时没有问题,获取第一行不会导致错误。但是想想你是否已经完成了前8行,大概是这样的:
1
2
3
----
4
5
6
---
79
832|179|456
x
x
没有有效值。你的算法是做什么的?返回并尝试更改6!不出所料,最终将用6替换6,并再次尝试将值设置为x
我在互联网上找到的数独生成器没有回溯功能,只需采用有效的解决方案并对其执行一系列更改,所有更改都会带来有效的解决方案(有关更多详细信息,请咨询谷歌)
如果你想使用回溯,在每一步你都应该扫描数独是否仍然是可解的(或者至少,那不是“坏的”)。并且有一种不重复不可解组合的方法
此外,试图将数字按顺序排列似乎(这是一种观点)在一开始就增加了一个太强的约束。填充前两行很容易,但它会影响整个解决方案(注意填充第一行不会影响它!:-D)。我认为这不是解决问题的好方法;不幸的是,我没有为您提供解决方案,但我确实看到,一旦
count==9
,您就会更改x和y
,这不一定是好事。尽管如此,您并没有提供终止while(!valid)
循环的方法。您需要将valid
更改为true
以实际回溯;但是,这不会使该方法起作用。您使用什么编写程序?您使用的是文本edi吗