【问题标题】:Recursion and if statement only returns the negative value递归和if语句只返回负值
【发布时间】:2021-07-04 19:28:59
【问题描述】:

所以这个问题实际上是与作业相关的 2 合 1 问题。我必须编写一个程序,将包含土地、水、沙袋和房屋瓷砖的文件中的地图读取到二维数组和显示地图的 GUI 中。

按下按钮时,水砖会散布到所有接触它的土地和房屋瓷砖(水平、垂直和对角线),然后显示一条消息,告诉您房屋是否被淹。

这必须通过递归方法来完成,我有一个程序在很大程度上使用 8 个 if 语句,我认为这些语句效率非常低,而且也不真正符合分配要求。我怎样才能使这个递归?

我认为与我处理洪水问题的方式有关的第二个问题是,我检查房子是否仍然站立的方法总是显示房屋被淹消息,即使房子是站立的。

我已经尝试解决这个问题好几天了,任何见解都将不胜感激。 (我以前也遇到过一个问题,在我的for 方法中使用for 循环会导致我的程序冻结并且必须通过任务管理器关闭,即使我没有更改任何东西,它也会随机停止这样做不确定是否这有帮助)。

public static void Flood(JLabel[][] labelArray, JPanel panel) {
    //Timer that allows the GUI to update slowly so progression can be seen
    ActionListener taskPerformer = new ActionListener() {
    public void actionPerformed(ActionEvent arg0) {
        boolean running = true;
        while(running) {
            //Checks through the entire array to find water tiles 
            for (int i = 0; i < labelArray.length; i++) {
                for (int j = 0; j < labelArray[0].length; j++) {
                    if (labelArray[i][j].getText().equals("W")) {
                        if(i > 0 && (labelArray[i-1][j].getText().equals("L") || labelArray[i-1][j].getText().equals("H"))) {//Checks the tile left of the water tile
                            labelArray[i-1][j].setText("W");
                            labelArray[i-1][j].setBackground(Color.BLUE);
                        }
                        else if(j > 0 && (labelArray[i][j-1].getText().equals("L") ||labelArray[i][j-1].getText().equals("H"))) {//Checks the tile above the water tile
                            labelArray[i][j-1].setText("W");
                            labelArray[i][j-1].setBackground(Color.BLUE);
                        }
                        else if(i < labelArray.length-1 && (labelArray[i+1][j].getText().equals("L") || labelArray[i+1][j].getText().equals("H"))){//Checks the tile to the right of the water tile
                            labelArray[i+1][j].setText("W");
                            labelArray[i+1][j].setBackground(Color.BLUE);
                        }
                        else if(j < labelArray[0].length-1 && (labelArray[i][j+1].getText().equals("L") || labelArray[i][j+1].getText().equals("H"))) {//Checks the tile below the water tile
                            labelArray[i][j+1].setText("W");
                            labelArray[i][j+1].setBackground(Color.BLUE);
                            }       
                        else if(j < labelArray[0].length-1 && i < labelArray.length-1 && (labelArray[i+1][j+1].getText().equals("L") || labelArray[i+1][j+1].getText().equals("H"))) {//Checks the tile to the bottom right of the water tile
                            labelArray[i+1][j+1].setText("W");
                            labelArray[i+1][j+1].setBackground(Color.BLUE);
                        }
                        else if(j > 0 && i > 0 && (labelArray[i-1][j-1].getText().equals("L") || labelArray[i-1][j-1].getText().equals("H"))) {//Checks the tile to the top left of the water tile
                            labelArray[i-1][j-1].setText("W");
                            labelArray[i-1][j-1].setBackground(Color.BLUE);
                        }
                        else if(j > 0 && i < labelArray.length-1 && (labelArray[i+1][j-1].getText().equals("L") || labelArray[i+1][j-1].getText().equals("H"))) {//Checks the tile to the top right of the water tile
                            labelArray[i+1][j-1].setText("W");
                            labelArray[i+1][j-1].setBackground(Color.BLUE);
                        }
                        else if(j < labelArray[0].length-1 && i > 0 && (labelArray[i-1][j+1].getText().equals("L") || labelArray[i-1][j+1].getText().equals("H"))) {//Checks the tile to the bottom left of the water tile
                            labelArray[i-1][j+1].setText("W");
                            labelArray[i-1][j+1].setBackground(Color.BLUE);
                        }
                    }
                }
            }
            running = false;
            checkForHouse(labelArray);
        }
    }
    };
    new Timer(250, taskPerformer).start();
}

    public static void checkForHouse (JLabel[][] labelArray) {
    for (int r =0; r<labelArray.length; r++) {
        for (int c =0;c<labelArray[0].length; c++) {
            if(labelArray[r][c].getText().equals("H")) {
                textArea.setText(safeHouse);
            }
            else {
                textArea.setText(floodedHouse);
            }
        }
    }
}

【问题讨论】:

    标签: java swing if-statement recursion multidimensional-array


    【解决方案1】:

    根据评论更新

    1. 水可以一直流到边界
    2. 水可以流到相邻的土地或相邻的房屋,它们变成水
    3. 水不能流到相邻的沙袋
    4. 基于第 3 点,四面被沙袋包围的水不会流动

    从每个新填的土地或房屋递归遍历

    1. 使用 2 个 for 循环,遍历所有单元格
    2. 对于任何具有“W”的单元格,调用另一个函数
    3. 另一个函数将递归更新任何相邻的土地或房屋
    final int[] x = new int[] {-1, -1, -1,  0,  0,  1,  1,  1};
    final int[] y = new int[] {-1,  0,  1, -1,  1, -1   0,  1}; 
    
    final char HOUSE = 'H'
    final char LAND = 'L'; 
    final char WATER = 'W';
    final char WATERED_HOUSE = 'A';
    final char WATERED_LAND = 'B'; 
    
    final char SANDBAG = 'S'; // not used and is not needed
    
    void process(char[][] input) {
      for (int row = 0; row < input.length; row++) {
        for (int col = 0; col < input[row].length; col++) {
          if (input[row][col] == WATER) {
            processNeighbor(input, row, col);
          }
        }
      }
      // if a cell is WATERED_HOUSE, then update text (if not done in processNeighbor function)
      for (int row = 0; row < input.length; row++) {
        for (int col = 0; col < input[row].length; col++) {
          if (input[row][col] == WATERED_HOUSE) {
            // set text
          }
          // if needed for WATERED_HOUSE and WATERED_LAND, 
          // change back to WATER and LAND respectively
        }
      }
    }
    
    void processNeighbor(char[][] input, final int row, final int col) {
      for (int adj = 0; adj < adjCount; adj++) {
        final int hor = col + x[adj];
        final int ver = row + y[adj];
    
        // stop recursion if neighbor is a not any one of house or land.
        if (!isValid(input, ver, hor) || !(input[ver][hor] == LAND || input[ver][hor] == HOUSE)) {
          continue;
        }
    
        // modify state to help recursion to end
        // if modification is not allowed, then maintain separate visited state
        if (input[ver][hor] == HOUSE) {
          input[ver][hor] = WATERED_HOUSE;
          // note: can set flooded here or in a separate loop later
        } else if (input[ver][hor] == LAND) {
          input[ver][hor] = WATERED_LAND;
        }
    
        // process any unprocessed neighbor recursively
        processNeighbor(input, ver, hor);
      }
    }
    
    // check whether given cell is within grid
    boolean isValid(char[][] input, final int row, final int col) {
      return row >= 0 && row < input.length && col >= 0 && col < input[row].length;
    }
    

    原创

    以下逻辑假设水只会流向 1 个相邻的格子。这是一个有效的假设吗?

    逻辑和bfs分离

    1. 使用附加标签。 “A”可以代表浇水的房子。
    2. 使用附加标签可简化代码并避免将“H”向前修改为“W”,随后的迭代将错误地视为“W”(而它实际上是带有“W”的“H”而不是最初的“ W')
    3. 2 循环在另一个外部函数中,如果在单元格中看到“W”,则调用另一个函数
    4. 第二个函数将运行带有方向的 for 循环并更新相邻位置(如果它们是 'H')
    5. 最后再运行一个 2 循环并将所有 'A' 更改为 'W' 并更改颜色
    6. 您也可以为土地添加类似的检查
    // can make this an unmodifiable list to avoid accidental modification
    //                         LU   L  LD   U   D  RU   R   RD
    final int[] x = new int[] {-1, -1, -1,  0,  0,  1,  1,  1};
    final int[] y = new int[] {-1,  0,  1, -1,  1, -1   0,  1}; 
    final int adjCount = 8;
    final char WATER = 'W';
    final char HOUSE = 'H'
    final char WATERED_HOUSE = 'A'; 
    
    int process(char[][] input) {
      int count = 0; // this is just to track and for any optimization
    
      // initial processing to process cells adjacent to water
      for (int row = 0; row < input.length; row++) {
        for (int col = 0; col < input[row].length; col++) {
          if (WATER == input[row][col]) {
            count += processAdjacents(input, row, col);
          }
        }
      }
    
      final int modified = count;
    
      // second round to set watered house to water and color
      for (int row = 0; row < input.length; row++) {
        // if needed can use count == 0 to break;
        for (int col = 0; col < input[row].length; col++) {
          // if needed can use count == 0 to break;
    
          if (WATERED_HOUSE == input[row][col]) {
            input[row][col] = WATER;
            // set background color also
            count--;
          }
        }  
      }
      return modified;
    }
    
    // process adjacent cells of water cell
    int processAdjacents(char[][] input, final int row, final int col) {
      int count = 0;
      for (int adj = 0; adj < adjCount; adj++) {
        final int hor = col + x[adj];
        final int ver = row + y[adj];
        
        if (isValid(input, ver, hor) && HOUSE == input[ver][hor]) {
          input[ver][hor] = WATERED_HOUSE;
          count++;
        }
      }
      return count;
    }
    
    // check whether given cell is within grid
    boolean isValid(char[][] input, final int row, final int col) {
      return row >= 0 && row < input.length && col >= 0 && col < input[row].length;
    }
    

    免责声明

    1. 未经测试的代码并输入 SO
    2. 没有使用 DFS
    3. 土地未处理

    【讨论】:

    • 不,我相信它要求立即更改所有适用的水砖,这意味着您必须确定需要更改哪些瓷砖然后更改它们 -> 重复多次,直到所有适用的瓷砖都被更改,因此递归,问题是我不知道该怎么做。
    猜你喜欢
    • 2010-10-30
    • 2015-12-22
    • 2020-07-30
    • 2014-02-03
    • 2013-08-25
    • 1970-01-01
    • 2014-03-07
    • 2019-10-07
    • 2014-03-31
    相关资源
    最近更新 更多