如何修复此堆栈溢出错误?

时间:2009-12-17 06:08:52

标签: java recursion stack-overflow sudoku

所以我认为我认为java中的数独求解器的代码非常好,但我需要一些帮助。当我将它嵌入main方法时,它给了我一个堆栈溢出。问题是我的方法不知道如何扭转并修复它的错误。我需要一个布尔标志(一个与下面的代码中使用的标志不同,实际上最好工作)或其他东西让它知道什么时候应该转回来,什么时候它可以再次前进并继续解决游戏。感谢您提供任何帮助

public void play(int r, int c){//this method throws the StackOverflowError
    if(needAtLoc(r,c).size()==9){
        int num=1+generator.nextInt(9);
        setCell(r,c,num,this);

    if(c<8){
    System.out.println(this);///////////////
    play(r, c+1);
    }
    else{
    play(r+1, 0);
    }
}
else{
    if(needAtLoc(r,c).size()==0){//no possible moves THIS IS THE PROBLEM LINE!!!
    if(c>0){
        play(r, c-1);//play last cell, in column to left
    }
    else{
        if(r==0){
        play(r,c);//first square, so must play again (can't go back)
        }
        else{
        play(r-1, 8);/*first cell of row so must go to previous row and 
                   the end column*/
        }
    }
    }

    else{//if there are possible moves
    int num=needAtLoc(r,c).remove(generator.nextInt(needAtLoc(r,c).size()));
    setCell(r,c,num,this);//set the value of the cell
    System.out.println(this);//////////////
    if(r==8 && c==8){//the end of the cell has been reached so must end recursive call
        return;
    }
    else{
        if(c<8){
        play(r, c+1);//normal, next cell
        }
        else{
        play(r+1, 0);/*last cell in row so we go to next one 
                   in the first column ("return" button)*/
        }       
    }
    }
}
}

7 个答案:

答案 0 :(得分:23)

我不会为你解决这个问题,而是会就如何解决这个问题提出一些建议。 9个小时是充足的。

1)您的代码难以阅读。试着把它分开一点。为变量提供有意义的明确名称(这有助于您和其他人阅读您的代码)。您可能犯了一个简单的错误,清洁代码会使这些更容易被发现。尝试将其分解为更小的方法,因为这将使其更易读和更易于维护。

2)当你进行太多嵌套方法调用并且在递归代码中很常见时,会导致堆栈溢出(通常我相信)。因此,请使您的递归清晰。确保你有一个将终止的基础案例。

很抱歉不给你“答案”,但由于这听起来像是家庭作业,我认为学习如何自己解决这个问题更有价值。希望看起来很公平。

答案 1 :(得分:3)

我认为你的问题就在于:

if(r==0)
{
    play(r,c);//first square, so must play again (can't go back)
}

那是因为你似乎没有在这里修改任何状态而你传递了相同的值,这使你首先进入这一步。对我来说似乎是无限递归。

另外,请正确对齐您的代码,因为它在未对齐时太难以阅读,并且可能提供其他方法的一些线索。祝你好运!

答案 2 :(得分:1)

您的代码抛出了堆栈溢出异常,因为您从未达到结束递归的终止条件,或者至少通过读取代码看到您有递归终止条件并不明显。

您的代码结构不正确,因此您将很难调试它。尝试重新构建代码,它将帮助您重新思考问题。另外,请评论您的代码:)

答案 3 :(得分:1)

你递归地调用了游戏而没有返回,看起来你每次都在函数的顶部初始化一组新的变量。

尝试从递归部分中分割出初始化。您还需要一个明确的结束条件来结束递归,例如(if(isBoardFilled()== true))return。

同样对它进行构造,以便您向棋盘添加一个数字,根据约束进行测试,如果通过则添加另一个数字(递归)或回溯,删除最后一个数字并重试。

答案 4 :(得分:0)

我认为你是递归地调用play()。试着检查你的递归​​调用是否有停止条件。

答案 5 :(得分:0)

我同意汤姆的意见,但这是一个提示。

没有条件和return语句来结束递归调用。

答案 6 :(得分:0)

我已经设法变得更简洁,更清晰,但它仍然不会运行......我只需要超越边缘,我就可以自由回家了。我把这么多浪费的时间浪费在这个项目上:

public ArrayList<Integer> needAtLoc(int r, int c){
    int bc=c/3;//the column within the SudokuBoard
    int blc;

    /*The two posibilities for the column within each SudokuBlock:*/
    if(c>=0 && c<3) {
        blc=c;
    }
    else {
        blc=c%3;
    }
    int br=r/3; //the row within the SudokuBoard
    int blr;

    /*The two possiblities for the row within each SudokuBlock:*/
    if(r>=0 && r<3) {
        blr=r;
    } else {
        blr=r%3;
    }
    ArrayList<Integer> needR = new ArrayList<Integer>();
    needR=checkR(r);//
    needR.trimToSize();
    System.out.println(needR);//////////////
    ArrayList<Integer> needC=new ArrayList<Integer>();
    needC=checkC(c);
    needC.trimToSize();
    System.out.println(needC);/////////////
    ArrayList<Integer> needBl=new ArrayList<Integer>();
    needBl=this.board[br][bc].updateMissing(); //that method updates and returns an ArrayList
    needBl.trimToSize();
    ArrayList<Integer> poss=new ArrayList<Integer>();
    poss.clear();
    for(Integer e: needBl){
        if(needC.contains(e) && needR.contains(e)){
            poss.add(e);
        }
    }

    return poss;
}

//this method throws the StackOverflowError
public void play(int r, int c){
    int bc=c/3; //the column within the SudokuBoard
    int blc;
    /*The two posibilities for the column within each SudokuBlock:*/
    if(c>=0 && c<3) {
        blc=c;
    } else {
        blc=c%3;
    }
    int br=r/3; //the row within the SudokuBoard
    int blr;

    /*The two possiblities for the row within each SudokuBlock:*/
    if(r>=0 && r<3) {
        blr=r;
    } else {
        blr=r%3;
    }
    if(needAtLoc(r,c).size()==9){
        int num=1+generator.nextInt(9);
        this.board[br][bc].setValue(blr, blc, num);
        if(c<8){
            System.out.println(this);///////////////
            play(r, c+1);
        } else{
            play(r+1, 0);
        }
    } else{
        if(needAtLoc(r,c).size()==0){ //no possible moves
            if(c>0){
                bc=(c-1)/3;
                if(c>0 && c<4) {
                    blc=c-1;
                } else {
                blc = (c-1) % 3;
            }
        this.board[br][bc].setValue(blr, blc, 0);
        play(r, c-1);
    }
    else{
        blc=0;
        bc=0;
        if(r==0){
        blr=0;
        br=0;
        this.board[br][bc].setValue(blr, blc, 0);
        play(r,c);
        }
        else{
        br=(r-1)/3;
        if(r>0 && r<4) {blr=r-1;}
        else {blr=(r-1)%3;}
        this.board[br][bc].setValue(blr, blc, 0);
        play(r-1, 8);
        }
    }
    }

    else{//if there are possible moves
        int num=needAtLoc(r,c).remove(generator.nextInt(needAtLoc(r,c).size()));
        this.board[br][bc].setValue(blr, blc, num);
        System.out.println(this);//////////////
        if(r==8 && c==8){
        return;
        }
        else{
        if(c<8){
            play(r, c+1);
        }
        else{
            play(r+1, 0);
        }       
        }
    }
    }
}