分享一个暴力求解迷宫的爆栈算法--->嘤嘤嘤!

package day_one;

import javafx.util.Pair;

import java.util.Stack;

/**
 * 使用堆栈完成迷宫求解问题,寻找一条到达终点的路径
 * */
public class maze_solve {
    public static void main(String [] args)
    {
        char[][] maze = {{'1','1','1','1','1','1','1','1','1','1'},
                         {'1','0','0','1','1','1','0','0','1','1'},
                         {'1','0','0','1','1','0','0','1','0','1'},
                         {'1','0','0','0','0','0','0','1','0','1'},
                         {'1','0','0','0','0','1','1','0','0','1'},
                         {'1','0','0','1','1','1','0','0','0','1'},
                         {'1','0','0','0','0','1','0','1','0','1'},
                         {'1','0','1','1','0','0','0','1','0','1'},
                         {'1','1','0','0','0','0','1','0','0','1'},
                         {'1','1','1','1','1','1','1','1','1','1'}};
        int start_x=8,start_y=1, end_x = 7,end_y = 8;
        search_run(maze,start_x,start_y,end_x,end_y);

    }
    private static void search_run(char[][] maze, int start_x, int start_y, int end_x, int end_y)
        {
            search_path sp = new search_path();
            sp.search_maze_path(maze,start_x,start_y,end_x,end_y);
        }
    }


/**
 *构造一个一个迷宫单元的类,该类包含迷宫单元(坐标)的点的所有属性
 *      1、坐标点(x,y)
 *      2、是否被访问过(boolean visited)
 *      3、标记路径 char=''; '1'表示是墙,‘0’表示为通路,‘*’表示起点到终点的路径
 * */

class cell{
    int x = 0;
    int y = 0;
    //默认所有点都没有被访问过
    boolean visited = false;
    //用于标记二维数组中的通路、非通路、起点到终点的路径
    char flag;
    cell(int x,int y,boolean visited, char flag)
    {
        this.x = x;
        this.y = y;
        this.visited = visited;
        this.flag = flag;
    }
}

/***
 *
 * */
class search_path{

    /**
     * maze:一个二维数组、start_x,start_y,end_x,end_y表示起点和终点的x、y坐标值
     * */
    void search_maze_path(char[][] maze, int start_x, int start_y, int end_x, int end_y)
    {
        //首先需要初始化迷宫单元(设置迷宫单元的属性)
        cell[][] cells =creatCell(maze);
        //打印迷宫maze
        print_maze(cells);
        //设置起点
        cell start_cell = cells[start_x][start_y];
        cell end_cell = cells[end_x][end_y];
        //申请一个可以存放多属性的二维数组的栈stack
        Stack<cell> stack = new Stack<cell>();
        //将起点入栈
        stack.push(start_cell);
        //入栈之后就需要将起点标记为已经访问过
        start_cell.visited = true;
        //弹栈
        while(!stack.isEmpty())
        {
            //查看栈顶的元素
            cell current = stack.peek();
            //如果当前的栈顶元素与终点相等,那么就说明找到一条从起点到终点的路径,则开始:1、弹栈和2、标记
            if(current==end_cell)
            {
                while(!stack.isEmpty())
                {
                    //1、弹栈
                    cell c = stack.pop();
                    //2、标*,标记为*也需要分情况
                    c.flag = '*';
                    //在沿着栈中的数据园路返回时,在某些节点的四邻域存在一些没有继续向下探索的点,对于这些点就直接弹栈
                    while(!stack.isEmpty()&&!isNeighborCoordinate(stack.peek(),c))
                    {
                        stack.pop();
                    }
                }
            System.out.println("find the route from start_point to end_point");
                //打印出来路线
                print_maze(cells);
            }
            //如果栈顶元素不是终点就需要入栈操作,即继续搜寻下一个可能的点入栈
            else {
                int x = current.x;
                int y = current.y;
                //当搜索到”死点“时需要将当前的点弹栈,"死点"即当前点的上下左右不存在下一个点或者下一个点已经存在于栈中
                //死点标记count
                int count = 0;
                //判断当前点的上下左右的点是否满足条件
                if(isValidCell(cells[x+1][y])){
                    stack.push(cells[x+1][y]);
                    cells[x+1][y].visited = true;
                    count++;
                }
                if(isValidCell(cells[x][y+1])){
                    stack.push(cells[x][y+1]);
                    cells[x+1][y].visited = true;
                    count++;
                }
                if(isValidCell(cells[x-1][y])){
                    stack.push(cells[x-1][y]);
                    cells[x+1][y].visited = true;
                    count++;
                }
                if(isValidCell(cells[x][y-1])){
                    stack.push(cells[x][y-1]);
                    cells[x+1][y].visited = true;
                    count++;
                }
                //count=0表示栈中的点的下一个点是”死点“,则当前点(栈中的点)需要退栈
                if(count==0)
                {
                    stack.pop();
                }
            }
        }
        //如果while结束,即表示没有一条路径可以达到终点
        System.out.println("no way to end_point");
    }
    /**
     * 如果当前要入栈的点没有被访问过并且是通路(即maze[x][y]=0)那么表示这个点可以入栈
     * */
    private boolean isValidCell(cell cell) {
        if(cell.flag=='0'&&!cell.visited)
        {
            return true;
        }
        return false;
    }

    /**
     * 判断出栈的元素和栈顶的元素之间的位置关系(是否属于栈顶的四邻域)
     * */
    private boolean isNeighborCoordinate(cell peek, cell c) {
        if(peek.x==c.x&&(Math.abs((peek.y-c.y)))<2)
            {return true;}
        if(peek.y==c.y&&Math.abs((peek.x-c.x))<2)
            {return true;}
        return false;
    }

    private void print_maze(cell[][] cells) {
        for (day_one.cell[] cell : cells) {
            for (day_one.cell value : cell) {
                System.out.print(value.flag+" ");
            }
            System.out.println();
        }
    }
    /**
     * maze只是一个只具有‘1’,‘0’的二维数组,并不具有其他属性,例如:访问标记,以及坐标信息、路径标记等,
     * 因此需要将maze的单纯二维数组转换成一个具有多属性的二维数组
     * */
    private cell[][] creatCell(char[][] maze) {
        //初始化迷宫单元(设置迷宫单元的属性)
        //申请一个迷宫
        cell[][] cells = new cell[maze.length][];
        //由于迷宫不一定是矩形的,因此每一行(列)的长度是可能不固定的,因此有:
        for(int x=0;x<maze.length;x++)
        {
            char[] row = maze[x];
            //初始化cells二维数组的列的长度
            cells[x] = new cell[row.length];
            //当初始化cells二维数组的每一行/列的长度之后,就需要初始化每一个坐标点的值及其其他属性
            for(int y=0;y<row.length;y++)
            {
                cells[x][y] = new cell(x,y,false,maze[x][y]);
            }
        }
        return cells;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值