关于这个哈密顿循环问题的NullPointerException

时间:2011-06-25 03:36:16

标签: java 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

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");

     }
}

2 个答案:

答案 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.yp可能会抛出NPE。

  • 如果(分别)dx[i]dy[i]为空,则
  • dxdy可能会抛出NPE。

通过简单检查代码,可以排除这些可能原因中的四分之二; dxdy被初始化为非空值,然后从未分配给。这使得p成为null可能的原因。 (您可以使用跟踪图或使用调试器来确认这一点。)

现在告诉你......


(我也同意@Speck。你的代码存在一些严重的样式问题,这使得阅读和难以调试很痛苦......)

答案 1 :(得分:0)

首先,您的代码难以辨认。如果使用可接受的样式指南,则在调试时会有所帮助。

有几项有待改进的事项:

对变量使用名称而非字母,并使用camelCaseVariables。这些将有助于提高可读性,特别是在提出这样的问题时。

即使对于一个带衬里的if语句和循环,也要使用open和close括号。它将更好地引发循环并使它们更具可读性,并有助于防止程序流中的错误。

无论如何,您可能正在传递一个空位置对象(将您的类名btw大写)到移动器方法。在IDE中,在该行上设置断点,并使其成为条件,仅在传递的指针对象为空时停止。你很快就会明白为什么。