所以我认为我认为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)*/
}
}
}
}
}
答案 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);
}
}
}
}
}