关于此哈密顿循环问题的NullPointerException

问题描述

| 以下代码在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
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,-1,1,2,1};
    static int dy[] = {-2,-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,J);
        if(!yy.search())
            System.out.println(\"\\nNo hay solucion\");

     }
}
    

解决方法

        以下是帮助您入门的提示: 从堆栈跟踪开始。跟踪的第一行显示:
at horseBETA.mover(horseBETA.java:55)
这意味着in6ѭ方法中发生了异常,该方法仅包含一行:
  return new position(p.x+dx[i],p.y+dy[i]);
尝试取消引用空引用时,将引发NPE。上面一行中有4个子表达式,其中引用对象已取消引用,并且可能会发生NPE。 如果
p
为null,则
p.x
p.y
可能会抛出NPE。 如果(13ѭ和
dy
分别为空,则11ѭ或
dy[i]
可能会抛出NPE。 通过简单地检查代码,可以排除其中四分之二的可能原因。
dx
dy
被初始化为非空值,然后从不分配给它们。导致
p
null
的可能原因。 (您可以使用跟踪记录或调试器进行确认。) 现在交给您... (我也同意@Speck。您的代码存在一些严重的样式问题,这使它难以阅读且难以调试...)     ,        首先,您的代码难以辨认。如果使用可接受的样式准则,则在调试时会有所帮助。 需要改善的几件事: 使用名称而不是字母作为变量,并使用camelCaseVariables。这些将有助于提高可读性,尤其是在问这样的问题时。 对于语句和循环的一行也使用开括号和闭括号。它将更好地触发循环并使它们更具可读性,并有助于防止程序流程中的错误。 无论如何,您可能正在将一个空位置对象(将您的类名大写)传递给mover方法。在您的IDE中,在该行上设置一个断点,并使其有条件仅在传递的指针对象为null时才停止。您很快就会明白原因。