使用递归方式写的走迷宫算法(Java)

这段时间在补Java基础,是有点感觉。昨天老师给了个算法题,要求写一个走迷宫的算法出来。我之前可以说从未写过什么算法,一直都只是在机械地码代码,确实,这种码农没太大价值。是该写写算法提升一下自己了。
然后这个算法我没有参考过任何资料,也没看过任何其他人写好的代码,完完全全是自己摸索出来的。当时一整个下午都不知道该如何入手,勉强写了一个也走不出去,脑袋一片混乱。然后就搁置了。到了晚上11点过后打算重写,不过这个时候我惊奇地发现自己的思维无比的清晰,只花了一个小时左右就走出去了,不过这个算法肯定不是最忧算法,它仅仅只是走出了这个迷宫而已,甚至没有做最优路径处理,但也先这样了。刚开始练算法,要求不需要太高。
整体思路是这样的:创建一个ArrayDeque栈来保存老鼠走过的路径坐标。程序启动即找出老鼠的坐标。以该坐标点为初始值检测上、下、左、右四个方向是否有通道,当然,在检测前还必须先判断当前坐标点的四向坐标是否有效,即是否越界,通过一个boolean isLocCor(int x,int y)方法来判断。若在上方检测到有通路,即将当前的坐标入栈,将当前坐标标为已走过路段(以字符’@’表示),将上方坐标入栈,并以上方坐标为新坐标值进行检测,即递归此search(int x,int y)方法。若在上方没有检测到可通行的路,即将记录变量failCount自加1.若在上方检测到出口’e’,即将当前坐标标为已走过路段,并将boolean标志finish置为true,结束当前方法。完成寻路。当四个方向都没有检测到可通行的路时,此时的failCount变量的值应为4,此时会将当前坐标标志为“死路”状态(以’n’)表示,并将当前栈顶的元素弹出。
以此规则递归,最终即能得出正确的路径来。
当然,再次声明,本算法仅仅是实现了找到出路的功能而已,没有做其它优化。

package maze;

import java.util.ArrayDeque;

public class MazeTest {
    /*
     * 使用递归求出路径。
     * */
    /*迷宫1
     * private char[][] maze = new char[][]{
        {'1','1','1','1','1','1','1','1','1','1','1'},
        {'1', 0,  0,  0,  0,  0, '1', 0,  0,  0, '1'},
        {'1', 0, '1', 0, '1','1','1', 0, '1', 0, '1'},
        {'e', 0, '1', 0,  0,  0,  0,  0, '1', 0, '1'},
        {'1', 0, '1','1','1','1','1', 0, '1', 0, '1'},
        {'1', 0, '1', 0, '1', 0,  0,  0, '1','1','1'},
        {'1', 0,  0,  0, '1', 0, '1','1','1', 0, '1'},
        {'1','1','1','1','1', 0, '1', 0,  0,  0, '1'},
        {'1', 0, '1','m','1', 0, '1',0, 0,  0, '1'},
        {'1', 0,  0,  0,  0,  0, '1', 0,  0,  0, '1'},
        {'1','1','1','1','1','1','1','1','1','1','1'},
    };*/

    /*
     * 迷宫2
    private char[][] maze = new char[][]{
            {'1',   '1', '1',    '1', '1', '1', '1', '1', '1', '1', '1'},
            {'1',   0, 0,    0, 0, 0, '1', 0, 0, 0, '1'},
            {'1',   0, '1',    0, 0, 0, '1', 0, '1', 0, '1'},
            {'e',   0, '1',    0, 0, 0, 0, 0, '1', 0, '1'},
            {'1',   0, '1',    '1', '1', '1', '1', 0, '1', 0, '1'},
            {'1',   0, '1',    0, '1', 0, 0, 0, '1', 0, '1'},
            {'1',   0, 0,    0, '1', 0, '1', 0, 0, 0, '1'},
            {'1',   '1', '1',    '1', '1', 0, '1', 0, 0, 0, '1'},
            {'1',   0, '1',    'm', '1', 0, '1', 0, 0, 0, '1'},
            {'1',   0, 0,    0, 0, 0, '1', 0, 0, 0, '1'},
            {'1',   '1', '1',    '1', '1', '1', '1', '1', '1', '1', '1'},
        };
        * /

    /*
     * 迷宫3
     * 
     * */
    private char[][] maze = new char[][]{
            {'1','1','1','1','1','1','1','1','1','1','1'},
            {'1', 0,  0,  0,  0,  0, '1', 0,  0,  0, '1'},
            {'1', 0, '1', 0, '1','1','1', 0, '1', 0, '1'},
            {'e', 0, '1', 0,  0,  0,  0,  0, '1', 0, '1'},
            {'1', 0, '1','1','1','1','1', 0, '1', 0, '1'},
            {'1', 0, '1', 0, '1', 0,  0,  0, '1', 0,'1'},
            {'1', 0,  0,  0, '1', 0, '1', 0,'1',  0, '1'},
            {'1','1','1','1','1', 0, '1', 0,  '1',0, '1'},
            {'1', 0, '1','1','1', 0, '1',0,'1', 0, '1'},
            {'1', 0,  0,  0,  0,  0, '1', 0,  0, '1', '1'},
            {'1','1','1','1','1','1','1','1',0,'m','1'},
        };

    private char pass = '@';
    private char noPass = 'n';
    private boolean finish = false;

    //定义一个用于存储老鼠走过的路径的栈集合。
    ArrayDeque<MouseLoc> aDeque = new ArrayDeque<>();
    //定义一个用于保存老鼠位置的类。
    MouseLoc mLoc = new MouseLoc();
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        MazeTest mt = new MazeTest();
        mt.init();
    }

    void init(){
        //打印出初始状态。
        printMaze();        
        //找到老鼠当前位置。
        this.findMouse();
        System.out.println("老鼠的初始位置为:(" + mLoc.x + "," + mLoc.y + ")");
        //把老鼠的初始位置加入到栈中。
        aDeque.offerFirst(mLoc);
        //开始搜寻出路(递归)。
        search(mLoc.x,mLoc.y);

        //寻路完毕,整理老鼠的路径。
        for(int i=0;i<maze.length;i++)
        {
            for(int j=0;j<maze[i].length;j++)
            {
                if(maze[i][j] == noPass){
                    maze[i][j] = 0;
                }
            }
        }
        System.out.println("寻路结果为:\n");
        printMaze();

        System.out.println("老鼠走过的路径为:");
        short stackSize = (short)aDeque.size();
        for(short i=0;i<stackSize;i++){
            MouseLoc ml = aDeque.removeLast();
            System.out.println((1+i)+"、("+ml.x+","+ml.y+")");
        }
    }// init method -- end.

    void search(int x,int y){
        int failCount = 0;
        //if(isLocCorr(x-1,y)){
            if (!finish && maze[x-1][y] == 0) {
                /*
                 * 如果检测到上方路段为可走空间,则去走,并
                 * 将此此空间标记为已走过路段。
                 * */
                aDeque.offerFirst(new MouseLoc(x - 1, y)); // step1. push into stack.
                maze[x][y] = pass;//step2. sign it.
                search(x-1,y);// step3. new search.
                if(maze[x-1][y] == noPass){
                    failCount++;
                }
            } else if (maze[x - 1][y] == 'e') {
                /*
                 * 如果检测到它是一个出口,则把当前位置标为已走过。
                 * 然后再把出口位置入栈,最后把出口位置标为已走过。
                 * 完成寻路。
                 * */
                maze[x][y] = pass;
                aDeque.offerFirst(new MouseLoc(x-1,y));
                maze[x - 1][y] = pass;
                finish = true;
                return;
            }else{
                failCount++;
            }
        }else{
            //如果位置检测不通过,也得让failCount的值自加1.
            failCount++;
        }


        //if(isLocCorr(x+1, y)){
            if (!finish && maze[x + 1][y] == 0) {
                aDeque.offerFirst(new MouseLoc(x + 1,y));
                maze[x][y] = pass;
                search(x+1,y);
                if(maze[x+1][y] == noPass){
                    failCount++;
                }
            } else if (maze[x + 1][y] == 'e') {
                maze[x][y] = pass;
                aDeque.offerFirst(new MouseLoc(x-1,y));
                maze[x+1][y] = pass;
                finish = true;
                return;
            }else{
                failCount++;
            }
        }else{
            //如果位置检测不通过,也得让failCount的值自加1.
            failCount++;
        }

        //if(isLocCorr(x, y-1)){
            if (!finish && maze[x][y - 1] == 0) {
                aDeque.offerFirst(new MouseLoc(x, y - 1));
                maze[x][y] = pass;
                search(x,y-1);
                if(maze[x][y-1] == noPass){
                    failCount++;
                }
            } else if (maze[x][y - 1] == 'e') {
                maze[x][y] = pass;
                aDeque.offerFirst(new MouseLoc(x,y-1));
                maze[x][y-1] = pass;
                finish = true;
                return;
            }else{
                failCount++;
            }
        }else{
            //如果位置检测不通过,也得让failCount的值自加1.
            failCount++;
        }

        //if(isLocCorr(x, y+1)){
            if (!finish && maze[x][y + 1] == 0) {
                aDeque.offerFirst(new MouseLoc(x, y + 1));
                maze[x][y] = pass;
                search(x,y+1);
                if(maze[x][y+1] == noPass){
                    failCount++;
                }
            } else if (maze[x][y + 1] == 'e') {
                maze[x][y] = pass;
                aDeque.offerFirst(new MouseLoc(x,y+1));
                maze[x][y+1] = pass;
                finish = true;
                return;
            }else{
                failCount++;
            }
        }else{
            //如果位置检测不通过,也得让failCount的值自加1.
            failCount++;
        }

        if(failCount == 4){
            MouseLoc m = aDeque.pop();
            maze[m.x][m.y] = noPass;
        }
    }// search method  --  end.

    void printMaze(){
        //专门打印迷宫阵列。
        for(int i=0;i<maze.length;i++)
        {
            for(int j=0;j<maze[i].length;j++)
            {
                System.out.print(maze[i][j]);
            }
            System.out.println("");
        }
    }

    private boolean isLocCorr(int x,int y){
        //用于判断给定的位置坐标是否超出迷宫范围。
        if(x<0 || y<0 || x>findYLength()-1 || y>findXLength()-1){
            return false;
        }
        return true;
    }

    private int findYLength() {
        //返回迷宫上下距离。(y)
        return maze.length;
    }

    private int findXLength() {
        //返回迷宫左右距离。(x)
        return maze[0].length;
    }

    void findMouse(){
        //用于寻找老鼠的起始位置。
        for(int i=0;i<maze.length;i++)
        {
            for(int j=0;j<maze[i].length;j++)
            {
                if(maze[i][j] == 'm'){
                    mLoc.x = i;
                    mLoc.y = j;
                    return;
                }
            }
        }
    }// findMouse method  -- end.

}

以下是用于保存路径坐标的类。

package maze;

public class MouseLoc {
    public int x;
    public int y;
    MouseLoc(){

    }
    MouseLoc(int x,int y){
        this.x = x;
        this.y = y;
    }
}
    原文作者:迷宫问题
    原文地址: https://blog.csdn.net/u012594358/article/details/47357341
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞