如何在 Java 程序中找到无限递归错误?
How to find an infinite recursion error in a Java program?
import java.lang.reflect.Array;
import java.util.*;
public class TMS {
private static int row = 5, col = 5;
private static String[][] board = new String[row][col];
private static String[][] board_copy = new String[row][col];
public static void main(String[] args) {
for(String[] array:board) {
Arrays.fill(array, "_");
}
create_mines();
Scanner input = new Scanner(System.in);
int inpx = 0, inpy;
while(inpx != 69){
show_board();
inpx = input.nextInt();
inpy = input.nextInt();
if(board_copy[inpx][inpy] == "*"){
System.out.println("YOU LOOSE");
break;
}
check_move(inpx, inpy);
}
}
public static void show_board() {
for(String[] row: board){
for(String element: row){
System.out.print(element+"\t");
}System.out.println();
}
}
public static void create_mines() {
Random rand = new Random();
rand.nextInt();
for(String[] array:board_copy) {
Arrays.fill(array, "_");
}
board_copy[1][1] = "*";
board_copy[3][1] = "*";
board_copy[3][3] = "*";
board_copy[2][4] = "*";
}
public static void check_move(int posx, int posy){
int mines = 0;
if(posx-1 >= 0 && posy-1 >= 0)
mines = (board_copy[posx-1][posy-1] == "*")? (mines+1):mines;
if(posx >= 0 && posy-1 >= 0)
mines = (board_copy[posx][posy-1] == "*")? (mines+1):mines;
if(posx+1 < row && posy+1 < col)
mines = (board_copy[posx+1][posy+1] == "*")? (mines+1):mines;
if(posx-1 >= 0 && posy >= 0)
mines = (board_copy[posx-1][posy] == "*")? (mines+1):mines;
if(posx+1 < row && posy >= 0)
mines = (board_copy[posx+1][posy] == "*")? (mines+1):mines;
if(posx >= 0 && posy+1 < col)
mines = (board_copy[posx][posy+1] == "*")? (mines+1):mines;
if(posx-1 >= 0 && posy+1 < col)
mines = (board_copy[posx-1][posy+1] == "*")? (mines+1):mines;
if(posx+1 < row && posy-1 >= 0)
mines = (board_copy[posx+1][posy-1] == "*")? (mines+1):mines;
board[posx][posy] = Integer.toString(mines);
if(mines == 0){
if((posx-1) >= 0 && (posy-1) >= 0) {
System.out.println((posx-1)+" "+(posy-1));
check_move((posx - 1), (posy - 1));
}
if(posx >= 0 && (posy-1) >= 0) {
System.out.println((posx)+" "+(posy-1));
check_move(posx, (posy - 1));
}
if((posx+1) < row && (posy+1) < col) {
System.out.println((posx+1)+" "+(posy+1));
check_move((posx + 1), (posy + 1));
}
if((posx-1) >= 0 && posy >= 0) {
System.out.println((posx-1)+" "+(posy));
check_move((posx - 1), posy);
}
if((posx+1) < row && posy >= 0) {
System.out.println((posx+1)+" "+(posy));
check_move((posx + 1), posy);
}
if(posx >= 0 && (posy+1) < col) {
System.out.println((posx)+" "+(posy+1));
check_move(posx, (posy + 1));
}
if((posx-1) >= 0 && (posy+1) < col) {
System.out.println((posx-1)+" "+(posy+1));
check_move((posx - 1), (posy + 1));
}
if((posx+1) < row && (posy-1) >= 0) {
System.out.println((posx+1)+" "+(posy-1));
check_move((posx + 1), (posy - 1));
}
}
}
}
显然,我在递归期间无限地调用方法 check_move。我不知道为什么它会无限地进行下去。这是错误消息:
Exception in thread "main" java.lang.WhosebugError
at java.lang.Integer.toString(Integer.java:402)
at TMS.check_move(TMS.java:70)
at TMS.check_move(TMS.java:79)
at TMS.check_move(TMS.java:79)
at TMS.check_move(TMS.java:95)
at TMS.check_move(TMS.java:79)
at TMS.check_move(TMS.java:95)
at TMS.check_move(TMS.java:79)
at TMS.check_move(TMS.java:95)
at TMS.check_move(TMS.java:79)
at TMS.check_move(TMS.java:95)
at TMS.check_move(TMS.java:79)
at TMS.check_move(TMS.java:95)
at TMS.check_move(TMS.java:79)
at TMS.check_move(TMS.java:95)
at TMS.check_move(TMS.java:79)
at TMS.check_move(TMS.java:95)
at TMS.check_move(TMS.java:79)
at TMS.check_move(TMS.java:95)
at TMS.check_move(TMS.java:79)
at TMS.check_move(TMS.java:95)
at TMS.check_move(TMS.java:79)
at TMS.check_move(TMS.java:95)
at TMS.check_move(TMS.java:79)
at TMS.check_move(TMS.java:95)
at TMS.check_move(TMS.java:79)
at TMS.check_move(TMS.java:95)
at TMS.check_move(TMS.java:79)
at TMS.check_move(TMS.java:95)
at TMS.check_move(TMS.java:79)
at TMS.check_move(TMS.java:95)
.
.
.
.
(GOES ON FOREVER)
例如,如果您有两个没有地雷的相邻单元格,您的递归将不会结束。例如,如果在某个位置 (posx,posy) 没有我的,你在
行的 (posx-1,posy-1) 处调用 check_move
if((posx-1) >= 0 && (posy-1) >= 0) {
System.out.println((posx-1)+" "+(posy-1));
check_move((posx - 1), (posy - 1));
现在,如果(posx-1,posy-1)也没有地雷,你将在
行的(posx,posy)调用check_move
if((posx+1) < row && (posy+1) < col) {
System.out.println((posx+1)+" "+(posy+1));
check_move((posx + 1), (posy + 1));
这将永远持续下去。您需要找到一种在所有情况下结束递归的方法。例如,您可以在每个单元格上设置一个 'checked' 标志,以阻止您在已经测试过的位置重新调用 check_move(可能还有其他方法...)。
正如 Andreas 指出的那样,您的 inpx = 69 不会产生预期的效果,因为您的例程会在返回到 while 循环测试之前调用异常。
import java.lang.reflect.Array;
import java.util.*;
public class TMS {
private static int row = 5, col = 5;
private static String[][] board = new String[row][col];
private static String[][] board_copy = new String[row][col];
public static void main(String[] args) {
for(String[] array:board) {
Arrays.fill(array, "_");
}
create_mines();
Scanner input = new Scanner(System.in);
int inpx = 0, inpy;
while(inpx != 69){
show_board();
inpx = input.nextInt();
inpy = input.nextInt();
if(board_copy[inpx][inpy] == "*"){
System.out.println("YOU LOOSE");
break;
}
check_move(inpx, inpy);
}
}
public static void show_board() {
for(String[] row: board){
for(String element: row){
System.out.print(element+"\t");
}System.out.println();
}
}
public static void create_mines() {
Random rand = new Random();
rand.nextInt();
for(String[] array:board_copy) {
Arrays.fill(array, "_");
}
board_copy[1][1] = "*";
board_copy[3][1] = "*";
board_copy[3][3] = "*";
board_copy[2][4] = "*";
}
public static void check_move(int posx, int posy){
int mines = 0;
if(posx-1 >= 0 && posy-1 >= 0)
mines = (board_copy[posx-1][posy-1] == "*")? (mines+1):mines;
if(posx >= 0 && posy-1 >= 0)
mines = (board_copy[posx][posy-1] == "*")? (mines+1):mines;
if(posx+1 < row && posy+1 < col)
mines = (board_copy[posx+1][posy+1] == "*")? (mines+1):mines;
if(posx-1 >= 0 && posy >= 0)
mines = (board_copy[posx-1][posy] == "*")? (mines+1):mines;
if(posx+1 < row && posy >= 0)
mines = (board_copy[posx+1][posy] == "*")? (mines+1):mines;
if(posx >= 0 && posy+1 < col)
mines = (board_copy[posx][posy+1] == "*")? (mines+1):mines;
if(posx-1 >= 0 && posy+1 < col)
mines = (board_copy[posx-1][posy+1] == "*")? (mines+1):mines;
if(posx+1 < row && posy-1 >= 0)
mines = (board_copy[posx+1][posy-1] == "*")? (mines+1):mines;
board[posx][posy] = Integer.toString(mines);
if(mines == 0){
if((posx-1) >= 0 && (posy-1) >= 0) {
System.out.println((posx-1)+" "+(posy-1));
check_move((posx - 1), (posy - 1));
}
if(posx >= 0 && (posy-1) >= 0) {
System.out.println((posx)+" "+(posy-1));
check_move(posx, (posy - 1));
}
if((posx+1) < row && (posy+1) < col) {
System.out.println((posx+1)+" "+(posy+1));
check_move((posx + 1), (posy + 1));
}
if((posx-1) >= 0 && posy >= 0) {
System.out.println((posx-1)+" "+(posy));
check_move((posx - 1), posy);
}
if((posx+1) < row && posy >= 0) {
System.out.println((posx+1)+" "+(posy));
check_move((posx + 1), posy);
}
if(posx >= 0 && (posy+1) < col) {
System.out.println((posx)+" "+(posy+1));
check_move(posx, (posy + 1));
}
if((posx-1) >= 0 && (posy+1) < col) {
System.out.println((posx-1)+" "+(posy+1));
check_move((posx - 1), (posy + 1));
}
if((posx+1) < row && (posy-1) >= 0) {
System.out.println((posx+1)+" "+(posy-1));
check_move((posx + 1), (posy - 1));
}
}
}
}
显然,我在递归期间无限地调用方法 check_move。我不知道为什么它会无限地进行下去。这是错误消息:
Exception in thread "main" java.lang.WhosebugError
at java.lang.Integer.toString(Integer.java:402)
at TMS.check_move(TMS.java:70)
at TMS.check_move(TMS.java:79)
at TMS.check_move(TMS.java:79)
at TMS.check_move(TMS.java:95)
at TMS.check_move(TMS.java:79)
at TMS.check_move(TMS.java:95)
at TMS.check_move(TMS.java:79)
at TMS.check_move(TMS.java:95)
at TMS.check_move(TMS.java:79)
at TMS.check_move(TMS.java:95)
at TMS.check_move(TMS.java:79)
at TMS.check_move(TMS.java:95)
at TMS.check_move(TMS.java:79)
at TMS.check_move(TMS.java:95)
at TMS.check_move(TMS.java:79)
at TMS.check_move(TMS.java:95)
at TMS.check_move(TMS.java:79)
at TMS.check_move(TMS.java:95)
at TMS.check_move(TMS.java:79)
at TMS.check_move(TMS.java:95)
at TMS.check_move(TMS.java:79)
at TMS.check_move(TMS.java:95)
at TMS.check_move(TMS.java:79)
at TMS.check_move(TMS.java:95)
at TMS.check_move(TMS.java:79)
at TMS.check_move(TMS.java:95)
at TMS.check_move(TMS.java:79)
at TMS.check_move(TMS.java:95)
at TMS.check_move(TMS.java:79)
at TMS.check_move(TMS.java:95)
.
.
.
.
(GOES ON FOREVER)
例如,如果您有两个没有地雷的相邻单元格,您的递归将不会结束。例如,如果在某个位置 (posx,posy) 没有我的,你在
行的 (posx-1,posy-1) 处调用 check_move if((posx-1) >= 0 && (posy-1) >= 0) {
System.out.println((posx-1)+" "+(posy-1));
check_move((posx - 1), (posy - 1));
现在,如果(posx-1,posy-1)也没有地雷,你将在
行的(posx,posy)调用check_moveif((posx+1) < row && (posy+1) < col) {
System.out.println((posx+1)+" "+(posy+1));
check_move((posx + 1), (posy + 1));
这将永远持续下去。您需要找到一种在所有情况下结束递归的方法。例如,您可以在每个单元格上设置一个 'checked' 标志,以阻止您在已经测试过的位置重新调用 check_move(可能还有其他方法...)。
正如 Andreas 指出的那样,您的 inpx = 69 不会产生预期的效果,因为您的例程会在返回到 while 循环测试之前调用异常。