【问题标题】:Maze path finder in JavaJava中的迷宫路径查找器
【发布时间】:2016-03-22 17:22:41
【问题描述】:

我正在尝试使用递归来解决迷宫问题。在下面的代码中,MazeCoord 是一个程序员创建的类型,它存储了一个坐标类型的位置。格式为 MazeCoord(int x, int y)。我的程序现在编译时,到达方法的某些部分并忽略其他部分,因此在所有情况下都说“未找到路径”,并且只将开始位置存储在 LinkedList mazePath 中。 search() 方法中有一个注释掉的部分,这是我尝试的另一种方法,但我很确定这是错误的,而不是这样做的方法。

感谢任何帮助。

递归代码:

/** 返回穿过迷宫的路径。第一个元素是起始位置,并且 最后一个元素是退出位置。如果没有路径,或者如果这被称为 搜索前,返回空列表。

@return 迷宫路径 */

public LinkedList<MazeCoord> getPath() {
       return mazePath; 
}

/** 找到一条穿过迷宫的路径(如果有的话)。客户端可以访问 通过 getPath 方法找到的路径。 @return 是否找到路径。 */

public boolean search() {  
       currentLoc = new MazeCoord(startLoc.getRow(), startLoc.getCol());
       visitedPath = new boolean[mazeData.length][mazeData[0].length];

       mazePath=new LinkedList<MazeCoord>();

       if(hasWallAt(startLoc) || hasWallAt(endLoc)){    
       return false;
       }
       else{
           mazePath.add(currentLoc);
           return appendToSearch(currentLoc.getRow(), currentLoc.getCol());
       }

       /**
       System.out.println("try1");
       mazePath.add(new MazeCoord(startLoc.getRow(), startLoc.getCol()));
       boolean searchResult = appendToSearch(numRows()-1, numCols()-1);

       System.out.println("test: " + searchResult);
       System.out.println("test2: row, col --> " + (numRows()-1) + " , " +  (numCols()-1));
       System.out.println("test3: wallValue:" + hasWallAt(new  MazeCoord(numRows()-1,numCols()-1)));

       if(searchResult){
           System.out.println("try2");
           mazePath.add(new MazeCoord(numRows()-1, numCols()-1));
       }
       return searchResult;
       */
   }

/**将执行的 search() 方法的帮助函数 实际递归获得通过迷宫的路径 @param row 当前位置所在的行 @param col 当前位置的列 @return true 如果路径可用 */

    private boolean appendToSearch(int row, int col) {


        //Check if within the maze
        if((row - 1 < 0) || (col - 1 < 0) || (row + 1 > numRows()) || (col + 1 >  numCols())){
            return false;
        }
        //Check if the position is the exit location
        if(row == endLoc.getRow() && col == endLoc.getCol()){
            mazePath.add(new MazeCoord(row, col));
            return false;
        }
        //Check for Wall
        if(hasWallAt(new MazeCoord(row, col))){
            return false;
        }
        //Check if the position has already been visited
        if(visitedPath[row][col]){
            return false;
        }
        //If all pass --> add to visitedPath
        visitedPath[row][col]=true;

        //Check to the Right
        if(appendToSearch(row, col + 1)){
           mazePath.add(new MazeCoord(row, col + 1));
           return true;
        }
        //Check Downwards
        else if(appendToSearch(row + 1, col)){
            mazePath.add(new MazeCoord(row + 1, col));
            return true;
        }
        //Check to the Left
        else if(appendToSearch(row, col - 1)){
            mazePath.add(new MazeCoord(row, col - 1));
            return true;
        }
        //Check Upwards
        else if(appendToSearch(row - 1, col)){
            mazePath.add(new MazeCoord(row - 1, col));
            return true;
        }
        return false;
    }

【问题讨论】:

    标签: java recursion path maze


    【解决方案1】:

    首先,我想向您推荐this link,它解释了最常见的寻路算法之一。

    你也可以在here找到一个简短的教程 在我看来,本教程将很好地满足您的要求,因为它以网格为例。

    不需要使用递归函数来执行寻路算法。 你可以做的是保存两个列表:一个已经'checked'单元格/图块,另一个还没有。

    您将从您想要开始路径的点开始,并检查从该点可以到达的所有单元格/图块,例如:

    void addCells(Point current) {
       // Left
       if (emptyAndNotChecked(current.x-1,current.y)) // Checking for walls here
          cellsToCheck.add(new Point(x-1,y)) // Adding this cell to the list
       // Right
       if (emptyAndNotChecked(current.x+1,current.y))
          cellsToCheck.add(new Point(x+1,y))
       // Top
       if (emptyAndNotChecked(current.x,current.y+1))
          cellsToCheck.add(new Point(x,y+1))
       // Bottom
       if (emptyAndNotChecked(current.x,current.y-1))
          cellsToCheck.add(new Point(x,y-1))
    }
    

    emptyAndNotChecked() 只检查给定位置是否不是墙并且尚未检查。 当然你也可以进行对角线检查!

    此时,您想要找到下一个您想要添加更多单元格的单元格/图块,您可以通过检查所有“未选中”的单元格/图块并将其应用于每个“权重”函数将为您提供给定目的地的最佳单元格/图块,基本实现可能是这样的:

    float weight(Point current,Point end) {
       return Math.sqrt(Math.pow(current.x-end.x,2)+Math.pow(current.y-end.y,2));
    }
    

    此功能将允许您找到最适合导航到的单元格/图块,一旦找到它(权重最低的那个),您就可以移动到这个并再次调用第一个函数来添加更多的单元格/图块。

    当您移动到的单元格/图块是目的地或调用addCells() 您没有添加任何新的单元格/图块时,您将停止。

    当然,这只是一种基本的方法,还有很多可以应用的改进。 希望这有帮助!

    【讨论】:

    • 嗨,卢克,感谢您的回复。我会查看您提供的链接。不过,关于递归,我必须使用递归找到路径,这是一个要求,所以我无法绕过它。我觉得我对代码的想法是正确的,只是我实现它的方式是错误的。我对已访问或未检查的点使用布尔二维数组。它在我的代码中称为visitedPath。你知道为什么我的代码的某些部分无法访问吗?
    • 您好,当您检查其他方向时,如果其中一个有效,则使用return true,但您不应该返回,否则其中一些方向将永远不会被检查!您可以声明一个标志boolean added = false,然后,对于您检查的每个方向,如果appendToSearch() 返回true,则将其设置为true,然后在函数末尾您只需编写return added;
    • 嗨,卢克,感谢您的提示。我也试试看。
    • 嗨@Luke,更新代码。我做了你建议的改变。它有效,但仅适用于代码的一次迭代。另外,search() 方法仍然没有达到 if 语句条件,它直接进入 else 语句条件。
    • 你说的是 if 语句:` if(hasWallAt(startLoc) || hasWallAt(endLoc))`?如果是这样,代码进入 else 语句应该没问题!请问你为什么要使用递归来做到这一点?如果迷宫足够大,它可能会导致你在调用中获得巨大的筹码!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-08
    • 1970-01-01
    • 2018-03-24
    • 2023-03-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多