`
哇!!!!!先让我哭一场!!!
看了一天的迷宫求解算法,终于有点看懂了。
啥都不说了,上代码,代码的注释自我感觉还行,比较详细。
//栈的节点的类
class stack {
private int x = 0;//横纵坐标
private int y = 0;
private stack next = null;//尾指针
private int front = 0;
//front用于记录走过了几个方向,1 代表走过一个方向,2 代表走过两个......
stack(int x, int y){
this.x = x;
this.y = y;
}
void setFront(int i) {
front = i;
}
int getFront() {
return front;
}
int getX() {
return x;
}
int getY() {
return y;
}
void setNext(stack next) {
this.next = next;
}
stack getNext() {
return next;
}
void print() {//打印坐标
System.out.printf("(%d, %d), ",x, y);
}
}
public class maze {
//对一些数值进行初始化
static int row = 0;
static int col = 0;
static int x = 0;
static int y = 0;
//栈底
static stack head = new stack(0,0);
static stack now = null;
static stack top = head;
//初始化迷宫
static int[][] map = {{1,1,1,1,1,1,1,1,1,1},//0
{1,0,0,1,0,0,0,1,0,1},//1
{1,0,0,1,0,0,0,1,0,1},//2
{1,0,0,0,0,1,1,0,0,1},//3
{1,0,1,1,1,0,0,0,0,1},//4
{1,0,0,0,1,0,0,0,0,1},//5
{1,0,1,0,0,0,1,0,0,1},//6
{1,0,1,1,1,0,1,1,0,1},//7
{1,1,0,0,0,0,0,0,2,1},//8
{1,1,1,1,1,1,1,1,1,1},//9
};
static boolean[][] isBy = new boolean[10][10];//设置标记位
public static void main(String[] da) {
//初始化标记
for(int i = 0; i < 9; i++)
for(int j = 0; j < 9; j++)
isBy[i][j] = false;//将标记位全部初始化为未走过
boolean result = search(1,1);//寻找路径
System.out.println(result);
}
public static boolean search(int x, int y) {
stack temp = null;//定义一个节点
do {
if (map[x][y] != 1 && !isBy[x][y]) {//如果当前位置不是墙且没走过
isBy[x][y] = true;//将当前位置置为走过
temp = new stack(x, y);
push(head, temp);//入栈
if( map[x][y] == 2) {//如果到了终点,打印地图,返回true
printRoad(head);
return true;
}
y += 1;//默认从左向右走
temp.setFront(temp.getFront()+1);//将方向设置为1,表示已经从左向右走过
}
else {//如果位置是墙或者是走过的坐标
while(top.getFront() == 4 && !isEmpty()) {//上一步的坐标,如果四个方向都走过且都不通,则出将上一步栈
pop(head);
}
if(top.getFront() < 4) {//上一步坐标,四个方向中有没有走过的方向,则换个方向继续探寻
//此坐标不通,将x, y重置为上一步的坐标
x = top.getX();
y = top.getY();
switch(top.getFront()) {
case 1: x += 1;break;//向下走
case 2: y -= 1;break;//向左走
case 3: x -= 1;break;//向上走
default:;
}
top.setFront(top.getFront() + 1);//将front + 1表示又试探了一个方向
}
}
} while(!isEmpty());
return false;
}
static boolean isEmpty() {//判断栈是否为空
if(head.getNext() == null)return true;
else return false;
}
static void printRoad(stack in) {//循环打印路径
while(in!=null) {
in.print();
in = in.getNext();
}
}
static void push(stack in, stack now) {//入栈
while(in.getNext()!=null)
in = in.getNext();
in.setNext(now);
top = now;
}
static void pop(stack in) {//出栈
stack front = in.getNext();
while(front.getNext()!=null) {
in = front;
front = front.getNext();
}
in.setNext(null);
top = in;
}
}
之前用递归做了一遍,然后改用循环做时各种不适应。
但是我发现循环找到结果后比递归更好跳出。同时也感觉算法更加清爽。
之前一直对循环里的front这个变量不理解。后来发现是用于记录试探过几个方向的。递归里的front表示这个坐标是从哪个坐标过来的,(1表示从左边坐标走过来,2表示从上边坐标走过来…)我刚开始以为两个front是一样的,后面才发现循环中的front表示的是这个节点去过哪几个方向。1表示向右试探过,2表示向右和下试探过,3表示向右,下和左试探过,4表示四个方向都试探过。理解了这个,其实循环求路径就不是很难了。