简体   繁体   English

递归迷宫求解器问题

[英]Recursive Maze Solver Issue

I'm making a recursive Java maze program and I'm stuck on the part when it comes to calling to my subroutines goNorth() , goWest() , goEast() and goSouth() . 我正在goNorth()一个递归Java迷宫程序,在调用子例程goNorth()goWest()goEast()goSouth() Basically my problem involves the fact that it calls to one subroutine, but within that subroutine it doesn't pick up on my other else if and else statements therefore not making it pick up on the other possibilities. 基本上,我的问题涉及以下事实:它调用了一个子例程,但是在该子例程中,if和else语句没有对我的其他子例程起作用,因此不会使它在其他可能性上起作用。 Please assist, I appreciate your upcoming answer. 请协助,感谢您即将收到的答复。

import java.util.*;
import java.io.*;

public class RecursiveMazeSolverv2 {

  static Scanner in;
  static int row = 0;
  static int col = 0;
  static char maze[][];
  static int rowSize = 0;
  static int colSize = 0;
  static boolean success = true;

  public static void main(String[] args) {

    while (true) {
      try {
        in = new Scanner(new File("Maze1.txt")); 
        break;
      }
      catch (FileNotFoundException e) {
        System.out.println("Wrong File"); 
      }
    }
    rowSize = Integer.parseInt(in.nextLine());
    colSize = Integer.parseInt(in.nextLine());

    maze = new char[rowSize][colSize];

    String lineOfInput = "";
    for (int i = 0; i < maze.length; i++) {
      lineOfInput = in.nextLine();
      for (int j = 0; j < maze.length; j++) {
        maze[i][j] = lineOfInput.charAt(j);
      }
    }

    displayGrid();

    for (int i = 0; i < maze.length; i++) {
      for (int j = 0; j < maze.length; j++) {
        if (maze[i][j] == 'S') {
          maze[i][j]='+';
          System.out.println("Starting coordinates: " + i + ", " + j);
          row = i;
          col = j;
        }
      }
    }

if (goNorth(row, col))
  displayGrid();
else
  System.out.println("Impossible!");
  }


  static Boolean goNorth(int row, int col) {
    if (maze[row][col] == '.') {
      maze[row][col] = '+';
      return goNorth(row -1, col);
    }

    else if (maze[row][col] == 'G') {
      return true;
    }

    else {
      success = goNorth(row, col);
      if (success == false) {
        success = goWest(row, col -1); 
      }
      if (success == false) {
        success = goEast(row, col +1); 
      }
      if (success == false) {
        success = goSouth(row +1, col); 
      }
      if (success == false) {
        maze[row][col] = '.';
        success = false; }
      return false; 
    }

  }
   static Boolean goWest(int row, int col) {
    if (maze[row][col] == '.') {
      maze[row][col] = '+';
      return goWest(row, col -1);
    }

    else if (maze[row][col] == 'G') {
      return true;
    }

    else {
     success = goWest(row, col);
      if (success == false) {
        success = goNorth(row -1, col); 
      }
      if (success == false) {
        success = goSouth(row +1, col); 
      }
       if (success == false) {
        success = goEast(row, col -1); 
       }
      if (success == false) {
        maze[row][col] = '.';
        success = false; }
      return false; 
    }

  }

   static Boolean goEast(int row, int col) {
    if (maze[row][col] == '.') {
      maze[row][col] = '+';
      return goEast(row, col +1);
    }

    else if (maze[row][col] == 'G') {
      return true;
    }

    else {
     success = goEast(row, col);
      if (success == false) {
        success = goNorth(row -1, col); 
      }
      if (success == false) {
        success = goSouth(row +1, col); 
      }
       if (success == false) {
        success = goWest(row, col -1); 
       }
      if (success == false) {
        maze[row][col] = '.';
        success = false; }
      return false; 
    }

  }


   static Boolean goSouth(int row, int col) {
    if (maze[row][col] == '.') {
      maze[row][col] = '+';
      return goSouth(row +1, col);
    }

    else if (maze[row][col] == 'G') {
      return true;
    }

    else {
     success = goSouth(row, col);
      if (success == false) {
        success = goNorth(row -1, col); 
      }
      if (success == false) {
        success = goWest(row, col -1); 
      }
       if (success == false) {
        success = goEast(row, col +1); 
       }
      if (success == false) {
        maze[row][col] = '.';
        success = false; }
      return false; 
    }

  }

  public static void displayGrid() {
    for (int j = 0; j < maze.length; j++) {
      for (int k = 0; k < maze.length; k++) {
        System.out.print(maze[j][k] + " "); 
      }
      System.out.println();
    }
  }
}

Sorry, I can't post the actual maze in here, it wont display right. 抱歉,我无法在此处发布实际的迷宫,它不会正确显示。

Problems I see: 我看到的问题:

  1. As others eluded to, you shouldn't make everything static . 正如其他人所躲避的那样,您不应使所有内容都保持static Without going into a super long and boring discussion, making everything static means that the values you set in your recursive calls will modify the value for all calls. 无需进行冗长而无聊的讨论,将所有内容设为static意味着您在递归调用中设置的值将修改所有调用的值。 You are effectively over-writing each recursive call with values you are setting in subsequent recursive calls. 您实际上正在使用在后续递归调用中设置的值来覆盖每个递归调用。 You will want to make most of those method-scoped variables so that the value will only be valid in the scope of that method call. 您将需要使用大多数这些方法范围的变量,以便该值仅在该方法调用的范围内有效。
  2. Your recursive calls are not in the same order. 您的递归调用顺序不同。 You need to do the same calls in the same step each time: Try North, then South, then East, then West. 您每次都需要在同一步骤中进行相同的呼叫:先尝试北,然后再进行南,然后再进行东,再进行西。 Whatever order you pick, the calls need to be in the same order. 无论选择哪种顺序,呼叫都必须以相同的顺序进行。 In fact, I am not really sure why you decided to have separate methods for each direction...why not have one method called "move" that tries to go North, then recurses, then tries to go South, then recurses, then tries to go East and recurses, then West and recurses. 实际上,我不太确定为什么您决定为每个方向使用单独的方法...为什么没有一种称为“移动”的方法尝试先向北,然后递归,然后尝试向南,然后递归,然后再尝试向东递归,然后向西递归。 The way you have things coded, there is no telling where the code will go in the maze, and most likely you will end up going around in circles. 您对事物进行编码的方式无法确定代码在迷宫中的去向,并且很可能最终会绕圈走动。
  3. This isn't directly linked to why it's not working, but you REALLY need to work on your code formatting, in particular your tabbing. 这与无法使用的原因没有直接关系,但是您确实需要处理代码格式,尤其是制表符。 Your code looks like it's all over the place. 您的代码看起来无处不在。 I can only imagine that that is making it WAY harder to troubleshoot that it needs to be. 我只能想象,这使得解决问题变得更加困难。

Edit - Example 编辑-示例

I will try to do this in a way to guide you without giving you a copy/paste answer, so this will be pseudo-code'ish. 我将尝试以某种方式指导您而不给您复制/粘贴答案,因此这将是伪代码。

/**
 * My move recursion
 */
public boolean move(int currRow, int currCol) {
  // See if we solved it...
  if (solved) {
    return true;
  }

  // Try to go north first...
  if (maze[currRow-1][currCol] == '.') {
    if (move(int currRow-1, currCol)) {
      // Mark this with the "good" path and return true
    }
  }

  // Try to go east next...
  if (maze[currRow][currCol+1] == '.') {
    if (move(int currRow, currCol+1)) {
      // Mark this with the "good" path and return true
    }
  }

  // Try to go south next...
  if (maze[currRow+1][currCol] == '.') {
    if (move(int currRow+1, currCol)) {
      // Mark this with the "good" path and return true
    }
  }

  // Try to go west...
  if (maze[currRow][currCol-1] == '.') {
    if (move(int currRow, currCol-1)) {
      // Mark this with the "good" path and return true
    }
  }

  return false;
}

So, basically we check if we are "solved". 因此,基本上,我们检查是否“已解决”。 If not, see if we can go north. 如果没有,看看我们是否可以向北走。 If we can, see if the next call is solved. 如果可以,请查看下一个呼叫是否已解决。 Repeat for east, south, and west. 重复东部,南部和西部。 Eventually one of the recursive calls will get to the solved condition, which will trigger each of the recursive calls to pass the inner if, which marks the maze and returns true, thus creating a chain reaction that ends up popping back up the call stack until you are done with the recursion. 最终,其中一个递归调用将达到已解决的条件,这将触发每个递归调用传递内部if,这会标记迷宫并返回true,从而产生连锁反应,最终连锁反应弹出调用堆栈,直到您完成了递归操作。

Things to note with recursion: 递归注意事项:

  1. It typically needs to be a process that can be broken into one or more repeatable, autonomous steps. 它通常需要是一个可以分解为一个或多个可重复的自主步骤的过程。 This doesn't mean it has to be one method, but if it's multiple methods you HAVE to perform things within the method in the same order. 这并不意味着它必须是一个方法,但是如果是多个方法,则您必须以相同的顺序在该方法中执行操作。 Otherwise, your logic get's out of sync. 否则,您的逻辑将不同步。
  2. It typically works best when you can break the "steps" into their smallest, most menial parts. 当您可以将“步骤”分解为最小,最容易处理的部分时,通常效果最佳。 Overly complex recursive methods makes for hard debugging and lots and lots of crazy branching and looping. 过于复杂的递归方法会导致难以调试以及大量疯狂的分支和循环。
  3. You have to have a VERY clear "end", else you will recurse until you blow the stack up. 您必须有一个非常清楚的“结束”,否则您将递归直到炸毁堆栈。
  4. There should be a very clear distinction between variables/data/information that are "method level" and things that are "global". 在“方法级别”的变量/数据/信息与“全局”的变量/数据/信息之间应该有非常清楚的区别。 In your case, the maze is global, the success and current position are not. 在您的情况下,迷宫是全球性的,成功和当前位置则不是。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM