簡體   English   中英

如何避免遞歸MazeSolver中的StackOverflow錯誤

[英]How to avoid StackOverflow Error in Recursive MazeSolver

像大學里的許多其他Java學生一樣,我需要開發一個解決迷宮的迷宮程序。 我實現遞歸的SolveMaze方法返回了stackoverflow運行時錯誤。 請問該如何解決? 這和我的算法有關嗎? 提前致謝。

A)我創建了一個解決方案迷宮,該迷宮將保留通往出口的路徑。

B)然后,我實現了方法solveMaze() ,該方法在每次調用時都朝着退出邁進了一步。

注意: isWall()方法檢查您要移動到的位置是否是牆。

  public void showPath() {
    int[][] sol = new int[m.length][m[0].length];
    for (int j = 0; j < sol.length; j++) {
      for (int i = 0; i < sol[0].length; i++) {
        sol[j][i] = m[j][i];
      }
    }
    if (solveMaze(sol, m.length - 1, 0, exitCords) == false)
      System.out.println("Solution doesn't exist");
    else {
      for (int y = 0; y < sol.length; y++) {
        for (int x = 0; x < sol[0].length; x++) {
          if (sol[y][x] == exitCords[0] && sol[y][x] == exitCords[1]) {
            System.out.print("E ");
          } else {
            if (sol[y][x] == 1) {
              System.out.print("  ");
            } else if (sol[y][x] == 3) {
              System.out.print("~");
            } else {
              System.out.print("# ");
            }
          }

        }
        System.out.println();
      }
    }
  }

  public boolean solveMaze(int[][] sol, int y, int x, int[] exitCords) {
    //exitCords[] is a one-dimensional array that holds the x and y coordinate of the exit point on a maze.
    if (y == exitCords[1] && x == exitCords[0]) {//Base Case
      return true;
    }
    //North
    if (!isWall(x, y - 1) && sol[y - 1][x] != 3) {
      sol[y][x] = 3;//3 is assigned to positions you already visited.
      y--;
      sol[y][x] = 3;
      //Implement recursion to call the solveMaze again on this line.
      solveMaze(sol, y, x, exitCords);
      return true;
    }

    //South
    else if (!isWall(x, y + 1) && sol[y + 1][x] != 3) {
      sol[y][x] = 3;
      y++;
      sol[y][x] = 3;
      solveMaze(sol, y, x, exitCords);
      return true;
    }
    //East
    else if (!isWall(x + 1, y) && sol[y][x + 1] != 3) {
      sol[y][x] = 3;
      x++;
      sol[y][x] = 3;
      solveMaze(sol, y, x, exitCords);
      return true;
    }
    //West
    else if (!isWall(x - 1, y) && sol[y][x - 1] != 3) {
      sol[y][x] = 3;
      x--;
      sol[y][x] = 3;
      solveMaze(sol, y, x, exitCords);
      return true;
    }
    /*The following line of code are to get out of dead ends and replace every position near a dead end with a wall*/
    else if ((isWall(x, y - 1) && isWall(x, y + 1) && isWall(x + 1, y)) || (isWall(x, y - 1) && isWall(x, y + 1) && isWall(x - 1, y))
        || (isWall(x - 1, y) && isWall(x, y + 1) && isWall(x + 1, y)) || (isWall(x - 1, y) && isWall(x, y - 1) && isWall(x + 1, y))) {

      if (isWall(x, y - 1) && isWall(x, y + 1) && isWall(x + 1, y)) {
        sol[y][x] = 0;
        solveMaze(sol, y, x - 1, exitCords);
        return true;
      }
      if (isWall(x, y - 1) && isWall(x, y + 1) && isWall(x - 1, y)) {
        sol[y][x] = 0;
        solveMaze(sol, y, x + 1, exitCords);
        return true;
      }
      if (isWall(x - 1, y) && isWall(x, y + 1) && isWall(x + 1, y)) {
        sol[y][x] = 0;
        solveMaze(sol, y - 1, x, exitCords);
        return true;
      }
      if (isWall(x - 1, y) && isWall(x, y - 1) && isWall(x + 1, y)) {
        sol[y][x] = 0;
        solveMaze(sol, y + 1, x, exitCords);
        return true;
      }
    }
    return false;
  }

堆棧溢出錯誤意味着您的遞歸超出了語言允許的范圍。 對於小迷宮, 除非您正在迷宮中重新定位, 否則不應發生這種情況。 由於您的代碼似乎沒有做出任何努力來避免這種情況,因此您可能需要修復該問題。

您有不同的方法來解決問題:

  • 第一個是不使用遞歸來重寫代碼(尾遞歸沒有運氣-Java沒有對此進行優化
  • 另一種方法是使用-Xss選項增加堆棧大小
  • 或者,您可以添加實際的深度檢查以解決solveMaze方法,例如:
  public void showPath() {
    // ...
    if (solveMaze(sol, m.length - 1, 0, exitCords , 0) == false) {
    // ...
  }

  public boolean solveMaze(int[][] sol, int y, int x, int[] exitCords, int depth) {
    if (depth > 64) {
      return false;
    }
    // ...
    solveMaze(sol, y, x, exitCords, depth + 1); 
    // ...  
  }

暫無
暫無

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

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