【问题标题】:Java - Attempt to read from a null 2-D Randomly Generate Array [duplicate]Java - 尝试从一个空的二维随机生成数组中读取[重复]
【发布时间】:2018-08-16 08:30:21
【问题描述】:

在这个问题here 之后,我遇到了一些问题,我使用这个 DFS 算法来搜索 2d 数组,但是当我尝试运行它时它得到第一行并且它崩溃了,它变成了就我的实用程序类而言,如果算法正确,算法应该存储状态,然后转到下一行,但似乎数组在第一次搜索后被删除。

int r = p[0];
            int c = p[1];
            System.out.println("expanding game state for node at (" + r + ", " + c + ")");

然后我得到了

java.lang.NullPointerException: Attempt to read from null array 错误。

这里是主要的search() 函数InitializeEasy() 以及生成数组的代码

public int[][] debug_board_state_easy = new int[4][4];
 void search(){

    Map<Point, List<Direction>> remainingOptions = new HashMap<>();

    Stack<Land> gameTree = new Stack<>();
    gameTree.push(new Land(STARTING_CLUES));

    while(true){

      Land state = gameTree.peek();
      int[] p = state.lowestTodo();
      if (p == null)
        System.out.println("solution found");

      // move to next game state
      int r = p[0];
      int c = p[1];
      System.out.println("expanding game state for node at (" + r + ", " + c + ")");

      List<Direction> ds = null;
      if(remainingOptions.containsKey(new Point(r,c)))
        ds = remainingOptions.get(new Point(r,c));
      else{
        ds = new ArrayList<>();
        for(Direction dir : Direction.values()) {
          int[] tmp = state.nextIsland(r, c, dir);
          if(tmp == null)
            continue;
          if(state.canBuildBridge(r,c,tmp[0], tmp[1]))
            ds.add(dir);
        }
        remainingOptions.put(new Point(r,c), ds);
      }

      // if the node can no longer be expanded, and backtracking is not possible we quit
      if(ds.isEmpty() && gameTree.isEmpty()){
        System.out.println("no valid configuration found");
        return;
      }

      // if the node can no longer be expanded, we need to backtrack
      if(ds.isEmpty()){
        gameTree.pop();
        remainingOptions.remove(new Point(r,c));
        System.out.println("going back to previous decision");
        continue;
      }

      Direction dir = ds.remove(0);
      System.out.println("connecting " + dir.name());
      remainingOptions.put(new Point(r,c), ds);

      Land nextState = new Land(state);
      int[] tmp = state.nextIsland(r,c,dir);
      nextState.connect(r,c, tmp[0], tmp[1]);
      gameTree.push(nextState);

    }

  }

  private void InitializeEasy() {
    Random rand = new Random();

    setCurrentState(new State(WIDTH_EASY));
    for (int row = 0; row < debug_board_state_easy.length; row++) {
      for (int column = 0; column < debug_board_state_easy[row].length; column++) {
        debug_board_state_easy[row][column] = Integer.valueOf(rand.nextInt(5));

      }

    }


    for (int row = 0; row < debug_board_state_easy.length; row++) {
      for (int column = 0; column < debug_board_state_easy[row].length; column++) {
        System.out.print(debug_board_state_easy[row][column] + " ");
      }
      System.out.println(debug_board_state_easy);
this.search();

    }
    this.search();
    for (int row = 0; row < WIDTH_EASY; ++row) {
      for (int column = 0; column < WIDTH_EASY; ++column) {
//                  System.out.println();

        getCurrentState().board_elements[row][column] = new BoardElement();
        getCurrentState().board_elements[row][column].max_connecting_bridges = Integer.valueOf(debug_board_state_easy[row][column]);
        getCurrentState().board_elements[row][column].row = row;
        getCurrentState().board_elements[row][column].col = column;

        if (getCurrentState().board_elements[row][column].max_connecting_bridges > 0) {
          getCurrentState().board_elements[row][column].is_island = true;
        }

      }
    }
  }

Land.Java - 实用程序类

public class Land {

    private int[][] BRIDGES_TO_BUILD;

    private boolean[][] IS_ISLAND;
    private Direction[][] BRIDGES_ALREADY_BUILT;

    public Land(int[][] bridgesToDo){
        BRIDGES_TO_BUILD = copy(bridgesToDo);

        int R = bridgesToDo.length;
        int C = bridgesToDo[0].length;
        BRIDGES_ALREADY_BUILT = new Direction[R][C];
        IS_ISLAND = new boolean[R][C];
        for(int i=0;i<R;i++) {
            for (int j = 0; j < C; j++) {
                BRIDGES_ALREADY_BUILT[i][j] = null;
                IS_ISLAND[i][j] = bridgesToDo[i][j] > 0;
            }
        }
    }

    public Land(Land other){
        BRIDGES_TO_BUILD = copy(other.BRIDGES_TO_BUILD);
        int R = BRIDGES_TO_BUILD.length;
        int C = BRIDGES_TO_BUILD[0].length;
        BRIDGES_ALREADY_BUILT = new Direction[R][C];
        IS_ISLAND = new boolean[R][C];
        for(int i=0;i<R;i++) {
            for (int j = 0; j < C; j++) {
                BRIDGES_ALREADY_BUILT[i][j] = other.BRIDGES_ALREADY_BUILT[i][j];
                IS_ISLAND[i][j] = other.IS_ISLAND[i][j];
            }
        }
    }

    public int[] next(int r, int c, Path.Direction dir){
        int R = BRIDGES_TO_BUILD.length;
        int C = BRIDGES_TO_BUILD[0].length;

        // out of bounds
        if(r < 0 || r >=R || c < 0 || c >= C)
            return null;


        // motion vectors
        int[][] motionVector = {{-1, 0},{0,1},{1,0},{0,-1}};
        int i = Arrays.asList(values()).indexOf(dir);

        // calculate next
        int[] out = new int[]{r + motionVector[i][0], c + motionVector[i][1]};

        r = out[0];
        c = out[1];

        // out of bounds
        if(r < 0 || r >=R || c < 0 || c >= C)
            return null;

        // return
        return out;
    }

    public int[] nextIsland(int r, int c, Path.Direction dir){
        int[] tmp = next(r,c,dir);
        if(tmp == null)
            return null;
        while(!IS_ISLAND[tmp[0]][tmp[1]]){
            tmp = next(tmp[0], tmp[1], dir);
            if(tmp == null)
                return null;
        }
        return tmp;
    }

    public boolean canBuildBridge(int r0, int c0, int r1, int c1){
        if(r0 == r1 && c0 > c1){
            return canBuildBridge(r0, c1, r1, c0);
        }
        if(c0 == c1 && r0 > r1){
            return canBuildBridge(r1, c0, r0, c1);
        }
        if(r0 == r1){
            int[] tmp = nextIsland(r0, c0, CW);
            if(tmp[0] != r1 || tmp[1] != c1)
                return false;
            if(BRIDGES_TO_BUILD[r0][c0] == 0)
                return false;
            if(BRIDGES_TO_BUILD[r1][c1] == 0)
                return false;
            for (int i = c0; i <= c1 ; i++) {
                if(IS_ISLAND[r0][i])
                    continue;
                if(BRIDGES_ALREADY_BUILT[r0][i] == Direction.NORTH)
                    return false;
            }
        }
        if(c0 == c1){
            int[] tmp = nextIsland(r0, c0, CCW);
            if(tmp[0] != r1 || tmp[1] != c1)
                return false;
            if(BRIDGES_TO_BUILD[r0][c0] == 0 || BRIDGES_TO_BUILD[r1][c1] == 0)
                return false;
            for (int i = r0; i <= r1 ; i++) {
                if(IS_ISLAND[i][c0])
                    continue;
                if(BRIDGES_ALREADY_BUILT[i][c0] == Direction.SOUTH) {
                    return false;
                }
            }
        }
        // default
        return true;
    }

    public int[] lowestTodo(){
        int R = BRIDGES_TO_BUILD.length;
        int C = BRIDGES_TO_BUILD[0].length;

        int[] out = {0, 0};
        for (int i=0;i<R;i++) {
            for (int j = 0; j < C; j++) {
                if(BRIDGES_TO_BUILD[i][j] == 0)
                    continue;
                if (BRIDGES_TO_BUILD[out[0]][out[1]] == 0)
                    out = new int[]{i, j};
                if (BRIDGES_TO_BUILD[i][j] < BRIDGES_TO_BUILD[out[0]][out[1]])
                    out = new int[]{i, j};
            }
        }
        if (BRIDGES_TO_BUILD[out[0]][out[1]] == 0) {
            return null;
        }
        return out;
    }

    @TargetApi(Build.VERSION_CODES.GINGERBREAD)
    private int[][] copy(int[][] other){
        int[][] out = new int[other.length][other.length == 0 ? 0 : other[0].length];
        for(int r=0;r<other.length;r++)
            out[r] = Arrays.copyOf(other[r], other[r].length);
        return out;
    }

    public void connect(int r0, int c0, int r1, int c1){
        if(r0 == r1 && c0 > c1){
            connect(r0, c1, r1, c0);
            return;
        }
        if(c0 == c1 && r0 > r1){
            connect(r1, c0, r0, c1);
            return;
        }
        if(!canBuildBridge(r0, c0, r1, c1))
            return;

        BRIDGES_TO_BUILD[r0][c0]--;
        BRIDGES_TO_BUILD[r1][c1]--;

        if(r0 == r1){
            for (int i = c0; i <= c1 ; i++) {
                if(IS_ISLAND[r0][i])
                    continue;
                BRIDGES_ALREADY_BUILT[r0][i] = Direction.EAST;
            }
        }
        if(c0 == c1){
            for (int i = r0; i <= r1 ; i++) {
                if(IS_ISLAND[i][c0])
                    continue;
                BRIDGES_ALREADY_BUILT[i][c0] = Direction.NORTH;
            }
        }
    }
}

【问题讨论】:

  • 请正确格式化您的代码,这不是阅读的乐趣。其他问题:你的第一个 dfs 算法? (显然不是你实现的,而是你第一次使用)
  • 可能是这个if (BRIDGES_TO_BUILD[out[0]][out[1]] == 0) { return null; }

标签: java arrays algorithm depth-first-search


【解决方案1】:

由于 Land 类中的这一行,您必须添加一个空检查

if (BRIDGES_TO_BUILD[out[0]][out[1]] == 0) {
            return null;
}

【讨论】:

    猜你喜欢
    • 2014-11-19
    • 1970-01-01
    • 2016-08-26
    • 2019-02-21
    • 1970-01-01
    • 1970-01-01
    • 2015-04-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多