以下代码在10x10或8x8棋盘中的位置0 0处开始时为棋盘中的骑士找到正确的哈密顿周期,但在其他任何地方启动时会抛出NullPointerException。
这里的输入应该是
8
8
0
0
对于从位置0 0开始的8x8棋盘上的哈密尔顿循环,它运行正确的输出:
1 16 27 22 3 18 29 32
26 23 2 17 28 31 4 19
15 64 25 36 21 50 33 30
24 37 48 61 56 35 20 5
47 14 63 38 49 60 51 34
42 39 44 57 62 55 6 9
13 46 41 54 11 8 59 52
40 43 12 45 58 53 10 7
on
8
8
1
1
我明白了:
Exception in thread "main" java.lang.NullPointerException
at horseBETA.mover(horseBETA.java:55)
at horseBETA.search(horseBETA.java:130)
at horseBETA.main(horseBETA.java:164)
Java Result: 1
为什么呢?
import java.util.Scanner;
/**
*
* @author Darwin Martinez
*/
class position{
int x,y;
position() {};
position(int a, int b) { x=a; y=b; }
}
public class horseBETA {
static int number_of_movements = 8;
static int dx[] = {-1, -2, -2, -1, 1, 2, 2, 1};
static int dy[] = {-2, -1, 1, 2, 2, 1, -1, -2};
static int longCycle;
static int N,M,I,J;
static int[][] order;
position solucion[];
static boolean free[][];
static int longitud;
static int dfs_visited[][],stampdfs;
horseBETA(int N, int M, int I, int J) {
longCycle = N*M;
order = new int[N][M];
solucion = new position[longCycle];
free = new boolean [N][M];
dfs_visited = new int[N][M];
for (int i=0;i<N;i++)
for (int j=0;j<M;j++) {
free[i][j] = true;
dfs_visited[i][j] = 0;
}
stampdfs = 0;
position aux=new position(I,J);
int index=(I*N)+J;
solucion[index]=aux;
free[I][J] = false;
longitud = 1;
}
boolean valida(position p) {
return 0<=p.x && p.x<N &&
0<=p.y && p.y<M && free[p.x][p.y];
}
position mover(position p,int i) {
return new position(p.x+dx[i],p.y+dy[i]);
}
boolean es_terminal() {
return longitud == longCycle;
}
boolean is_factible(position p) {
return ((p.x == I+dx[0] && p.y == J+dy[0]) || (p.x == I+dx[1] && p.y == J+dy[1])
|| (p.x == I+dx[2] && p.y == J+dy[2])|| (p.x == I+dx[3] && p.y == J+dy[3])
|| (p.x == I+dx[4] && p.y == J+dy[4])|| (p.x == I+dx[5] && p.y == J+dy[5])
|| (p.x == I+dx[6] && p.y == J+dy[6])|| (p.x == I+dx[7] && p.y == J+dy[7]));
}
boolean prometedor_recurs(position d) {
if (is_factible(d)) return true;
for (int i=0;i<number_of_movements;i++) {
position a = mover(d,i);
if (valida(a) && dfs_visited[a.x][a.y] != stampdfs) {
dfs_visited[a.x][a.y] = stampdfs;
if (prometedor_recurs(a)) return true;
}
}
return false;
}
boolean promising(position d) {
stampdfs++;
return prometedor_recurs(d);
}
void print_solution() {
for (int i=0;i<longCycle;i++)
order[solucion[i].x][solucion[i].y] = i+1;
for (int i = 0; i < N; i++) {
for (int j = 0; j < M; j++) {
if(order[i][j]<10)
System.out.print(" "+order[i][j]);
else{
if(order[i][j]>=10&&order[i][j]<100)
System.out.print(" "+order[i][j]);
else
System.out.print(" "+order[i][j]);
}
}System.out.print("\n");
}
System.exit(0);
}
void insertionSort(position p[], int r[], int n) {
int i,j,aux;
position auxp;
for (i=1; i<n; i++) {
aux=r[i]; auxp = p[i];
for (j=i-1; j>=0 && aux<r[j]; j--) {
r[j+1]=r[j]; p[j+1]=p[j];
}
r[j+1]=aux; p[j+1] = auxp;
}
}
public boolean search() {
if (es_terminal()) {
if (is_factible(solucion[longCycle-1])){
print_solution();
return true;
}
} else {
int nchildren = 0;
position p[]=new position[number_of_movements];
int r[]=new int[number_of_movements];
for (int i=0;i<number_of_movements;i++) {
position a = mover(solucion[longitud-1],i);
if (valida(a)) {
int grado = 0;
for (int j=0;j<number_of_movements;j++)
if (valida(mover(a,j)))
grado++;
p[nchildren] = a;
r[nchildren] = grado;
nchildren++;
}
}
insertionSort(p,r,nchildren);
for (int i=0; i<nchildren; i++) {
solucion[longitud] = p[i]; longitud++;
free[p[i].x][p[i].y] = false;
if (promising(p[i]))
search();
free[p[i].x][p[i].y] = true;
longitud--;
}
}return false;
}
public static void main(String[] args) {
Scanner x= new Scanner(System.in);
N = x.nextInt();
M = x.nextInt();
I = x.nextInt();
J = x.nextInt();
horseBETA yy = new horseBETA(N,M,I,J);
if(!yy.search())
System.out.println("\nNo hay solucion");
}
}
答案 0 :(得分:4)
这是一个让你入门的提示:
从stacktrace开始。跟踪的第一行说:
at horseBETA.mover(horseBETA.java:55)
这意味着mover
方法中发生了异常,该方法只包含一行:
return new position(p.x+dx[i],p.y+dy[i]);
尝试取消引用空引用时抛出NPE。上面的行中有4个子表达式,其中对象引用被解除引用,并且可能发生NPE。
p.x
为空,则 p.y
和p
可能会抛出NPE。
dx[i]
和dy[i]
为空,则 dx
或dy
可能会抛出NPE。
通过简单检查代码,可以排除这些可能原因中的四分之二; dx
和dy
被初始化为非空值,然后从未分配给。这使得p
成为null
可能的原因。 (您可以使用跟踪图或使用调试器来确认这一点。)
现在告诉你......
(我也同意@Speck。你的代码存在一些严重的样式问题,这使得阅读和难以调试很痛苦......)
答案 1 :(得分:0)
首先,您的代码难以辨认。如果使用可接受的样式指南,则在调试时会有所帮助。
有几项有待改进的事项:
对变量使用名称而非字母,并使用camelCaseVariables。这些将有助于提高可读性,特别是在提出这样的问题时。
即使对于一个带衬里的if语句和循环,也要使用open和close括号。它将更好地引发循环并使它们更具可读性,并有助于防止程序流中的错误。
无论如何,您可能正在传递一个空位置对象(将您的类名btw大写)到移动器方法。在IDE中,在该行上设置断点,并使其成为条件,仅在传递的指针对象为空时停止。你很快就会明白为什么。