我的循环永无止境
My loop never ends
我的程序有问题,它应该解决数独并在完成后打印,但问题是,程序看起来永远不会结束,在打印解决的数独后出现错误。
这是程序正在执行的循环:
它也不会打印字段,如果我在开始时删除 System.out.print(f+"\n");
它只会打印错误。
代码:
public class Sudoku {
public static void main(String[] args) throws SolvedException {
Field field = new Field();
field.fromFile("test1.txt");
SudokuSolver solver = new SudokuSolver();
solve(field, 0, 0, solver);
System.out.println(field);
}
public static void solve(Field f, int i, int j, SudokuSolver solver) {
System.out.print(f+"\n");
if ( j >= Field.SIZE) {
//we are done (return true now!)
solver.done=true;
return;
}
if (f.isEmpty(i, j)) {
for (int val = 1; val <=9; val++) {
if (f.tryValue(val, i, j)){
if (j>=Field.SIZE-1){
solve (f, i+1, 0, solver);
if ( solver.done ) {
// This halts the loop here:
return;
}
f.clear(i, j);
} else {
solve(f,i,j+1, solver);
if ( solver.done ) {
// This halts the loop here:
return;
}
f.clear(i, j);
}
}
}
} else if (j>=Field.SIZE-1) {
solve(f,i+1,0, solver);
} else {
solve(f,i,j+1, solver);
}
}
}
数独求解器
public class SudokuSolver{
/* Set true when the solve is done */
public boolean done;
}
错误:
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 9
at Field.isEmpty(Field.java:101)
at Sudoku.solve(Sudoku.java:30)
at Sudoku.solve(Sudoku.java:38)
at Sudoku.solve(Sudoku.java:50)
at Sudoku.solve(Sudoku.java:71)
at Sudoku.solve(Sudoku.java:71)
at Sudoku.solve(Sudoku.java:50)
at Sudoku.solve(Sudoku.java:50)
at Sudoku.solve(Sudoku.java:71)
at Sudoku.solve(Sudoku.java:50)
at Sudoku.solve(Sudoku.java:50)
at Sudoku.solve(Sudoku.java:67)
at Sudoku.solve(Sudoku.java:71)
at Sudoku.solve(Sudoku.java:50)
at Sudoku.solve(Sudoku.java:50)
at Sudoku.solve(Sudoku.java:71)
at Sudoku.solve(Sudoku.java:50)
at Sudoku.solve(Sudoku.java:50)
at Sudoku.solve(Sudoku.java:50)
at Sudoku.solve(Sudoku.java:50)
at Sudoku.solve(Sudoku.java:38)
at Sudoku.solve(Sudoku.java:71)
at Sudoku.solve(Sudoku.java:50)
at Sudoku.solve(Sudoku.java:50)
at Sudoku.solve(Sudoku.java:71)
at Sudoku.solve(Sudoku.java:71)
at Sudoku.solve(Sudoku.java:50)
at Sudoku.solve(Sudoku.java:71)
at Sudoku.solve(Sudoku.java:71)
at Sudoku.solve(Sudoku.java:38)
at Sudoku.solve(Sudoku.java:50)
at Sudoku.solve(Sudoku.java:71)
at Sudoku.solve(Sudoku.java:50)
at Sudoku.solve(Sudoku.java:71)
at Sudoku.solve(Sudoku.java:71)
at Sudoku.solve(Sudoku.java:50)
at Sudoku.solve(Sudoku.java:71)
at Sudoku.solve(Sudoku.java:71)
at Sudoku.solve(Sudoku.java:38)
at Sudoku.solve(Sudoku.java:50)
at Sudoku.solve(Sudoku.java:71)
at Sudoku.solve(Sudoku.java:71)
at Sudoku.solve(Sudoku.java:50)
at Sudoku.solve(Sudoku.java:71)
at Sudoku.solve(Sudoku.java:71)
at Sudoku.solve(Sudoku.java:50)
at Sudoku.solve(Sudoku.java:50)
at Sudoku.solve(Sudoku.java:67)
at Sudoku.solve(Sudoku.java:71)
at Sudoku.solve(Sudoku.java:50)
at Sudoku.solve(Sudoku.java:71)
at Sudoku.solve(Sudoku.java:71)
at Sudoku.solve(Sudoku.java:50)
at Sudoku.solve(Sudoku.java:71)
at Sudoku.solve(Sudoku.java:50)
at Sudoku.solve(Sudoku.java:50)
at Sudoku.solve(Sudoku.java:67)
at Sudoku.solve(Sudoku.java:71)
at Sudoku.solve(Sudoku.java:50)
at Sudoku.solve(Sudoku.java:71)
at Sudoku.solve(Sudoku.java:71)
at Sudoku.solve(Sudoku.java:50)
at Sudoku.solve(Sudoku.java:50)
at Sudoku.solve(Sudoku.java:71)
at Sudoku.solve(Sudoku.java:50)
at Sudoku.solve(Sudoku.java:38)
at Sudoku.solve(Sudoku.java:50)
at Sudoku.solve(Sudoku.java:50)
at Sudoku.solve(Sudoku.java:50)
at Sudoku.solve(Sudoku.java:71)
at Sudoku.solve(Sudoku.java:50)
at Sudoku.solve(Sudoku.java:50)
at Sudoku.solve(Sudoku.java:71)
at Sudoku.solve(Sudoku.java:71)
at Sudoku.solve(Sudoku.java:38)
at Sudoku.solve(Sudoku.java:50)
at Sudoku.solve(Sudoku.java:71)
at Sudoku.solve(Sudoku.java:50)
at Sudoku.solve(Sudoku.java:50)
at Sudoku.solve(Sudoku.java:71)
at Sudoku.solve(Sudoku.java:71)
at Sudoku.solve(Sudoku.java:50)
at Sudoku.solve(Sudoku.java:50)
at Sudoku.main(Sudoku.java:9)
有什么想法可以停止循环并打印正确的字段吗? System.out.println(field)
而不是解决方法中的这个?
某处试图访问不存在的数组上层元素。尝试调试并找到。
可能 val 是要查找的关键。
我假设
for (int val = 1; val <=9; val++)
应该
for (int val = 1; val <9; val++)
永不终止的递归
(在这种情况下,它会在出错时终止)。
你的这部分代码需要实际做一些事情来表明它已经完成:
if ( j >= Field.SIZE) {
//we are done
}
否则该循环只是继续进行,没有意识到它应该停止(缩短):
for (int val = 1; val <=9; val++) {
...
solve (f, i+1, 0); // Maybe this call is 'done', but this loop will keep going
...
}
因此,基于 throws SolvedException
你的代码应该在那里抛出异常:
if ( j >= Field.SIZE) {
//we are done
throw new SolvedException();
}
但这是一个坏主意。例外情况是 not 用于控制代码流 - 它们用于 completely unexpected situations.
表示完成
相反,我们需要通过某种方式知道代码何时达到 'done' 条件。在经典递归中,这是通过 returning 某些东西来执行的。正如我们只想知道它是否完成,bool
处理得很好:
// Type changed to bool, removed throws:
public static bool solve(Field f, int i, int j) {
System.out.print(f+"\n");
if ( j >= Field.SIZE) {
//we are done (return true now!)
return true;
}
if (f.isEmpty(i, j)) {
for (int val = 1; val <=9; val++) {
if (f.tryValue(val, i, j)){
if (j>=Field.SIZE-1){
if( solve (f, i+1, 0) ){
// This halts the loop here:
return true;
}
f.clear(i, j);
} else {
if( solve(f,i,j+1) ){
// This halts the loop here:
return true;
}
f.clear(i, j);
}
}
}
} else if (j>=Field.SIZE-1) {
// (Side note: This one is tail recursion)
return solve(f,i+1,0);
}
// (Side note: This one is tail recursion)
return solve(f,i,j+1);
}
在被调用者中,你还有这个:
try {
solve(field, 0, 0);
}
catch (SolvedException e) { }
你也会换成:
if( solve(field, 0, 0) ){
// It was solved!
}
改为返回 void
您提到您仍然想要 return void
。好的,所以,我们需要在其他地方跟踪 'done' 状态 - 例如在我们称之为 SudokuSolver
:
的某个对象中
public class SudokuSolver{
/* Set true when the solve is done */
public bool done;
}
使用它使代码看起来更像这样:
// Type changed to void, added our solver arg:
public static void solve(Field f, int i, int j, SudokuSolver solver) {
System.out.print(f+"\n");
if ( j >= Field.SIZE) {
//we are done (return true now!)
solver.done=true;
return;
}
if (f.isEmpty(i, j)) {
for (int val = 1; val <=9; val++) {
if (f.tryValue(val, i, j)){
if (j>=Field.SIZE-1){
solve (f, i+1, 0, solver);
if ( solver.done ) {
// This halts the loop here:
return;
}
f.clear(i, j);
} else {
solve(f,i,j+1, solver);
if ( solver.done ) {
// This halts the loop here:
return;
}
f.clear(i, j);
}
}
}
} else if (j>=Field.SIZE-1) {
solve(f,i+1,0, solver);
} else {
solve(f,i,j+1, solver);
}
}
呼叫站点现在看起来像这样:
SudokuSolver solver=new SudokuSolver();
solve(field, 0, 0, solver);
if ( solver.done ) {
// It was solved!
}
我的程序有问题,它应该解决数独并在完成后打印,但问题是,程序看起来永远不会结束,在打印解决的数独后出现错误。
这是程序正在执行的循环:
它也不会打印字段,如果我在开始时删除 System.out.print(f+"\n");
它只会打印错误。
代码:
public class Sudoku {
public static void main(String[] args) throws SolvedException {
Field field = new Field();
field.fromFile("test1.txt");
SudokuSolver solver = new SudokuSolver();
solve(field, 0, 0, solver);
System.out.println(field);
}
public static void solve(Field f, int i, int j, SudokuSolver solver) {
System.out.print(f+"\n");
if ( j >= Field.SIZE) {
//we are done (return true now!)
solver.done=true;
return;
}
if (f.isEmpty(i, j)) {
for (int val = 1; val <=9; val++) {
if (f.tryValue(val, i, j)){
if (j>=Field.SIZE-1){
solve (f, i+1, 0, solver);
if ( solver.done ) {
// This halts the loop here:
return;
}
f.clear(i, j);
} else {
solve(f,i,j+1, solver);
if ( solver.done ) {
// This halts the loop here:
return;
}
f.clear(i, j);
}
}
}
} else if (j>=Field.SIZE-1) {
solve(f,i+1,0, solver);
} else {
solve(f,i,j+1, solver);
}
}
}
数独求解器
public class SudokuSolver{
/* Set true when the solve is done */
public boolean done;
}
错误:
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 9
at Field.isEmpty(Field.java:101)
at Sudoku.solve(Sudoku.java:30)
at Sudoku.solve(Sudoku.java:38)
at Sudoku.solve(Sudoku.java:50)
at Sudoku.solve(Sudoku.java:71)
at Sudoku.solve(Sudoku.java:71)
at Sudoku.solve(Sudoku.java:50)
at Sudoku.solve(Sudoku.java:50)
at Sudoku.solve(Sudoku.java:71)
at Sudoku.solve(Sudoku.java:50)
at Sudoku.solve(Sudoku.java:50)
at Sudoku.solve(Sudoku.java:67)
at Sudoku.solve(Sudoku.java:71)
at Sudoku.solve(Sudoku.java:50)
at Sudoku.solve(Sudoku.java:50)
at Sudoku.solve(Sudoku.java:71)
at Sudoku.solve(Sudoku.java:50)
at Sudoku.solve(Sudoku.java:50)
at Sudoku.solve(Sudoku.java:50)
at Sudoku.solve(Sudoku.java:50)
at Sudoku.solve(Sudoku.java:38)
at Sudoku.solve(Sudoku.java:71)
at Sudoku.solve(Sudoku.java:50)
at Sudoku.solve(Sudoku.java:50)
at Sudoku.solve(Sudoku.java:71)
at Sudoku.solve(Sudoku.java:71)
at Sudoku.solve(Sudoku.java:50)
at Sudoku.solve(Sudoku.java:71)
at Sudoku.solve(Sudoku.java:71)
at Sudoku.solve(Sudoku.java:38)
at Sudoku.solve(Sudoku.java:50)
at Sudoku.solve(Sudoku.java:71)
at Sudoku.solve(Sudoku.java:50)
at Sudoku.solve(Sudoku.java:71)
at Sudoku.solve(Sudoku.java:71)
at Sudoku.solve(Sudoku.java:50)
at Sudoku.solve(Sudoku.java:71)
at Sudoku.solve(Sudoku.java:71)
at Sudoku.solve(Sudoku.java:38)
at Sudoku.solve(Sudoku.java:50)
at Sudoku.solve(Sudoku.java:71)
at Sudoku.solve(Sudoku.java:71)
at Sudoku.solve(Sudoku.java:50)
at Sudoku.solve(Sudoku.java:71)
at Sudoku.solve(Sudoku.java:71)
at Sudoku.solve(Sudoku.java:50)
at Sudoku.solve(Sudoku.java:50)
at Sudoku.solve(Sudoku.java:67)
at Sudoku.solve(Sudoku.java:71)
at Sudoku.solve(Sudoku.java:50)
at Sudoku.solve(Sudoku.java:71)
at Sudoku.solve(Sudoku.java:71)
at Sudoku.solve(Sudoku.java:50)
at Sudoku.solve(Sudoku.java:71)
at Sudoku.solve(Sudoku.java:50)
at Sudoku.solve(Sudoku.java:50)
at Sudoku.solve(Sudoku.java:67)
at Sudoku.solve(Sudoku.java:71)
at Sudoku.solve(Sudoku.java:50)
at Sudoku.solve(Sudoku.java:71)
at Sudoku.solve(Sudoku.java:71)
at Sudoku.solve(Sudoku.java:50)
at Sudoku.solve(Sudoku.java:50)
at Sudoku.solve(Sudoku.java:71)
at Sudoku.solve(Sudoku.java:50)
at Sudoku.solve(Sudoku.java:38)
at Sudoku.solve(Sudoku.java:50)
at Sudoku.solve(Sudoku.java:50)
at Sudoku.solve(Sudoku.java:50)
at Sudoku.solve(Sudoku.java:71)
at Sudoku.solve(Sudoku.java:50)
at Sudoku.solve(Sudoku.java:50)
at Sudoku.solve(Sudoku.java:71)
at Sudoku.solve(Sudoku.java:71)
at Sudoku.solve(Sudoku.java:38)
at Sudoku.solve(Sudoku.java:50)
at Sudoku.solve(Sudoku.java:71)
at Sudoku.solve(Sudoku.java:50)
at Sudoku.solve(Sudoku.java:50)
at Sudoku.solve(Sudoku.java:71)
at Sudoku.solve(Sudoku.java:71)
at Sudoku.solve(Sudoku.java:50)
at Sudoku.solve(Sudoku.java:50)
at Sudoku.main(Sudoku.java:9)
有什么想法可以停止循环并打印正确的字段吗? System.out.println(field)
而不是解决方法中的这个?
某处试图访问不存在的数组上层元素。尝试调试并找到。
可能 val 是要查找的关键。
我假设 for (int val = 1; val <=9; val++) 应该 for (int val = 1; val <9; val++)
永不终止的递归
(在这种情况下,它会在出错时终止)。
你的这部分代码需要实际做一些事情来表明它已经完成:
if ( j >= Field.SIZE) {
//we are done
}
否则该循环只是继续进行,没有意识到它应该停止(缩短):
for (int val = 1; val <=9; val++) {
...
solve (f, i+1, 0); // Maybe this call is 'done', but this loop will keep going
...
}
因此,基于 throws SolvedException
你的代码应该在那里抛出异常:
if ( j >= Field.SIZE) {
//we are done
throw new SolvedException();
}
但这是一个坏主意。例外情况是 not 用于控制代码流 - 它们用于 completely unexpected situations.
表示完成
相反,我们需要通过某种方式知道代码何时达到 'done' 条件。在经典递归中,这是通过 returning 某些东西来执行的。正如我们只想知道它是否完成,bool
处理得很好:
// Type changed to bool, removed throws:
public static bool solve(Field f, int i, int j) {
System.out.print(f+"\n");
if ( j >= Field.SIZE) {
//we are done (return true now!)
return true;
}
if (f.isEmpty(i, j)) {
for (int val = 1; val <=9; val++) {
if (f.tryValue(val, i, j)){
if (j>=Field.SIZE-1){
if( solve (f, i+1, 0) ){
// This halts the loop here:
return true;
}
f.clear(i, j);
} else {
if( solve(f,i,j+1) ){
// This halts the loop here:
return true;
}
f.clear(i, j);
}
}
}
} else if (j>=Field.SIZE-1) {
// (Side note: This one is tail recursion)
return solve(f,i+1,0);
}
// (Side note: This one is tail recursion)
return solve(f,i,j+1);
}
在被调用者中,你还有这个:
try {
solve(field, 0, 0);
}
catch (SolvedException e) { }
你也会换成:
if( solve(field, 0, 0) ){
// It was solved!
}
改为返回 void
您提到您仍然想要 return void
。好的,所以,我们需要在其他地方跟踪 'done' 状态 - 例如在我们称之为 SudokuSolver
:
public class SudokuSolver{
/* Set true when the solve is done */
public bool done;
}
使用它使代码看起来更像这样:
// Type changed to void, added our solver arg:
public static void solve(Field f, int i, int j, SudokuSolver solver) {
System.out.print(f+"\n");
if ( j >= Field.SIZE) {
//we are done (return true now!)
solver.done=true;
return;
}
if (f.isEmpty(i, j)) {
for (int val = 1; val <=9; val++) {
if (f.tryValue(val, i, j)){
if (j>=Field.SIZE-1){
solve (f, i+1, 0, solver);
if ( solver.done ) {
// This halts the loop here:
return;
}
f.clear(i, j);
} else {
solve(f,i,j+1, solver);
if ( solver.done ) {
// This halts the loop here:
return;
}
f.clear(i, j);
}
}
}
} else if (j>=Field.SIZE-1) {
solve(f,i+1,0, solver);
} else {
solve(f,i,j+1, solver);
}
}
呼叫站点现在看起来像这样:
SudokuSolver solver=new SudokuSolver();
solve(field, 0, 0, solver);
if ( solver.done ) {
// It was solved!
}