您的位置:首页 > 编程语言 > Java开发

随机生成一个迷宫并探索一条路径的JAVA实现

2018-02-08 10:16 507 查看
问题:实现一个随机迷宫,可以想象是一个二维数组,入口在左上角,出口在右下角。
要求:

1、不能超过边界
2、路线不能重复,也就是说每个点只能经过一次

3、走出迷宫的路线是随机生成的,每次生成的路线都应该不一样
4、迷宫的大小可以任意指定,也就是说明二维数组的大小可以随意变化

5、最终生成的迷宫需要打印出来

迷宫实体类MazePoint:

public class MazePoint {
private boolean isVisited = false;
private boolean wallUp = true;
private boolean wallRight = true;
private boolean wallDown = true;
private boolean wallLeft = true;

public boolean isVisited() {
return isVisited;
}
public void setVisited(boolean isVisited) {
this.isVisited = isVisited;
}
public boolean isWallUp() {
return wallUp;
}
public void setWallUp(boolean wallUp) {
this.wallUp = wallUp;
}
public boolean isWallRight() {
return wallRight;
}
public void setWallRight(boolean wallRight) {
this.wallRight = wallRight;
}
public boolean isWallDown() {
return wallDown;
}
public void setWallDown(boolean wallDown) {
this.wallDown = wallDown;
}
public boolean isWallLeft() {
return wallLeft;
}
public void setWallLeft(boolean wallLeft) {
this.wallLeft = wallLeft;
}
}


迷宫类Maze:

import java.util.Random;
import java.util.Scanner;
import java.util.Stack;
public class Maze {
private final static int dirUp = 0;
private final static int dirRight = 1;
private final static int dirDown = 2;
private final static int dirLeft = 3;

private final static int gridWall = 1;
private final static int gridEmpty = 0;
private final static int gridBlind = -1;
private final static int gridPath = 2;

private int width;
private int height;
private MazePoint[][] matrix;
private int[][] maze;

/*
* 构造一个迷宫,初始化迷宫的宽度和高度,同时初始化包含MazePoint的点阵
*/
public Maze(int height, int width) {
this.width = width;
this.height = height;
this.matrix = new MazePoint[height][width];
for (int i=0; i<height; i++)
for (int j=0; j<width; j++)
matrix[i][j] = new MazePoint();
this.maze = new int[2*height+1][2*width+1];  //构建宽为2*height+1、长为2*width+1的迷宫
}

/*
* 检查目标点的上下左右的邻居是否可以被访问,如果目标点超出界限则视为已被访问
*/
public boolean isNeighborOK(int x, int y, int dir) {
boolean isNeighborVisited = false;
switch ( dir ) {
case dirUp:
if ( x <= 0 )
isNeighborVisited = true;  //越界视为已被访问
else
isNeighborVisited = matrix[x-1][y].isVisited();
break;
case dirRight:
if ( y >= width - 1 )
isNeighborVisited = true;
else
isNeighborVisited = matrix[x][y+1].isVisited();
break;
case dirDown:
if ( x >= height - 1 )
isNeighborVisited = true;
else
isNeighborVisited = matrix[x+1][y].isVisited();
break;
case dirLeft:
if ( y <= 0 )
isNeighborVisited = true;
else
isNeighborVisited = matrix[x][y-1].isVisited();
break;
}
return !isNeighborVisited;  //若点未被访问过(isNeighborVisited为false),则返回值为true,表示有邻居可以被访问
}

/*
* 检查目标点的上下左右是否至少有一个可以访问
*/
public boolean isNeighborOK(int x, int y) {
return (this.isNeighborOK(x, y, dirUp) || this.isNeighborOK(x, y, dirRight) ||
this.isNeighborOK(x, y, dirDown) || this.isNeighborOK(x, y, dirLeft));
}

/*
* 获得一个可以被访问的方向
*/
public int getRandomDir(int x, int y) {
int dir = -1;
Random rand = new Random();
if ( isNeighborOK(x, y) ) {
do {
dir = rand.nextInt(4);
} while ( !isNeighborOK(x, y, dir) );  //(x,y)的dir方向不可被访问,重新选择方向
}
return dir;
}

/*
* 将相邻可以访问的点设置为通路
*/
public void pushWall(int x, int y, int dir) {
switch ( dir ) {
case dirUp:
matrix[x][y].setWallUp(false);
matrix[x-1][y].setWallDown(false);  //将该点与其上面相邻的点设置通路
break;
case dirRight:
matrix[x][y].setWallRight(false);
matrix[x][y+1].setWallLeft(false);  //将该点与其右面相邻的点设置通路
break;
case dirDown:
matrix[x][y].setWallDown(false);
matrix[x+1][y].setWallUp(false);  //将该点与其下面相邻的点设置通路
break;
case dirLeft:
matrix[x][y].setWallLeft(false);
matrix[x][y-1].setWallRight(false);  //将该点与其左面相邻的点设置通路
break;
}
}

/*
* 深度优先遍历
*/
public void traversal() {
int x = 0;
int y = 0;
Stack<Integer> stackX = new Stack<Integer>();
Stack<Integer> stackY = new Stack<Integer>();
do {
MazePoint p = matrix[x][y];
if ( !p.isVisited() ) {
p.setVisited(true);
}
if ( isNeighborOK(x, y) ) {
int dir = this.getRandomDir(x, y);  //获得一个随机可访问的方向
this.pushWall(x, y, dir);  //设置通路
stackX.add(x);  //保存坐标信息
stackY.add(y);  //保存坐标信息
switch ( dir ) {
case dirUp:
x--;
break;
case dirRight:
y++;
break;
case dirDown:
x++;
break;
case dirLeft:
y--;
break;
}
}
else {
x = stackX.pop();
y = stackY.pop();
}
} while ( !stackX.isEmpty() );
}

/*
* 根据MazePoint点阵右侧和下侧的墙构建迷宫
*/
public void create() {
//
}

/*
* 打印迷宫
*/
public void print() {
for (int i=0; i<2*height+1; i++) {
for (int j=0; j<2*width+1; j++)
if ( maze[i][j] == gridWall )
System.out.print("□");
else if ( maze[i][j] == gridPath )
System.out.print(".");
adf6
//通路标记为".",其他设置为"□"
else
System.out.print("□");
System.out.println();
}
}

/*
* 在迷宫数组中去获得一个访问的方向
*/
public int getBreakOutDir(int x, int y) {
int dir = -1;
if ( maze[x][y+1] == 0 )
dir = dirRight;
else if ( maze[x+1][y] == 0 )
dir = dirDown;
else if ( maze[x][y-1] == 0 )
dir = dirLeft;
else if ( maze[x-1][y] == 0 )
dir = dirUp;
return dir;
}

/*
* 找到从点 (1, 1) 到点 (2*height-1, 2*width-1) 的一条路径
*/
public void findPath() {
int x = 1;
int y = 1;
Stack<Integer> stackX = new Stack<Integer>();
Stack<Integer> stackY = new Stack<Integer>();
do {
int dir = this.getBreakOutDir(x, y);
if ( dir == -1 ) {
maze[x][y] = gridBlind;  //方向不存在的设置为盲点
x = stackX.pop();
y = stackY.pop();
}
else {
maze[x][y] = gridPath;
stackX.add(x);
stackY.add(y);  //保存通路点坐标信息
switch ( dir ) {
case dirUp:
x--;
break;
case dirRight:
y++;
break;
case dirDown:
x++;
break;
case dirLeft:
y--;
break;
}
}
} while ( !(x == 2*height-1 && y == 2*width-1) );
maze[x][y] = gridPath;
}

/*
* 清除迷宫中的路径
*/
public void reset() {
for (int i=0; i<2*height+1; i++)
for (int j=0; j<2*width+1; j++)
if ( maze[i][j] != gridWall )
maze[i][j] = gridEmpty;
}
}


测试的main类:

public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner scanner = new Scanner(System.in);
System.out.println("请输入n:迷宫的行数为2n+1(包括上下两道墙)");
int row = scanner.nextInt();
System.out.println("请输入m:迷宫的列数为2m+1");
int col = scanner.nextInt();
Maze maze = new Maze(row, col);
maze.traversal();  //遍历
maze.create();     //构建迷宫
maze.findPath();   //找到路径
maze.print();     //打印迷宫
maze.reset();     //清除迷宫
}


运行截图:



代码下载链接:完整代码下载
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息