JAVA泛型及栈应用之简单迷宫
将泛型与栈结合结合之后,可以高效解决一些数据结构中的问题,其中,走迷宫便是我们最常遇到的一类。再此之前,需要对栈以及泛型有所了解:>JAVA泛型与栈应用<
这里,先以简单迷宫为例:
假设现在有一个6X6的矩形迷宫,1表示通路,其他表示无路。
如果以[5][2]为入口,那么,走出迷宫的路径应该为:
那该如何用代码来走呢?
思路应该如下:
- 1.判断给定入口是否为真入口;
- 2.走下一步,在走之前判断下一步是否为通路;
- 3.判断是否已经到达出口;
- 4.循环寻路;
寻路其实就是去试探上下左右四个方向是否通路,如果这里每次以上,左,右,下为序寻路,那么最终路径应该为:
好,思路已经有了,现在来写代码吧。
首先,创建一个类Position,用来存放坐标,以后栈就用来放一个个Position实例化的对象。
class Position {
private int x;//横坐标
private int y;//纵坐标
public Position(int x, int y) {//构造
this.x = x;
this.y = y;
}
public int getX() {//getter方法,用来将来取坐标
return x;
}
public int getY() {
return y;
}
public void setX(int x) {//这里既用构造,又用setter方法,方便在后面写入
this.x = x;
}
public void setY(int y) {
this.y = y;
}
}
根据前面的思路,可以写三个方法,分别用来判断入口是否有效,是否到达出口,是否为通路
判断入口方法isEntry(),返回值为boolean;,该点应该为1,且在四个边界其中一个上
public static boolean isEntry(Position entry,int [][] maze,int r,int l) {//入口是否合法
if (maze[entry.getX()][entry.getY()] == 1 && (entry.getX() ==0 ||entry.getX() == r-1) || (entry.getY() ==0 ||entry.getY() == r-1)) {
return true;
}
return false;
}
判断通路方法isPath(),返回值为boolean,该点的值应该为1,且不能出边界。
public static boolean isPath(int [][] maze,Position cur,int r,int l) {
if (maze[cur.getX()][cur.getY()] == 1 && (cur.getX() >=0 ||cur.getX() <= r-1) && (cur.getY() >=0 ||cur.getY() <= r-1))
return true;
return false;
}
出口判断isExit(),返回值也为boolean;跟入口判断极为相似,在边界,但不是在入口的位置。
public static boolean isExit(int [][] maze,Position cur,Position entry,int r,int l) {//是否为出口
if ((cur.getX() !=entry.getX() && cur.getY() !=entry.getY()) && (cur.getX() ==0 ||cur.getX() == r-1) || (cur.getY() ==0 ||cur.getY() == r-1))
return true;
return false;
}
全部代码,因为设定1为通路,将走过的点置为2,表示已经走过来,当走到末路,往回走时将其设置成3,这样就可以看到走过的路径,这里的2和3可以随意设置,并无特殊含义。
package maze;
//建栈
interface Stack<T> {
void stackPush(T posi);// 入
void stackPop();// 出
T stackTop();// 取
int stackSize();// 数量
boolean stackEmpty();// 为空否
}
class StackImp<T> implements Stack<T> {
// 栈要放啥?头,尾,数量
private int size;
private Node first;
private Node last;
private class Node {
private T position;
private Node next;
public Node(T position, StackImp<T>.Node next) {
this.position = position;
this.next = next;
}
}
@Override
public void stackPush(T posi) {
Node tmp = this.first;
Node newNode = new Node(posi, null);
this.last = newNode;
if (null == this.first) {
this.first = newNode;
} else {
while (null != tmp.next) {
tmp = tmp.next;
}
tmp.next = newNode;
}
++this.size;
}
@Override
public void stackPop() {
// 只剩一个时
// 剩多个时
Node tmp = this.first;
if (null == tmp.next || null == tmp) {
this.first = null;
this.last = null;
this.size = 0;
return;
}
while (null != tmp.next.next) {
tmp = tmp.next;
}
tmp.next = null;
this.last = tmp;
--this.size;
}
@Override
public T stackTop() {
if (this.first == null) {
return null;
} else {
return (T)this.last.position;
}
}
@Override
public int stackSize() {
return this.size;
}
@Override
public boolean stackEmpty() {
if (0 == this.size) {
return true;
} else {
return false;
}
}
}
class Position {//坐标类
private int x;
private int y;
public Position(int x, int y) {
this.x = x;
this.y = y;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
public void setX(int x) {
this.x = x;
}
public void setY(int y) {
this.y = y;
}
}
public class Test {
public static void main(String[] args) {
Stack <Position> stack = new StackImp<Position>();
int [][] arr = {
{ 0, 0, 0, 0, 0, 0 },
{ 0, 0, 1, 0, 0, 0 },
{ 0, 0, 1, 0, 0, 0 },
{ 0, 0, 1, 1, 1, 0 },
{ 0, 0, 1, 0, 1, 1 },
{ 0, 0, 1, 0, 0, 0 } };
Position entry = new Position(5, 2);
maze(stack,arr,entry);
}
//++++++++++++++++++++++++++++++++++++以下为走迷宫 ++++++++++++++++++++++++++++++++++++++++++++
public static void maze(Stack<Position> stack,int arr[][],Position entry) {
int r = 6;
int l = 6;
int [][] maze= new int [r][l];
for (int i = 0 ; i < r ; i ++) {//初始化走迷宫数组
for (int j = 0; j < l; j ++) {
maze[i][j] = arr[i][j];
}
}
//需要几个判断方法
//1.传入的坐标是否为真入口;
//2.当前坐标是否为出口;
//3.下一步要走的坐标是否可走;
if (!isEntry(entry, maze, r, l)) {
return;
}
Position cur = new Position(entry.getX(), entry.getY());
Position tmp1 = new Position(entry.getX(), entry.getY());
stack.stackPush(tmp1);
maze[entry.getX()][entry.getY()] = 2;//判断过就相当于走过了,置为2
while (!isExit(maze, cur, entry, r, l)) {
//up
Position tmp = new Position(entry.getX(), entry.getY());//这里有个小坑,tmp是必须每次都新实例化的,要不然就会一直使用一个tmp对象,最后栈中放的都是同一个坐标。
tmp.setX(cur.getX()-1);
tmp.setY(cur.getY());
if (isPath(maze, tmp, r, l)) {
maze[tmp.getX()][tmp.getY()] = 2;
cur.setX(tmp.getX());
stack.stackPush(tmp);
System.out.println(stack.stackTop().getX() + " "+stack.stackTop().getY());
printMaze(maze);
continue;
}
//left
tmp.setX(cur.getX());
tmp.setY(cur.getY()-1);
if (isPath(maze, tmp, r, l)) {
maze[tmp.getX()][tmp.getY()] = 2;
cur.setY(tmp.getY());
stack.stackPush(tmp);
System.out.println(stack.stackTop().getX() + " "+stack.stackTop().getY());
printMaze(maze);
continue;
}
//right
tmp.setX(cur.getX());
tmp.setY(cur.getY()+1);
if (isPath(maze, tmp, r, l)) {
maze[tmp.getX()][tmp.getY()] = 2;
cur.setY(tmp.getY());
stack.stackPush(tmp);
System.out.println(stack.stackTop().getX() + " "+stack.stackTop().getY());
printMaze(maze);
continue;
}
//down
tmp.setX(cur.getX()+1);
tmp.setY(cur.getY());
if (isPath(maze, tmp, r, l)) {
maze[tmp.getX()][tmp.getY()] = 2;
cur.setX(tmp.getX());
stack.stackPush(cur);
System.out.println(stack.stackTop().getX() + " "+stack.stackTop().getY());
printMaze(maze);
continue;
}
//走了,或者下一步走不了
cur = stack.stackTop();
printMaze(maze);
maze[cur.getX()][cur.getY()] = 3;
stack.stackPop();
}
System.out.println("I'm out!");
}
public static void printMaze(int [][] maze) {
for (int i = 0 ; i < 6 ; i ++) {
for (int j = 0; j < 6; j ++) {
System.out.print(maze[i][j]+ " ");
}
System.out.println();
}
System.out.println();
}
public static boolean isExit(int [][] maze,Position cur,Position entry,int r,int l) {//是否为出口
if ((cur.getX() !=entry.getX() && cur.getY() !=entry.getY()) && (cur.getX() ==0 ||cur.getX() == r-1) || (cur.getY() ==0 ||cur.getY() == r-1))
return true;
return false;
}
public static boolean isEntry(Position entry,int [][] maze,int r,int l) {//入口是否合法
if (maze[entry.getX()][entry.getY()] == 1 && (entry.getX() ==0 ||entry.getX() == r-1) || (entry.getY() ==0 ||entry.getY() == r-1)) {
return true;
}
return false;
public static boolean isPath(int [][] maze,Position cur,int r,int l) {
if (maze[cur.getX()][cur.getY()] == 1 && (cur.getX() >=0 ||cur.getX() <= r-1) && (cur.getY() >=0 ||cur.getY() <= r-1))
return true;
return false;
}
}
这里要特别注意while语句Position tmp = new Position(entry.getX(), entry.getY());
这一句,这里有个小坑,tmp是必须每次都新实例化的,要不然就会一直引用同一个tmp对象,最后栈中放的都是同一个坐标。
while (!isExit(maze, cur, entry, r, l)) {
//up
Position tmp = new Position(entry.getX(), entry.getY());
tmp.setX(cur.getX()-1);
tmp.setY(cur.getY());
if (isPath(maze, tmp, r, l)) {
...
如果不想看JAVA语言,可以选择C语言版>C语言用栈实现走迷宫源码<