[英]How do I fix this stack overflow error?
所以我認為我認為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)*/
}
}
}
}
}
我不會為你解決這個問題,而是會就如何解決這個問題提出一些建議。 9個小時是充足的。
1)您的代碼難以閱讀。 試着把它分開一點。 為變量提供有意義的明確名稱(這有助於您和其他人閱讀您的代碼)。 您可能犯了一個簡單的錯誤,清潔代碼會使這些更容易被發現。 嘗試將其分解為更小的方法,因為這將使其更具可讀性和可維護性。
2)當您進行太多嵌套方法調用並且在遞歸代碼中很常見時,會導致堆棧溢出(通常我相信)。 因此,請使您的遞歸清晰。 確保您有一個將終止的基本案例。
很抱歉不給你“答案”,但由於這聽起來像是家庭作業,我認為學習如何自己解決這個問題更有價值。 希望看起來很公平。
我認為你的問題就在於:
if(r==0)
{
play(r,c);//first square, so must play again (can't go back)
}
那是因為你似乎沒有在這里修改任何狀態而你傳遞了相同的值,這使你首先進入這一步。 對我來說似乎是無限遞歸。
另外,請正確對齊您的代碼,因為它在未對齊時太難以閱讀,並且可能提供其他方法的一些線索。 祝好運!
您的代碼正在拋出堆棧溢出異常,因為您從未達到結束遞歸的終止條件,或者至少通過讀取代碼看到您有遞歸終止條件並不明顯。
你的代碼結構不好,因此你很難調試它。 嘗試重新構建代碼,它將幫助您重新思考問題。 另外,請評論你的代碼:)
你遞歸地調用play而不返回,看起來你每次都在函數的頂部初始化一組新的變量。
嘗試從遞歸部分中分離出初始化。 您還需要一個明確的結束條件來結束遞歸,例如(if(isBoardFilled()== true))return。
還要對它進行結構化,以便在板上添加一個數字,根據約束進行測試,如果通過,則通過刪除最后一個數字添加另一個數字(遞歸)或回溯,然后重試。
我認為你是遞歸地調用play()。試着檢查你的遞歸調用是否有停止條件。
我同意湯姆的意見,但這是一個提示。
沒有條件和return語句來結束遞歸調用。
我已經設法變得更簡潔,更清晰,但它仍然無法運行......我只是需要一個超越邊緣,我在家里自由。 我把這么多浪費的時間浪費在這個項目上:
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);
}
}
}
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.