代码之家  ›  专栏  ›  技术社区  ›  AutoTester213

Java-尝试从空的二维随机生成数组中读取[duplicate]

  •  -1
  • AutoTester213  · 技术社区  · 6 年前

    在这个问题之后 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;
            }
    
          }
        }
      }
    

    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;
                }
            }
        }
    }
    
    1 回复  |  直到 6 年前
        1
  •  0
  •   AsfK    6 年前

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