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;
}
}
分享一个暴力求解迷宫的爆栈算法--->嘤嘤嘤!
最新推荐文章于 2022-07-01 11:40:19 发布