目录
1.问题描述
输入迷宫大小,以及路径,0表示可走路径,1表示死路,从输入矩阵的左上角起点到右下角终口(也可简单改动自定义起点和终点)找出一条能通过的路径。
如输入大小3*3,路径为
0 0 0
0 1 1
0 0 0
最终要做的是找到并将对应路径的值改写,比如说是2,用来表示找到的路径所在,如:
2 0 0
2 1 1
2 2 2
2.自定义类栈
思路:利用回溯法去做,每次进行结点探查,能走就走,路不通就返回,因此这里利用栈去做,自定义栈类如下:
栈中用一个自定义的MazeNode类型的一维数组存储结点信息,size为栈中有效元素个数,操作主要有入栈,出栈,取栈顶元素。
package com.maze;
import java.util.Arrays;
import java.util.EmptyStackException;
/**
* Description :
* Created by Resumebb
* Date :2020/10/21
*/
public class MyStack {
private MazeNode[] element;
private int size;
private static final int INITSIZE = 100;
public MyStack(){
element = new MazeNode[INITSIZE];
}
public int getSize() {
return size;
}
public void setSize(int size) {
this.size = size;
}
private void ensureCapacity(){
if(size == element.length){
element = Arrays.copyOf(element,element.length+(element.length>>1));
}
}
public void push(MazeNode mazeNode,int row, int colum){
ensureCapacity();
element[size++] = mazeNode;
mazeNode.setRow(row);
mazeNode.setColum(colum);
}
public void pop(){
if(size == 0){
return;
}
size--;
}
public MazeNode peek(){
if(size == 0){
throw new EmptyStackException();
}
return element[size-1];
}
}
3.结点类
接下来定义结点类:
成员变量有结点的方向,东南西北四个方向,当前所在行列坐标,以及当前结点的value值。
package com.maze;
/**
* Description :
* Created by Resumebb
* Date :2020/10/21
*/
public class MazeNode {
private int value;
public boolean way_east;
public boolean way_west;
public boolean way_south;
public boolean way_north;
private int row;
private int colum;
public MazeNode(int value, int row, int colum){
this.value = value;
this.row = row;
this.colum = colum;
}
public int getRow() {
return row;
}
public void setRow(int row) {
this.row = row;
}
public int getColum() {
return colum;
}
public void setColum(int colum) {
this.colum = colum;
}
public int getValue() {
return value;
}
public void setValue(int value) {
this.value = value;
}
}
4.操作类
定义操作类,寻路操作等在此类中进行:
package com.maze;
import java.util.Scanner;
import java.util.Stack;
/**
* Description :
* Created by Resumebb
* Date :2020/10/21
*/
public class Maze {
private MazeNode[][] mazeNodes;
private int row;
private int colum;
public Maze(int row, int colum) {
this.row = row;
this.colum = colum;
mazeNodes = new MazeNode[row][colum];
}
public int getRow() {
return row;
}
public void setRow(int row) {
this.row = row;
}
public int getColum() {
return colum;
}
public void setColum(int colum) {
this.colum = colum;
}
public void goMaze(){
initValue();
if(mazeNodes[0][0].getValue() != 0){
return;
}
initWayState();
MyStack stack = run();
display(stack);
}
public void initValue(){
Scanner in = new Scanner(System.in);
System.out.println("input route:");
for (int i = 0; i < row; i++) {
for (int j = 0; j < colum; j++) {
mazeNodes[i][j] = new MazeNode(in.nextInt(),i,j);
}
}
}
private void initWayState(){
for (int i = 0; i < row; i++) {
for (int j = 0; j < colum; j++) {
if(mazeNodes[i][j].getValue() == 0){
//东
if(j+1<colum && mazeNodes[i][j+1].getValue() == 0){
mazeNodes[i][j].way_east = true;
}
//西
if(j-1>=0 && mazeNodes[i][j-1].getValue() == 0){
mazeNodes[i][j].way_west = true;
}
//南
if(i+1<row && mazeNodes[i+1][j].getValue() == 0){
mazeNodes[i][j].way_south = true;
}
//北
if(i-1>=0 && mazeNodes[i-1][j].getValue() == 0){
mazeNodes[i][j].way_north = true;
}
}
}
}
}
//0 0 0 0 1 1 0 0 0
public MyStack run(){
MyStack stack = new MyStack();
int i = 0, j = 0;
stack.push(mazeNodes[0][0]);
while(stack.getSize()!=0){
//东边可走
if(j+1<colum && mazeNodes[i][j+1].getValue() == 0 && mazeNodes[i][j+1].way_west){
stack.push(mazeNodes[i][j+1]);
mazeNodes[i][j].way_east = false;
mazeNodes[i][++j].way_west = false;
}
//南边可走
else if(i+1<row && mazeNodes[i+1][j].getValue() == 0 && mazeNodes[i+1][j].way_north){
stack.push(mazeNodes[i+1][j]);
mazeNodes[i][j].way_south = false;
mazeNodes[++i][j].way_north = false;
}
//西边可走
else if(j-1>=0 && mazeNodes[i][j-1].getValue() == 0 && mazeNodes[i][j-1].way_east){
stack.push(mazeNodes[i][j-1]);
mazeNodes[i][j].way_west = false;
mazeNodes[i][--j].way_east = false;
}
//北边可走
else if(i-1>=0 && mazeNodes[i-1][j].getValue() == 0 && mazeNodes[i-1][j].way_south){
stack.push(mazeNodes[i-1][j]);
mazeNodes[i][j].way_north = false;
mazeNodes[--i][j].way_south = false;
}
//四路不通出栈
else {
stack.pop();
i = stack.peek().getRow();
j = stack.peek().getColum();
}
if(i==row-1 && j==colum-1){
return stack;
}
}
return stack;
}
public void display(MyStack stack){
int x = 0, y = 0;
int len = stack.getSize();
for (int i = 0; i < len; i++) {
x = stack.peek().getRow();
y = stack.peek().getColum();
mazeNodes[x][y].setValue(2);
stack.pop();
}
System.out.println("route:");
for (int i = 0; i < row; i++) {
for (int j = 0; j < colum; j++) {
System.out.print(mazeNodes[i][j].getValue()+" ");
}
System.out.println();
}
}
}
5.函数讲解
在该类中主要函数是initValue(); initWayState(); run(); display();
initValue函数:
该函数的作用主要用于存储路径的二维数组初始化的数据录入操作。
initWayState函数:
该函数的作用是用于对每个结点的方向进行初始化,如当前结点的右边是0,则将当前结点的way_east给置TRUE,如果下方也是0,则way_south给置TRUE,像这样将整个迷宫的所有结点的方向给初始化。
run函数:
该函数就是让孩子去闯去跳,去勇敢的倒挂金钩。
首先将起点给入栈,然后进行轮回,按照东南西北的顺时针方向去循环(因为我要靠近右下角的终点,这样搞快点),只要检测到四个方向哪个方向的下一个结点值为0,说明这条路是通的,并且它这个结点对应的反方向值为TRUE,举个例子:
0 0 0
0 1 1
0 0 0
if(j+1<colum && mazeNodes[i][j+1].getValue() == 0 && mazeNodes[i][j+1].way_west){
stack.push(mazeNodes[i][j+1]);
mazeNodes[i][j].way_east = false;
mazeNodes[i][++j].way_west = false;
}
我先把左上角第一个结点入栈,然后去遍历,该项右边结点的值为0,说明这是一条路径,然后看右边结点的西方向是否为TRUE(也可以判断当前结点的东方向是否为TRUE,但是我喜欢反着来),如果为TRUE,就相当于这条路径是能走的,那么就将当前结点入栈,然后把当前结点的东边方向和右边结点的西边方向给置FALSE,相当于过河拆桥,只能走一次,下次就不行了,桥已经炸了,判断的时候要注意边界问题。
当走到第3个结点时,发现右边没路,南边也是1,路不通,并且回去的路也给封了,此时就要将当前结点出栈,说明此路不通,开始浪子回头,并且将i,j指针指向出栈后新栈顶元素的行列坐标。
stack.pop();
i = stack.peek().getRow();
j = stack.peek().getColum();
最后直到找到一条路径,将栈给返回。
display函数:
这个函数就是用来进行打印路径的,遍历栈中元素,获取行列坐标,将路径对应的结点值给换成2,进行打印输出。
public void display(MyStack stack){
int x = 0, y = 0;
int len = stack.getSize();
for (int i = 0; i < len; i++) {
x = stack.peek().getRow();
y = stack.peek().getColum();
mazeNodes[x][y].setValue(2);
stack.pop();
}
for (int i = 0; i < row; i++) {
for (int j = 0; j < colum; j++) {
System.out.print(mazeNodes[i][j].getValue()+" ");
}
System.out.println();
}
}
6.测试类及结果
最后一个测试类:
package com.maze;
import java.util.Scanner;
/**
* Description :
* Created by Resumebb
* Date :2020/10/21
*/
public class TestDemo {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
System.out.println("input size:");
int row = in.nextInt();
int colum = in.nextInt();
Maze maze = new Maze(row,colum);
maze.goMaze();
}
}
测试后结果: