【问题标题】:Java learning maze solverJava学习迷宫求解器
【发布时间】:2015-02-03 00:57:24
【问题描述】:

我一直在编写一些代码来引导“机器人”通过具有多个死角和 1 条通往目标的正确路径的迷宫,如下所示:

我使用堆栈来记录机器人第一次到达具有 3 或 4 个可能出口的方格时所面对的方向,如果所有相邻方格都已被访问过,则使用 pop() 使机器人从它最初来自的方向(与到达的方向相反)。在运行结束时,堆栈包含到达目标路线上所有方格的方向。按照堆栈的相反方向将机器人从目标带回起点。我正在努力找出如何使用此堆栈,以便在下一次运行时机器人将采用最佳路径到达目标。

我的一些代码:

private int pollRun = 0; // Incremented after each pass
private int explorerMode; // 1 = explore, 0 = backtrack

public void exploreControl(IRobot robot) {

  byte exits = nonwallExits(robot);
  int direction;

  switch (exits) { //passes control to respective method
    case 1: direction = deadEnd(robot);   break;
    case 2: direction = corridor(robot); break;
    case 3: direction = junction(robot); break;
    default: direction = crossroads(robot); break;
  }

  if (exits == 1) {explorerMode = 0;}

  robot.face(direction); 

  pollRun++;

}

public void backtrackControl(IRobot robot) {

  byte exits = nonwallExits(robot);
  int direction = IRobot.CENTRE;

  switch (exits) { //passes control to respective method
    case 1: direction = deadEnd(robot);   break;
    case 2: direction = corridor(robot); break;
    default: direction = junction(robot); break; // do nothing
  }

  if (exits > 2) {
    if (passageExits(robot) > 0){
      exploreControl(robot);
      explorerMode = 1;
      pollRun++;
      return;
    } else {
      robot.setHeading(st.pop());
      robot.face(IRobot.BEHIND);
      pollRun++;
      return;
    }

  }

    robot.face(direction); 

  pollRun++;

}

public void optimal(IRobot robot) {

  byte exits = nonwallExits(robot);
  int direction;
  int heading;

  for(int i = 0; i < st.size(); i++) {
    stNew.push(st.pop());
  }

  if (exits < 3) {

    switch (exits) { //passes control to respective method
      case 1: direction = deadEnd(robot);   break;
      default: direction = corridor(robot); break;
    }

    robot.face(direction);

  } else {
    robot.setHeading(stNew.pop());
  }

}

public void controlRobot(IRobot robot) {

  if ((robot.getRuns() == 0) && (pollRun == 0)) {
    robotData = new RobotData(); //reset the data store
    explorerMode = 1;
  }

  if (robot.getRuns() = 1) {
    optimal(robot);
    return;
  }

  if (robot.getRuns() <= 0 && (nonwallExits(robot) >= 3)
      && (beenbeforeExits(robot) <= 0)) {
    st.push(robot.getHeading());
  }

  if (explorerMode == 1) {
    exploreControl(robot);
  } else {backtrackControl(robot);}

}

最佳方法展示了我尝试解决它的方法,但它所做的只是让机器人在每个路口直行

比如这个迷宫,

会让我留下堆栈:EAST,EAST,SOUTH,SOUTH,EAST,SOUTH,SOUTH,EAST,EAST,SOUTH,SOUTH,EAST,EAST,EAST,SOUTH,EAST,SOUTH

【问题讨论】:

  • 我不认为堆栈是正确的方法。要找到最佳解决方案,您需要构建一个完整的迷宫图,然后进行广度优先搜索。
  • 这是解决问题的可能方法之一,但有人告诉我使用堆栈要简单得多。
  • 如果你构建了一个完整的迷宫图,这会使它成为一个不真实的场景,你需要假设迷宫图对他来说是未知的,想想迷宫上的一个物理机器人试图找到出口,听起来更像是在真实场景中,您将使用深度搜索并走可能的路径,记录沿途发现的路径。
  • 我之前回答过一个类似的问题,它只使用堆栈。不知道是否有帮助:stackoverflow.com/a/22187419/395202

标签: java stack maze prims-algorithm


【解决方案1】:

确实,这个问题可以使用堆栈和对迷宫的详尽搜索来解决。有更有效的方法,但这一种会奏效。

很难知道您的代码打算如何运行,因为您只提供了其中的一部分。然而,一般来说,这些详尽的搜索会大量使用递归——这是堆栈的一个非常常见的用例。我假设您的代码也是如此,但我在您提供的示例中看不到该代码。

这里是一个详尽的“深度优先”搜索的示例伪代码。这段代码最终会得到所有可能的解决方案,而不仅仅是一个。您的代码中应该有一个类似这样的方法。

void findPath(Stack currentPath) {
    if (currentPath.peek() == goal) {
        solutions.add(currentPath);
    } else {
        for (Position next: currentPath.openPositions()) {
            currentPath.push(next);
            findPath(currentPath);
            currentPath.pop();
        }
    }
}

“openPositions”方法需要通过查看当前路径显式停止任何加倍返回 - 换句话说,它不应该返回任何已经在 currentPath 堆栈中的位置,否则您将得到无限递归。

因为这会找到所有可能的解决方案,所以您需要找到具有最短长度的解决方案作为最佳路径。在您的情况下,迷宫似乎只有一条路径,因此您可以在找到路径后立即退出。

最后一点:您尝试将设置机器人需要转向的方向的任务与寻找穿过迷宫的路径的任务混为一谈。我建议将这些分开。使用上面的算法找到一条路径(或更有效的路径,例如 a*),然后一旦你有路径穿过它,就可以确定机器人的方向列表。

【讨论】:

  • 我在发布此问题后再次阅读了您的问题,我现在意识到您正在尝试模拟机器人通过迷宫寻找路径,而不是找到最佳路径然后指导机器人走。这显然就是为什么你不能按照上面的评论员的建议去做(即制作迷宫图)。我仍然相信我上面给出的算法是正确的——唯一的变化是你需要一个单独的列表(不是 currentPath)来记录搜索过程中的动作。
猜你喜欢
  • 2011-09-22
  • 2014-04-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-03-02
  • 1970-01-01
  • 2013-04-16
相关资源
最近更新 更多