我的程序有问题,它应该解决数独并在完成时打印,但问题是,程序看起来好像永远不会结束,打印解决后的数据后会出现错误。
这是程序正在制作的循环:
如果我在开始时删除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);
}
}
}
SudokuSolver
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)
而不是这个?
答案 0 :(得分:1)
(在这种情况下,它会在错误时终止。)
这部分代码需要实际做一些事情来表明它已经完成了:
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();
}
但这是一个坏主意。用于控制代码流的例外不 - 它们用于completely unexpected situations。
相反,我们需要有一些方法来了解代码何时达到“完成”的目的。条件。在经典递归中,这是通过返回一些东西来执行的。我们只想知道它是否已经完成,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
。好的,所以,我们需要跟踪那些已经完成的事情。在其他地方陈述 - 例如在我们称之为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!
}
答案 1 :(得分:0)
某处试图访问不存在的数组上层元素。尝试调试并找到。
可能val是寻找的关键。
我假设 for(int val = 1; val&lt; = 9 ; val ++) 应该 for(int val = 1; val&lt; 9 ; val ++)