Java 如何修复此堆栈溢出错误?
所以我有一个我认为非常好的java数独解算器代码,但是我需要一些关于这个方法的帮助。当我将它嵌入主方法时,它会给我一个堆栈溢出。问题是,我的方法不知道如何扭转局面并纠正错误。我需要一个布尔标志(与下面代码中使用的标志不同,它实际上更好地工作)或其他东西,让它知道何时应该返回,何时可以再次前进并继续解决游戏。谢谢你能给我的帮助Java 如何修复此堆栈溢出错误?,java,recursion,stack-overflow,sudoku,Java,Recursion,Stack Overflow,Sudoku,所以我有一个我认为非常好的java数独解算器代码,但是我需要一些关于这个方法的帮助。当我将它嵌入主方法时,它会给我一个堆栈溢出。问题是,我的方法不知道如何扭转局面并纠正错误。我需要一个布尔标志(与下面代码中使用的标志不同,它实际上更好地工作)或其他东西,让它知道何时应该返回,何时可以再次前进并继续解决游戏。谢谢你能给我的帮助 public void play(int r, int c){//this method throws the StackOverflowError if(need
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)*/
}
}
}
}
}
public void play(int r,int c){//此方法抛出StackOverflower错误
if(needAtLoc(r,c).size()=9){
int num=1+生成器.nextInt(9);
setCell(r,c,num,this);
如果(c0){
播放(r,c-1);//播放左侧列中的最后一个单元格
}
否则{
如果(r==0){
播放(r,c);//第一个方块,所以必须再次播放(不能返回)
}
否则{
播放(r-1,8);/*行的第一个单元格,因此必须转到前一行并
尾柱*/
}
}
}
否则{//如果有可能的移动
int num=needAtLoc(r,c).remove(generator.nextInt(needAtLoc(r,c).size());
setCell(r,c,num,this);//设置单元格的值
System.out.println(本文件)//////////////
如果(r==8&&c==8){//已到达单元格的末尾,则必须结束递归调用
返回;
}
否则{
如果(c不是为你解决这个问题,我会就如何解决这个问题提出一些建议。9小时就足够了
1) 您的代码很难阅读。请尝试将其隔开一点。为变量提供清晰的有意义的名称(这有助于您和其他人阅读您的代码)。您可能犯了一个简单的错误,干净的代码将使这些错误更容易被发现。请尝试将其拆分为更小的方法,因为这将使其更具可读性和可维护性
2) 堆栈溢出是由嵌套方法调用过多造成的(通常我认为),这在递归代码中很常见。因此,请明确递归。确保有一个将终止的基本情况
很抱歉没有给你“答案”,但因为这听起来像是家庭作业,我认为学习如何自己解决这个问题更有价值。希望这看起来公平。我想你是在说play()递归。尝试检查您的递归调用是否有停止条件。您的代码正在抛出堆栈溢出异常,因为您从未达到终止递归的终止条件,或者至少通过读取代码看不出您有递归终止条件
你的代码结构不好,因此你将很难调试它。尝试重新构造你的代码,这将帮助你重新思考问题。另外,请评论你的代码:)我同意Tom的观点,但这里有一个提示
没有条件和return语句来结束递归调用。您正在递归调用play,但从未返回,并且每次在函数顶部初始化一组新的变量
尝试从递归部分分离初始化。您还需要一个明确的结束条件来结束递归,例如:(if(isBoardFilled()==true))返回
还要对其进行结构设计,以便在电路板上添加一个数字,对照约束进行测试,如果通过,则添加另一个数字(递归)或者通过删除最后一个数字来回溯,然后再试一次。我已经设法变得更简洁、更清晰,但它仍然无法运行……我只需要一次突破,我就可以自由回家了。我在这个项目中浪费了太多时间:
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);
}
}
}
}
}
public ArrayList needAtLoc(int r,int c){
int bc=c/3;//数独板中的列
int blc;
/*每个Sudoku区块内柱的两种可能性:*/
如果(c>=0&&c=0&&r=0&&c=0&&r0&&c0&&r,我认为你的问题在于:
if(r==0)
{
play(r,c);//first square, so must play again (can't go back)
}
这是因为你似乎没有修改这里的任何状态,你在其中传递了相同的值,这使你首先进入了这一步。对我来说,似乎是无限递归
另外,请正确对齐您的代码,因为当代码未对齐时很难阅读,并且可能会提供其他方法的一些线索。祝您好运!您应该告诉人们这是Java。顺便说一句,这是很多代码,请考虑将其分解为函数。您确定解决数独问题适合堆栈吗?数独代码有期限。呵呵mework?除非T-9hrs是终端型号的名称;)@Kobi-我很确定它会被放在堆栈上。我以前做过几次这种练习。你在试图发现错误之前试过纠正缩进吗?+1因为你不是一个启用者,为别人做工作:)它更少的是家庭工作,更多的是一个项目。是的,我会评论,当我被扔过去的时候,我倾向于顺其自然一个问题。我在这门课上已经上了14个多小时了,我非常沮丧。我只是在一堵砖墙前。我知道程序哪里出了问题。它无法返回并修复错误的数字选择。它将被卡在一个单元格中并继续循环,这就是为什么内存会被填满。我只是需要一种方法,或者至少是在正确的方向上轻轻推一下我真的是一个好学生,只是我的教授从来没有教过我们递归,但希望我们使用它。我发现,有时你可以通过重新开始获得很多(但取决于你)我认为递归调用应该只需要发生一次,如果使用一个索引变量而不是两个(r
和c
)会更简单.使用一个,然后从中计算出r
和c
。递归方法通常采用以下形式:我完成了吗?如果是,则返回。如果不做某事,则递归,可能做其他事情并返回。尽量使其简单-否则你会继续被咬。谢谢,你们真的很有帮助,我希望我没有陷入这样的困境因为这将是一个令人愉快的开悟的前妻