簡體   English   中英

Java學習迷宮求解器

[英]Java learning maze solver

我一直在研究一些代碼,以引導“機器人”穿過迷宮,迷宮中有多個死角,並且有一條通往目標的正確路徑,如下所示:

我已經使用堆棧記錄了機器人第一次到達具有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);}

}

最佳方法表明了我為解決該問題所做的嘗試,但是它所做的只是使機器人在每個路口直行

例如這個迷宮

在此處輸入圖片說明

會讓我失望的是:東,東,南,南,東,南,南,東,東,東,南,南,東,東,東,東,南,東,南

確實可以使用堆棧和對迷宮的詳盡搜索來解決此問題。 有更有效的方法,但是這種方法可以工作。

知道代碼的意圖是相當困難的,因為您只給出了一部分。 但是,總的來說,這類窮舉搜索大量使用了遞歸-這是堆棧的一種非常常見的用例。 我假設您的代碼也一樣,盡管在您提供的示例中看不到該代碼。

這是一些示例性偽代碼,用於詳盡的“深度優先”搜索。 該代碼將以所有可能的解決方案而不僅僅是一種解決方案。 您應該有一個在代碼中看起來像這樣的方法。

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 *),然后一旦路徑通過,就可以確定機器人的方向列表。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM