一、简要
偶尔接触到迷宫问题发现挺有趣的,所以开始研究了一下。我觉得这个问题的关键是:
- 怎么设计这个迷宫?
- 怎么利用栈的特点来解决这个问题?
- 在迷宫行走怎么更改迷宫的方向?
- 怎么寻找迷宫路径?以及怎么才算找到迷宫路径?
二、思路
通过上面的问题关键,在脑中可以构造一个大体的思路:
- 首先创建一个迷宫maze,对于迷宫可以采用mxn的一个二维数组来设计。
- 创建一个mazenode节点类来控制二维数组中的每一个节点,另外还需要构造一个函数来设计每个节点(东、南、西、北)的可行性。
- 为了保证在任何位置上都能沿原路退回,所以需要用一个后进先出的结构来保存从入口到当前位置的路径,因此在求迷宫通路的算法中要应用“栈”的思想,所以必须设计一个栈出来,用来存储“当前路径”,即“在搜索过程中某一时刻所在图中某个方块位置”。
- 然后就可以开始寻找迷宫路径了,从迷宫的入口节点开始入栈,来寻找它下一个位置,如果当前位置的下个位置(东、南、西、北)可以走,那么就把当前位置的下个位置的行走状态改为不可以行走,把当前位置也改为不可以行走,(因为都是从那里走回来的不能再走回去了,不然就是一个死循环了),然后把下个位置节点入栈;继续寻找,如果遇见了死胡同,那么就开始出栈。如果入栈的节点的行列数和迷宫行列数相等,说明我们已经找到出口,可以跳出循环。或者另一种情况就是一直遇见死胡同,一直出栈,直到栈空,那就说明该迷宫没有路径。
- 最后就可以出栈打印出迷宫路径。
- 以上操作都是个人想法,如有错误还望指正。
三、java代码实现
//常数类方便操作
public class Constant {
public static final int WAY_NUMBER = 4;
//表示路径可以行走
public static final int WAY_ENABLE = 1;
//表示路径不可以行走
public static final int WAY_DISABLE = 0;
//迷宫节点的四个方向
public static final int WAY_EAST = 0;
public static final int WAY_SOUTH = 1;
public static final int WAY_WEST = 2;
public static final int WAY_NORTH = 3;
}
//迷宫节点类
public class MazeNode {
private int value;
private int i;
private int j;
private int[] pathState;
public MazeNode(int value, int i, int j){
this.value = value;
this.i = i;
this.j = j;
//初始化节点的四个方向的路径信息,都初始化成不能行走
pathState = new int[Constant.WAY_NUMBER];
for(int k=0; k<pathState.length; ++k){
pathState[k] = Constant.WAY_DISABLE;
}
}
//设置迷宫行走状态的构造函数
public void setPathState(int path, int state){
pathState[path]=state;
}
//获取迷宫行走状态的构造函数
public int getPathState(int path){
return pathState[path];
}
public int getValue() {
return value;
}
public void setValue(int value) {
this.value = value;
}
public int getRow() {
return i;
}
public void setRow(int i) {
this.i = i;
}
public int getCol() {
return j;
}
public void setCol(int j) {
this.j = j;
}
}
import java.util.Arrays;
import java.util.Scanner;
//创建栈
class SqStack{
private MazeNode[] stack;
private int top;
public SqStack(){
top = 0;
stack = new MazeNode[50];
}
//push要支持stack的内存增长操作,一次性增长2倍
public void push(MazeNode node) {
if(full())
resize();
this.stack[this.top++]=node;
}
public void pop() {
if(empty())
return ;
this.top--;
}
public MazeNode top() {
//return null;
return this.stack[this.top-1];
}
public boolean empty() {
//return false;
return this.top == 0;
}
public boolean full() {
//return false;
return this.top == 0;
}
private void resize(){
this.stack=Arrays.copyOf(this.stack, this.stack.length*2);
}
}
//构造迷宫类
class Maze{
private int row;
private int colum;
private MazeNode[][] mazePath;//迷宫节点,二维数组
private SqStack stack;
public Maze(int row, int colum){
this.row = row;
this.colum = colum;
mazePath = new MazeNode[this.row][this.colum];
stack = new SqStack();
}
public void setPath(int i, int j, int value){
mazePath[i][j] = new MazeNode(value, i, j);
}
//该函数主要用来更改迷宫节点四个方向的行走状态
public void adjustMazePath(){
for(int i=0;i<this.row;i++){
for(int j=0;j<this.colum;j++){
//先调整最层路径
if(mazePath[i][j].getValue()==0){
//东
if(j<this.colum-1&&mazePath[i][j+1].getValue()==0){
mazePath[i][j].setPathState(Constant.WAY_EAST,Constant.WAY_ENABLE);
}
//南
if(i<this.row-1&&mazePath[i+1][j].getValue()==0){
mazePath[i][j].setPathState(Constant.WAY_SOUTH,Constant.WAY_ENABLE);
}
//西
if(j>0&&mazePath[i][j-1].getValue()==0){
mazePath[i][j].setPathState(Constant.WAY_WEST,Constant.WAY_ENABLE);
}
//北
if(i>0&&mazePath[i-1][j].getValue()==0){
mazePath[i][j].setPathState(Constant.WAY_NORTH,Constant.WAY_ENABLE);
}
}
}
}
}
//开始寻找迷宫路径
public void findMazePath(){
System.out.println("正在寻找迷宫路径。。。");
this.stack.push(mazePath[0][0]);//入口传入栈
int i=0,j=0;
while(!this.stack.empty()){
MazeNode top=this.stack.top();
//如果top的行列数等于Maze的行列书,说明就已经找到出口
if(i ==this.row-1&&j==this.colum-1){
break;
}
//判断东
if(top.getPathState(Constant.WAY_EAST)==Constant.WAY_ENABLE){
mazePath[i][j].setPathState(Constant.WAY_EAST, Constant.WAY_DISABLE);
mazePath[i][j+1].setPathState(Constant.WAY_WEST, Constant.WAY_DISABLE);
this.stack.push(mazePath[i][j+1]);
j++;
continue;
}
//判断南
if(top.getPathState(Constant.WAY_SOUTH)==Constant.WAY_ENABLE){
mazePath[i][j].setPathState(Constant.WAY_SOUTH, Constant.WAY_DISABLE);
mazePath[i+1][j].setPathState(Constant.WAY_NORTH, Constant.WAY_DISABLE);
this.stack.push(mazePath[i+1][j]);
i++;
continue;
}
//判断西
if(top.getPathState(Constant.WAY_WEST)==Constant.WAY_ENABLE){
mazePath[i][j].setPathState(Constant.WAY_WEST, Constant.WAY_DISABLE);
mazePath[i][j-1].setPathState(Constant.WAY_EAST, Constant.WAY_DISABLE);
this.stack.push(mazePath[i][j-1]);
j--;
continue;
}
//判断北
if(top.getPathState(Constant.WAY_NORTH)==Constant.WAY_ENABLE){
mazePath[i][j].setPathState(Constant.WAY_NORTH, Constant.WAY_DISABLE);
mazePath[i-1][j].setPathState(Constant.WAY_SOUTH, Constant.WAY_DISABLE);
this.stack.push(mazePath[i-1][j]);
i--;
continue;
}
this.stack.pop();
}
if(this.stack.empty()){
System.out.println("从左上角入口到右下角出口不存在有效路径 、、、、");
}
}
//打印最终的迷宫路径信息
public void showMazePath(){
while(!this.stack.empty()){
MazeNode top=this.stack.top();
int i=top.getRow();
int j=top.getCol();
mazePath[i][j].setValue(2);
//System.out.printf("<%d,%d>->",this.stack.top().getRow(),this.stack.top().getCol());
this.stack.pop();
}
System.out.println("路径已找到,输入如下(2代表行走的路径):");
for(int i=0;i<this.row;i++){
for(int j=0;j<this.colum;j++){
System.out.print(mazePath[i][j].getValue()+" ");
}
System.out.println();
}
}
}
public class TestMazePathDemo {
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner scan = new Scanner(System.in);
System.out.print("请输入迷宫的行列数(m * n):");
int row = scan.nextInt();
int col = scan.nextInt();
//maze现在代表的就是整个迷宫
Maze maze = new Maze(row, col);
System.out.println("请输入迷宫的路径:");
for(int i=0; i<row; ++i){
for(int j=0; j<col; ++j){
int data = scan.nextInt();
maze.setPath(i, j, data);
}
}
//以上代码,就把整个迷宫路径的信息都设置到maze对象里面了
//该函数主要用来更改迷宫节点四个方向的行走状态
maze.adjustMazePath();
//开始寻找迷宫路径
maze.findMazePath();
//打印最终的迷宫路径信息
maze.showMazePath();
}
}