Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 我的回溯算法有什么问题?_Java_Algorithm_Sudoku_Backtracking - Fatal编程技术网

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吗