仍在研究我的数独求解器,我又遇到了一些麻烦。我已经让数独求解器工作了,但是每当我尝试求解一个真正“硬”的数独板时,我的求解器都会告诉我,由于堆栈溢出错误,没有可能的解决方案。是的,我知道这些板确实有解决方案。
我正在使用蛮力算法——我从第一格开始(或 [0][0],如果您愿意)并插入第一个合法值。然后我对下一个方块进行递归调用,依此类推。如果我的函数没有遍历整个棋盘,并且发现没有可能的合法值,它会移动到前一个方块并尝试增加那里的值。如果失败,它会向后移动。如果它在没有可能的解决方案的情况下结束于第一格,它就会退出。
我承认我的代码并不漂亮,而且可能非常低效,但请记住,我是一名一年级学生,正在努力做到最好。我不介意评论如何使我的代码生效:)
对于没有最终预定义数字的正方形,这里是求解器函数:
public void fillRemainderOfBoard(Square sender){
try {
while(true){
if(currentPos > boardDimension){
if(previous != null){
this.setNumrep(-1);
this.setCurrentPos(1);
previous.setCurrentPos(previous.getCurrentPos()+1);
previous.fillRemainderOfBoard(this);
return;
} else if(sender == this){
this.setCurrentPos(1);
} else {
break;
}
}
if((thisBox.hasNumber(currentPos)) || (thisRow.hasNumber(currentPos)) || (thisColumn.hasNumber(currentPos))){
currentPos++;
} else {
this.setNumrep(currentPos);
currentPos++;
break;
}
}
if(this != last){
next.setNumrep(-1);
next.fillRemainderOfBoard(this);
} else {
return;
}
} catch (StackOverflowError e){
return;
}
}
在我的代码中,numrep 值是方块在板上表示的值。currentPos 变量是一个计数器,从 1 开始并递增,直到达到正方形表示的合法值。
对于具有预定义数字的正方形,这是相同的功能:
public void fillRemainderOfBoard(Square sender){
if((sender.equals(this) || sender.equals(previous)) && this != last){
System.out.println(next);
next.fillRemainderOfBoard(this);
} else if (sender.equals(next) && this != first) {
previous.fillRemainderOfBoard(this);
} else {
System.out.println("No possible solutions for this board.");
}
}
现在,我的问题是,就像我说的,这个函数确实很好地解决了数独问题。容易的。棘手的数独,比如有许多预定义数字但只有一个解决方案的数独,只会让我的程序进入堆栈溢出并告诉我没有可能的解决方案。我假设这表明我在内存管理方面遗漏了一些东西,或者程序复制了我在递归函数中调用的对象,但我不知道如何修复它们。
任何帮助是极大的赞赏!也可以随意选择我的代码;我还在学习(哦,我们不是总是这样吗?)。
__ _ __ _ __ _ __ _ __ _ ____编辑_ __ _ __ _ __ _ __ _ __ _
感谢 Piotr 提出了回溯的好主意,我重写了我的代码。但是,我仍然无法解决任何数独问题。即使是空棋盘,它也会到达 39 号方格,然后一直返回 false。这是我当前的代码:
public boolean fillInnRemainingOfBoard(Square sender){
if(this instanceof SquarePredef && next != null){
return next.fillInnRemainingOfBoard(this);
} else if (this instanceof SquarePredef && next == null){
return true;
}
if(this instanceof SquareNoPredef){
currentPos = 1;
if(next != null){
System.out.println(this.index);
for(; currentPos <= boardDimension; currentPos++){
if((thisBox.hasNumber(currentPos)) || (thisRow.hasNumber(currentPos)) || (thisColumn.hasNumber(currentPos))){
continue;
} else {
System.out.println("Box has " + currentPos + "? " + thisBox.hasNumber(currentPos));
this.setNumrep(currentPos);
System.out.println("Got here, square " + index + " i: " + numrep);
}
if(next != null && next.fillInnRemainingOfBoard(this)){
System.out.println("Returnerer true");
return true;
} else {
}
}
}
if(next == null){
return true;
}
}
System.out.println("Returning false. Square: " + index + " currentPos: " + currentPos);
return false;
}
我不得不使事情复杂一点,因为我需要检查当前对象是否是最后一个。因此额外的 if 测试。哦,我使用 boardDimension 的原因是因为这个数独求解器可以解决任何数独问题——不仅仅是那些 9 x 9 数独 :)
你能发现我的错误吗?任何帮助表示赞赏!