开发环境:
操作系统Win10。
1.下载Java 15,提取码:soft 2.下载软件 Eclipse 2020-12,提取码:soft 3.生成迷宫第1版
画迷宫思路:
想象着有一个正方形区域,由长宽相等数量的正方形房间构成,房间中间是空的,四周是墙壁。有这么一个工人,他是来到这块区域的某一个房间,开始砸墙。
规则一:随机砸上下左右其中一个方向的墙,举例这个方向是下,就砸下面的墙和下面房间的上面的墙,然后前往下面的房间,并对上面的房间做个标记,不再砸上面的房间。以此类推,一直砸下去。
规则二:当工人发现四周所有房间都做了标记,就随机前往一个被标记的房间,继续规则一的步骤。
规则三:所有房间都做了标记的时候,迷宫就创建完了。
寻路思路:
规则一:随机生成起点终点,假设有一个玩家站在起点房间,首先随机一个方向,如果这个方向不是墙壁,就前往这个方向的房间,然后记录这个房间的位置,避免走相同的房间。
规则二:如果玩家当前所在房间有三面墙壁,表示进入死胡同,就后退到那唯一没有墙壁的方向的房间,如果那个房间之前走过,就从记录里删除,如果之前没有走过就增加新的房间位置的记录。后退完毕后,把那个死胡同的房间的唯一没有墙的方向,重新筑墙,然后重复规则一。
规则三:如果当前玩家所在房间是终点,则寻路完毕,得到走出迷宫的答案。
文章目录
- 1. 工程目录结构
- 2. 程序效果
- 3. 代码内容
1. 工程目录结构
2. 程序效果
3. 代码内容
Constant.java
package maze.view;
public class Constant {
/** 方向 */
public static enum DIRECT {
// 上
TOP
// 下
,BOTTOM
// 左
,LEFT
// 右
,RIGHT
}
}
LogUtils.java
这个类,中间调试的时候用了下,最后都删掉了。
package maze.view;
public class LogUtils {
public static boolean changedLine = true;
public static boolean showFlg = true;
public static int tryCount = 0;
public static void log(String message) {
// try {
// PrintStream out = System.out;// 保存原系统输出流
// PrintStream ps = new PrintStream("./src/maze/view/maze.log");
// System.setOut(ps);// 设定新的输出流
if (tryCount == 20) {
showFlg = false;
}
if (showFlg) {
if (message.contains("try")) {
tryCount++;
} else {
tryCount = 0;
}
if (changedLine) {
System.out.println(message);
} else {
System.out.print(message);
}
}
//
// System.setOut(out);// 恢复原系统输出流
// } catch (FileNotFoundException e) {
// // TODO Auto-generated catch block
// e.printStackTrace();
// }// 创建文件输出流
}
}
MainFrame.java
package maze.view;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JTextField;
/**
* 用迷宫算法,随机生成迷宫<br>
* 思想:生成迷宫的过程就是一个在一个个房间里砸墙的过程<br>
* 迷宫算法规则:<br>
* 1,只有当隔壁房间没去过的时候,墙才可以砸<br>
* 2, 无墙可砸的时候,就传送到一个去过的房间里<br>
* 3, 每一个房间都要到达
*
* @author 见瑞彬
*
*/
public class MainFrame extends JFrame implements ActionListener {
/** 序列号 */
private static final long serialVersionUID = 1L;
private int frameX = 0;
private int frameY = 0;
private int frameW = 800;
private int frameH = 700;
/** 迷宫管理员 */
private MazeUtils mazeUtils;
/** 迷宫区域 */
private Rectangle mazeArea;
/** 按钮<<生成迷宫>> */
private JButton remakeMazeButton;
/** 文本<<迷宫长度>> */
private JTextField horizontalCountField;
/** 标签<<迷宫长度>> */
private JLabel horizontalCountLabel;
/** 起点 */
private Point startPoint;
/** 终点 */
private Point endPoint;
/** 迷宫 */
private Room[][] maze;
public MainFrame() {
// 初始化迷宫工具类
mazeUtils = new MazeUtils();
// 初始化迷宫区域
mazeArea = new Rectangle(20, 80, 600, 600);
// 设定窗体控件布局
this.setLayout(null);
// 添加按钮<<生成迷宫>>
remakeMazeButton = new JButton("生成迷宫");
remakeMazeButton.setBounds(0, 5, 90, 30);
remakeMazeButton.addActionListener(this);
this.add(remakeMazeButton);
// 设定横排方格数
horizontalCountLabel = new JLabel("迷宫长度");
horizontalCountLabel.setBounds(100, 5, 50, 30);
this.add(horizontalCountLabel);
horizontalCountField = new JTextField(6);
horizontalCountField.setBounds(160, 5, 40, 30);
this.add(horizontalCountField);
// 居中
Dimension clientSize = Toolkit.getDefaultToolkit().getScreenSize();
frameX = (int) ((clientSize.getWidth() - frameW) / 2);
frameY = (int) ((clientSize.getHeight() - frameH) / 2);
// 窗体属性
this.setBounds(frameX, frameY, frameW, frameH);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setResizable(false);
this.setVisible(true);
this.validate();
}
/**
* 重绘窗体
*/
@Override
public void paint(Graphics g) {
super.paint(g);
drawMaze(g);
}
/**
* 画迷宫
*
* @param g
*/
private void drawMaze(Graphics g) {
// 禁止迷宫长度
if (mazeUtils.getMazeLength() <= 1) {
return;
}
// 重画迷宫
maze = mazeUtils.createMaze(mazeArea, mazeUtils.getMazeLength());
// 显示路径
mazeUtils.playMazeGame(maze, startPoint, endPoint);
// 遍历房间,画房间
for (int i = 0; i < mazeUtils.getMazeLength(); i++) {
for (int j = 0; j < mazeUtils.getMazeLength(); j++) {
// 获得迷宫房间
Room room = maze[i][j];
// 绘制迷宫房间
room.draw(g);
}
}
}
@Override
public void actionPerformed(ActionEvent e) {
// 重新生成迷宫
if (e.getSource() == this.remakeMazeButton) {
// 修改迷宫的横排方格数量
try {
mazeUtils.setMazeLength(Integer.parseInt(horizontalCountField.getText()));
} catch (Exception e1) {
if (mazeUtils.getMazeLength() == 0) {
mazeUtils.setMazeLength(10);
}
}
// 画迷宫路径
// 随机起点
int randX1 = (int) (Math.random() * mazeUtils.getMazeLength());
int randY1 = (int) (Math.random() * mazeUtils.getMazeLength());
startPoint = new Point(randX1, randY1);
// 随机终点
int randX2 = 0;
int randY2 = 0;
while (randX1 == randX2 && randY1 == randY2) {
randX2 = (int) (Math.random() * mazeUtils.getMazeLength());
randY2 = (int) (Math.random() * mazeUtils.getMazeLength());
}
endPoint = new Point(randX2, randY2);
// 重绘迷宫
this.repaint();
}
}
}
MazeUtils.java
package maze.view;
import java.awt.Point;
import java.awt.Rectangle;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.List;
/**
* 迷宫工具类
*
* @author 见瑞彬
*
*/
public class MazeUtils {
/** 迷宫 */
private Room[][] maze;
/** 迷宫长度 */
private int mazeLength;
/** 创建迷宫砸墙工人 */
private WallWorker wallWorker;
/** 迷宫玩家 完成迷宫任务的人 */
private Player player;
public MazeUtils() {
mazeLength = 0;
}
/**
* 创建迷宫
*
* @param areaWidth 迷宫区域
* @param mazeLength 迷宫宽度
* @return
*/
public Room[][] createMaze(Rectangle area, int mazeLength) {
// 取得房间宽度
BigDecimal roomWidth = new BigDecimal(area.width).divide(new BigDecimal(mazeLength), 4, RoundingMode.DOWN);
// 初始化迷宫的每一个房间
maze = new Room[getMazeLength()][getMazeLength()];
for (int i = 0; i < getMazeLength(); i++) {
for (int j = 0; j < getMazeLength(); j++) {
maze[i][j] = new Room(i, j, roomWidth,area.getLocation(),getMazeLength());
}
}
// 初始化砸墙工人,并设定位置
wallWorker = new WallWorker(maze);
// 迷宫算法规则3, 每一个房间都要到达
while (!wallWorker.destroyAllRoom()) {
// 迷宫算法规则1,只有当隔壁房间没去过的时候,墙才可以砸
boolean pushWallSuccess = destroyStraightRoom();
// 迷宫算法规则2, 无墙可砸的时候,就传送到一个去过的房间里
if (!pushWallSuccess) {
// 跳跃到曾经去过的迷宫房间
wallWorker.gotoAnyDestroyedRoom();
}
}
return wallWorker.getMaze();
}
/**
* 规则1:去到相邻的没去过的房间,并砸开与相邻房间之间的墙
*
* @return
*/
private boolean destroyStraightRoom() {
// 隔壁房间(上下左右)中违法房间的集合
List<Integer> illegalRooms = new ArrayList<>();
// 遍历隔壁房间
while (true) {
// 所有隔壁房间都访问失败
if (illegalRooms.size() == 4) {
return false;
}
// 随机抽取一个隔壁房间(上下左右)
int roomIndex = (int) (Math.random() * 4);
// 隔壁房间的合法性的判定
if (!illegalRooms.contains(roomIndex)) {
// 开始砸墙
if (roomIndex == Constant.DIRECT.TOP.ordinal()) {
if (wallWorker.destroyTopWall()) {
return true;
}
} else if (roomIndex == Constant.DIRECT.BOTTOM.ordinal()) {
if (wallWorker.destroyBottomWall()) {
return true;
}
} else if (roomIndex == Constant.DIRECT.LEFT.ordinal()) {
if (wallWorker.destroyLeftWall()) {
return true;
}
} else {
if (wallWorker.destroyRightWall()) {
return true;
}
}
// 访问失败
illegalRooms.add(roomIndex);
}
}
}
/**
* 开始迷宫游戏
*
* @param startPoint 起点
* @param endPoint 终点
*
*/
public Room[][] playMazeGame(Room[][] maze, Point startPoint, Point endPoint) {
// 创建玩家
player = new Player(maze, startPoint.x, startPoint.y);
// 到达终点
gotoEndPoint(startPoint, endPoint);
List<Point> pointList = player.getPathList();
for (int i = 0; i < pointList.size() - 1; i++) {
// 当前通路房间位置
int v = pointList.get(i).x;
int h = pointList.get(i).y;
// 下一个通路房间的位置
int nextv = pointList.get(i + 1).x;
int nexth = pointList.get(i + 1).y;
// 设置当前房间为通路房间
maze[v][h].getCenterWall().setType(Wall.TYPE.PATH);
// 设置当前房间和下一个房间之间的墙体的类型
if (v - 1 == nextv) {
maze[v][h].getTopWall().setType(Wall.TYPE.PATH);
maze[nextv][nexth].getBottomWall().setType(Wall.TYPE.PATH);
} else if (v + 1 == nextv) {
maze[v][h].getBottomWall().setType(Wall.TYPE.PATH);
maze[nextv][nexth].getTopWall().setType(Wall.TYPE.PATH);
} else if (h - 1 == nexth) {
maze[v][h].getLeftWall().setType(Wall.TYPE.PATH);
maze[nextv][nexth].getRightWall().setType(Wall.TYPE.PATH);
} else {
maze[v][h].getRightWall().setType(Wall.TYPE.PATH);
maze[nextv][nexth].getLeftWall().setType(Wall.TYPE.PATH);
}
}
maze[pointList.get(pointList.size() - 1).x][pointList.get(pointList.size() - 1).y].getCenterWall()
.setType(Wall.TYPE.PATH);
return maze;
}
/**
* 从起点走到终点
*
* @param maze 迷宫
*/
private void gotoEndPoint(Point startPoint, Point endPoint) {
int direct = 0;
while (true) {
// 如果到达终点,则寻路成功
if (player.getVertical() == endPoint.x && player.getHorizontal() == endPoint.y) {
break;
}
// 遍历周围的房间(上下左右)
if (direct > 3) {
direct = 0;
}
if (direct == Constant.DIRECT.TOP.ordinal()) {
player.walkTopRoom();
} else if (direct == Constant.DIRECT.BOTTOM.ordinal()) {
player.walkBottomRoom();
} else if (direct == Constant.DIRECT.LEFT.ordinal()) {
player.walkLeftRoom();
} else {
player.walkRightRoom();
}
direct++;
}
}
/**
* @return the maze
*/
public Room[][] getMaze() {
return maze;
}
/**
* @param maze the maze to set
*/
public void setMaze(Room[][] maze) {
this.maze = maze;
}
/**
* @return the mazeLength
*/
public int getMazeLength() {
return mazeLength;
}
/**
* @param mazeLength the mazeLength to set
*/
public void setMazeLength(int mazeLength) {
this.mazeLength = mazeLength;
}
/**
* @return the wallWorker
*/
public WallWorker getWallWorker() {
return wallWorker;
}
/**
* @param wallWorker the wallWorker to set
*/
public void setWallWorker(WallWorker wallWorker) {
this.wallWorker = wallWorker;
}
/**
* @return the player
*/
public Player getPlayer() {
return player;
}
/**
* @param player the player to set
*/
public void setPlayer(Player player) {
this.player = player;
}
}
Player.java
package maze.view;
import java.awt.Point;
import java.util.ArrayList;
import java.util.List;
/**
* 玩家类
*
* @author 见瑞彬
*
*/
public class Player {
/** 玩家水平坐标 */
private int horizontal;
/** 玩家垂直坐标 */
private int vertical;
/** 玩家所在的迷宫 */
private Room[][] maze;
/** 记录玩家走过的轨迹 */
List<Point> pathList;
/**
* 设定玩家默认属性
*
* @param maze
* @param vertical
* @param horizontal
*/
public Player(Room[][] maze, int vertical, int horizontal) {
// 迷宫
this.maze = new Room[maze.length][maze.length];
for (int i = 0; i < maze.length; i++) {
for (int j = 0; j < maze.length; j++) {
this.maze[i][j] = new Room(maze[i][j].getVertical(), maze[i][j].getHorizontal(), maze[i][j].getWidth(),
new Point(maze[i][j].getLeftTopWall().getHorizontalPx().intValue(),
maze[i][j].getLeftTopWall().getVerticalPx().intValue()),maze.length);
this.maze[i][j].setTopWall(maze[i][j].getTopWall());
this.maze[i][j].setBottomWall(maze[i][j].getBottomWall());
this.maze[i][j].setLeftWall(maze[i][j].getLeftWall());
this.maze[i][j].setRightWall(maze[i][j].getRightWall());
}
}
// 玩家位置
this.vertical = vertical;
this.horizontal = horizontal;
// 轨迹起点
pathList = new ArrayList<>();
pathList.add(new Point(vertical, horizontal));
}
/**
* 当前位置是否已经不在迷宫
*
* @param vertical
* @param horizontal
* @return
*/
private boolean isOutMaze(int vertical, int horizontal) {
if (vertical >= 0 && vertical < maze.length && horizontal >= 0 && horizontal < maze.length) {
// 不出界,返回false
return false;
}
// 出界返回true
return true;
}
/**
* 判断这个点是否走过
*
* @param vertical
* @param horizontal
* @return
*/
private boolean existsPoint(int vertical, int horizontal) {
for (int i = 0; i < pathList.size(); i++) {
if (pathList.get(i).x == vertical && pathList.get(i).y == horizontal) {
return true;
}
}
return false;
}
/**
* 走向上面的房间
*
* @return
*/
public void walkTopRoom() {
// 下面的位置
int nextVertical = vertical - 1;
int nextHorizontal = horizontal;
Room room = maze[vertical][horizontal];
// 如果玩家所在房间的上面有墙,则不能走向到上面的房间
if (room.getTopWall().getType() == Wall.TYPE.WALL) {
// 如果当前房间上左右有墙
if (room.getLeftWall().getType() == Wall.TYPE.WALL && room.getRightWall().getType() == Wall.TYPE.WALL) {
// 后面的位置
int lastVertical = vertical + 1;
int lastHorizontal = horizontal;
// 筑墙,防止再次走
maze[vertical][horizontal].getBottomWall().setType(Wall.TYPE.WALL);
maze[lastVertical][lastHorizontal].getTopWall().setType(Wall.TYPE.WALL);
// 已经走过的情况
if (existsPoint(lastVertical, lastHorizontal)) {
pathList.remove(pathList.size() - 1);
} else {
// 没有走过的情况
pathList.add(new Point(lastVertical, lastHorizontal));
}
// 更新位置
vertical = lastVertical;
horizontal = lastHorizontal;
}
return;
}
// 如果上面的房间已经走过了,则不能再走
if (existsPoint(nextVertical, nextHorizontal)) {
return;
}
// 如果出界了,不能继续走
if (isOutMaze(nextVertical, nextHorizontal)) {
return;
}
// 走到上面的房间
pathList.add(new Point(nextVertical, nextHorizontal));
// 更新位置
vertical = nextVertical;
horizontal = nextHorizontal;
}
/**
* 走向下面的房间
*
* @return
*/
public void walkBottomRoom() {
// 下面的位置
int nextVertical = vertical + 1;
int nextHorizontal = horizontal;
Room room = maze[vertical][horizontal];
// 如果玩家所在房间的下面有墙,则不能走向到下面的房间
if (room.getBottomWall().getType() == Wall.TYPE.WALL) {
// 如果当前房间下左右有墙
if (room.getLeftWall().getType() == Wall.TYPE.WALL && room.getRightWall().getType() == Wall.TYPE.WALL) {
// 后面的位置
int lastVertical = vertical - 1;
int lastHorizontal = horizontal;
// 筑墙,防止再次走
maze[vertical][horizontal].getTopWall().setType(Wall.TYPE.WALL);
maze[lastVertical][lastHorizontal].getBottomWall().setType(Wall.TYPE.WALL);
// 已经走过的情况
if (existsPoint(lastVertical, lastHorizontal)) {
pathList.remove(pathList.size() - 1);
} else {
// 没有走过的情况
pathList.add(new Point(lastVertical, lastHorizontal));
}
// 更新位置
vertical = lastVertical;
horizontal = lastHorizontal;
}
return;
}
// 如果上面的房间已经走过了,则不能再走
if (existsPoint(nextVertical, nextHorizontal)) {
return;
}
// 如果出界了,不能继续走
if (isOutMaze(nextVertical, nextHorizontal)) {
return;
}
// 走到下面的房间
pathList.add(new Point(nextVertical, nextHorizontal));
// 更新位置
vertical = nextVertical;
horizontal = nextHorizontal;
}
/**
* 走向左面的房间
*
* @return
*/
public void walkLeftRoom() {
// 左面的位置
int nextVertical = vertical;
int nextHorizontal = horizontal - 1;
Room room = maze[vertical][horizontal];
// 如果玩家所在房间的左面有墙,则不能走向到左面的房间
if (room.getLeftWall().getType() == Wall.TYPE.WALL) {
// 如果当前房间左上下有墙
if (room.getTopWall().getType() == Wall.TYPE.WALL && room.getBottomWall().getType() == Wall.TYPE.WALL) {
// 后面的位置
int lastVertical = vertical;
int lastHorizontal = horizontal + 1;
// 筑墙,防止再次走
maze[vertical][horizontal].getRightWall().setType(Wall.TYPE.WALL);
maze[lastVertical][lastHorizontal].getLeftWall().setType(Wall.TYPE.WALL);
// 已经走过的情况
if (existsPoint(lastVertical, lastHorizontal)) {
pathList.remove(pathList.size() - 1);
} else {
// 没有走过的情况
pathList.add(new Point(lastVertical, lastHorizontal));
}
// 更新位置
vertical = lastVertical;
horizontal = lastHorizontal;
}
return;
}
// 如果左面的房间已经走过了,则不能再走
if (existsPoint(nextVertical, nextHorizontal)) {
return;
}
// 如果出界了,不能继续走
if (isOutMaze(nextVertical, nextHorizontal)) {
return;
}
// 走到左面的房间
pathList.add(new Point(nextVertical, nextHorizontal));
// 更新位置
vertical = nextVertical;
horizontal = nextHorizontal;
}
/**
* 走向右面的房间
*
* @return
*/
public void walkRightRoom() {
// 右面的位置
int nextVertical = vertical;
int nextHorizontal = horizontal + 1;
Room room = maze[vertical][horizontal];
// 如果玩家所在房间的右面有墙,则不能走向到右面的房间
if (room.getRightWall().getType() == Wall.TYPE.WALL) {
// 如果当前房间上下右有墙
if (room.getTopWall().getType() == Wall.TYPE.WALL && room.getBottomWall().getType() == Wall.TYPE.WALL) {
// 后面的位置
int lastVertical = vertical;
int lastHorizontal = horizontal - 1;
// 筑墙,防止再次走
maze[vertical][horizontal].getLeftWall().setType(Wall.TYPE.WALL);
maze[lastVertical][lastHorizontal].getRightWall().setType(Wall.TYPE.WALL);
// 已经走过的情况
if (existsPoint(lastVertical, lastHorizontal)) {
pathList.remove(pathList.size() - 1);
} else {
// 没有走过的情况
pathList.add(new Point(lastVertical, lastHorizontal));
}
// 更新位置
vertical = lastVertical;
horizontal = lastHorizontal;
}
return;
}
// 如果右面的房间已经走过了,则不能再走
if (existsPoint(nextVertical, nextHorizontal)) {
return;
}
// 如果下面的位置出界了,则不能继续走
if (isOutMaze(nextVertical, nextHorizontal)) {
return;
}
// 走到右面的房间
pathList.add(new Point(nextVertical, nextHorizontal));
// 更新位置
vertical = nextVertical;
horizontal = nextHorizontal;
}
/**
* @return the thoughPoints
*/
public List<Point> getPathList() {
return pathList;
}
/**
* @return the horizontal
*/
public int getHorizontal() {
return horizontal;
}
/**
* @return the vertical
*/
public int getVertical() {
return vertical;
}
}
Room.java
package maze.view;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Point;
import java.math.BigDecimal;
import java.math.RoundingMode;
public class Room {
/** 上面的墙 */
private Wall topWall;
/** 下面的墙 */
private Wall bottomWall;
/** 左面的墙 */
private Wall leftWall;
/** 右面的墙 */
private Wall rightWall;
/** 左上角墙体 */
private Wall leftTopWall;
/** 左下角墙体 */
private Wall leftBottomWall;
/** 右上角墙体 */
private Wall rightTopWall;
/** 右下角墙体 */
private Wall rightBottomWall;
/** 中间墙体 */
private Wall centerWall;
/** 是否墙体被砸过 */
private boolean destroyed;
/** 水平坐标 */
private int horizontal;
/** 垂直坐标 */
private int vertical;
/** 房间宽度(两侧墙体+房间中心) */
private BigDecimal width;
int mazeLength;
/***
* 设定房间默认属性
*
* @param vertical 垂直坐标位置
* @param horizontal 水平坐标位置
* @param width 房间宽度
*/
public Room(int vertical, int horizontal, BigDecimal width,Point location,int mazeLength) {
this.mazeLength = mazeLength;
// 设定房间坐标位置
this.vertical = vertical;
this.horizontal = horizontal;
// ***************** 计算房间在迷宫中的像素位置,并设定各个墙体的位置和宽高 *****************
BigDecimal vPx = new BigDecimal(vertical).multiply(width).add(new BigDecimal(location.y));
BigDecimal hPx = new BigDecimal(horizontal).multiply(width).add(new BigDecimal(location.x));
// 墙体单元宽度
BigDecimal unit = width.divide(new BigDecimal(4), RoundingMode.DOWN); // 宽度的1/4
BigDecimal unit2 = unit.add(unit); // 宽度的2/4
BigDecimal unit3 = unit2.add(unit); // 宽度的3/4
BigDecimal one = new BigDecimal(1);
BigDecimal two = new BigDecimal(2);
// 设定四角的墙体,显示墙体颜色
// 设定左上角墙体
Wall leftTopWall = new Wall();
leftTopWall.setVerticalPx(vPx);
leftTopWall.setHorizontalPx(hPx);
leftTopWall.setWidthPx(unit);
leftTopWall.setHeightPx(unit);
leftTopWall.setType(Wall.TYPE.WALL);
this.setLeftTopWall(leftTopWall);
// 设定左下角墙体
Wall leftBottomWall = new Wall();
leftBottomWall.setVerticalPx(vPx.add(unit3));
leftBottomWall.setHorizontalPx(hPx);
leftBottomWall.setWidthPx(unit);
if(this.getVertical() == mazeLength - 1) {
leftBottomWall.setHeightPx(unit);
}else {
leftBottomWall.setHeightPx(unit.add(one));
}
leftBottomWall.setType(Wall.TYPE.WALL);
this.setLeftBottomWall(leftBottomWall);
// 设定右上角墙体
Wall rightTopWall = new Wall();
rightTopWall.setVerticalPx(vPx);
rightTopWall.setHorizontalPx(hPx.add(unit3));
if(this.getHorizontal() == mazeLength - 1) {
rightTopWall.setWidthPx(unit2);
}else {
rightTopWall.setWidthPx(unit.add(one));
}
rightTopWall.setHeightPx(unit);
rightTopWall.setType(Wall.TYPE.WALL);
this.setRightTopWall(rightTopWall);
// 设定右下角墙体
Wall rightBottomWall = new Wall();
rightBottomWall.setVerticalPx(vPx.add(unit3));
rightBottomWall.setHorizontalPx(hPx.add(unit3));
if(this.getHorizontal() == mazeLength - 1) {
rightBottomWall.setWidthPx(unit2);
}else {
rightBottomWall.setWidthPx(unit.add(one));
}
if(this.getVertical() == mazeLength - 1) {
rightBottomWall.setHeightPx(unit);
}else {
rightBottomWall.setHeightPx(unit.add(one));
}
rightBottomWall.setType(Wall.TYPE.WALL);
this.setRightBottomWall(rightBottomWall);
// 设定四边墙体,默认是透明,显示迷宫背景色
// 设定上面墙体
Wall topWall = new Wall();
topWall.setHorizontalPx(hPx.add(unit).subtract(one));
topWall.setVerticalPx(vPx);
topWall.setWidthPx(unit2.add(two));
topWall.setHeightPx(unit);
topWall.setType(Wall.TYPE.WALL);
this.setTopWall(topWall);
// 设定下面墙体
Wall bottomWall = new Wall();
bottomWall.setHorizontalPx(hPx.add(unit).subtract(one));
bottomWall.setVerticalPx(vPx.add(unit3));
bottomWall.setWidthPx(unit2.add(two));
if(this.getVertical() == mazeLength - 1) {
bottomWall.setHeightPx(unit);
}else {
bottomWall.setHeightPx(unit.add(one));
}
bottomWall.setType(Wall.TYPE.WALL);
this.setBottomWall(bottomWall);
// 设定左面墙体
Wall leftWall = new Wall();
leftWall.setHorizontalPx(hPx);
leftWall.setVerticalPx(vPx.add(unit).subtract(one));
leftWall.setWidthPx(unit);
leftWall.setHeightPx(unit2.add(two));
leftWall.setType(Wall.TYPE.WALL);
this.setLeftWall(leftWall);
// 设定右面墙体
Wall rightWall = new Wall();
rightWall.setHorizontalPx(hPx.add(unit3));
rightWall.setVerticalPx(vPx.add(unit).subtract(one));
if(this.getHorizontal() == mazeLength - 1) {
rightWall.setWidthPx(unit2);
}else {
rightWall.setWidthPx(unit.add(one));
}
rightWall.setHeightPx(unit2.add(two));
rightWall.setType(Wall.TYPE.WALL);
this.setRightWall(rightWall);
// 设定中间墙体
Wall centerWall = new Wall();
centerWall.setVerticalPx(vPx.add(unit));
centerWall.setHorizontalPx(hPx.add(unit));
centerWall.setWidthPx(unit2);
centerWall.setHeightPx(unit2);
centerWall.setType(Wall.TYPE.DESTROYED);
this.setCenterWall(centerWall);
// 设定房间状态,默认房间的墙体没有被砸
this.destroyed = false;
// 设定房间宽度
this.width = width;
}
/**
* 画房间
*
* @param g 画笔
* @param showPathFlg 是否画路径
*/
public void draw(Graphics g) {
Color color = g.getColor();
// 画墙的颜色
Color wallColor = Color.RED;
g.setColor(wallColor);
// 画四角的墙
if(this.getVertical() == 0) {
g.fillRect(
this.getLeftTopWall().getHorizontalPx().intValue()
,this.getLeftTopWall().getVerticalPx().subtract(this.getLeftTopWall().getHeightPx()).intValue()+1
,this.getLeftTopWall().getWidthPx().intValue()
,this.getLeftTopWall().getHeightPx().intValue()
);
g.fillRect(
this.getLeftTopWall().getHorizontalPx().intValue()
,this.getLeftTopWall().getVerticalPx().intValue()
,this.getLeftTopWall().getWidthPx().intValue()
,this.getLeftTopWall().getHeightPx().intValue()
);
}else {
g.fillRect(
this.getLeftTopWall().getHorizontalPx().intValue()
,this.getLeftTopWall().getVerticalPx().intValue()
,this.getLeftTopWall().getWidthPx().intValue()
,this.getLeftTopWall().getHeightPx().intValue()
);
}
g.fillRect(
this.getLeftBottomWall().getHorizontalPx().intValue()
,this.getLeftBottomWall().getVerticalPx().intValue()
,this.getLeftBottomWall().getWidthPx().intValue()
,this.getLeftBottomWall().getHeightPx().intValue()
);
if(this.getVertical() == 0) {
g.fillRect(
this.getRightTopWall().getHorizontalPx().intValue()
,this.getRightTopWall().getVerticalPx().subtract(this.getRightTopWall().getHeightPx()).intValue()+1
,this.getRightTopWall().getWidthPx().intValue()
,this.getRightTopWall().getHeightPx().intValue()
);
g.fillRect(
this.getRightTopWall().getHorizontalPx().intValue()
,this.getRightTopWall().getVerticalPx().intValue()
,this.getRightTopWall().getWidthPx().intValue()
,this.getRightTopWall().getHeightPx().intValue()
);
}else {
g.fillRect(
this.getRightTopWall().getHorizontalPx().intValue()
,this.getRightTopWall().getVerticalPx().intValue()
,this.getRightTopWall().getWidthPx().intValue()
,this.getRightTopWall().getHeightPx().intValue()
);
}
g.fillRect(
this.getRightBottomWall().getHorizontalPx().intValue()
,this.getRightBottomWall().getVerticalPx().intValue()
,this.getRightBottomWall().getWidthPx().intValue()
,this.getRightBottomWall().getHeightPx().intValue()
);
// 画四边的墙
if (this.getTopWall().getType() == Wall.TYPE.WALL) {
if(this.getVertical() == 0) {
g.fillRect(
this.getTopWall().getHorizontalPx().intValue()
,this.getTopWall().getVerticalPx().subtract(this.getTopWall().getHeightPx()).intValue()+1
,this.getTopWall().getWidthPx().intValue()
,this.getTopWall().getHeightPx().intValue()
);
g.fillRect(
this.getTopWall().getHorizontalPx().intValue()
,this.getTopWall().getVerticalPx().intValue()
,this.getTopWall().getWidthPx().intValue()
,this.getTopWall().getHeightPx().intValue()
);
}else {
g.fillRect(
this.getTopWall().getHorizontalPx().intValue()
,this.getTopWall().getVerticalPx().intValue()
,this.getTopWall().getWidthPx().intValue()
,this.getTopWall().getHeightPx().intValue()
);
}
}
if (this.getBottomWall().getType() == Wall.TYPE.WALL) {
g.fillRect(
this.getBottomWall().getHorizontalPx().intValue()
,this.getBottomWall().getVerticalPx().intValue()
,this.getBottomWall().getWidthPx().intValue()
,this.getBottomWall().getHeightPx().intValue()
);
}
if (this.getLeftWall().getType() == Wall.TYPE.WALL) {
g.fillRect(
this.getLeftWall().getHorizontalPx().intValue()
,this.getLeftWall().getVerticalPx().intValue()
,this.getLeftWall().getWidthPx().intValue()
,this.getLeftWall().getHeightPx().intValue()
);
}
if (this.getRightWall().getType() == Wall.TYPE.WALL) {
g.fillRect(
this.getRightWall().getHorizontalPx().intValue()
,this.getRightWall().getVerticalPx().intValue()
,this.getRightWall().getWidthPx().intValue()
,this.getRightWall().getHeightPx().intValue()
);
}
// 画路径的颜色
Color pathColor = Color.GREEN;
g.setColor(pathColor);
BigDecimal unit = this.getCenterWall().getWidthPx().divide(new BigDecimal(4));
BigDecimal unit2 = unit.multiply(new BigDecimal(2));
BigDecimal unit3 = unit.multiply(new BigDecimal(3));
// 画路径
if (this.getCenterWall().getType() == Wall.TYPE.PATH) {
// 上
if (this.getTopWall().getType() == Wall.TYPE.PATH) {
// 上面的墙
g.fillRect(
this.getTopWall().getHorizontalPx().add(unit).intValue(),
this.getTopWall().getVerticalPx().intValue()-1,
unit2.intValue(),
this.getTopWall().getHeightPx().intValue()+2);
// 中间的墙
g.fillRect(
this.getCenterWall().getHorizontalPx().add(unit).intValue(),
this.getCenterWall().getVerticalPx().intValue(),
unit2.intValue()
,unit3.intValue()
);
}
// 下
if (this.getBottomWall().getType() == Wall.TYPE.PATH) {
// 下面的墙
g.fillRect(
this.getBottomWall().getHorizontalPx().add(unit).intValue()
,this.getBottomWall().getVerticalPx().intValue()-1
,unit2.intValue()
,this.getBottomWall().getHeightPx().intValue()+2
);
// 中间的墙
g.fillRect(
this.getCenterWall().getHorizontalPx().add(unit).intValue(),
this.getCenterWall().getVerticalPx().add(unit).intValue(),
unit2.intValue()
,unit3.intValue()
);
}
if (this.getLeftWall().getType() == Wall.TYPE.PATH) {
// 左面的墙
g.fillRect(
this.getLeftWall().getHorizontalPx().intValue()-1
,this.getLeftWall().getVerticalPx().add(unit).intValue()
,this.getLeftWall().getWidthPx().intValue()+2
, unit2.intValue()
);
// 中间的墙
g.fillRect(
this.getCenterWall().getHorizontalPx().intValue()
,this.getCenterWall().getVerticalPx().add(unit).intValue()
,unit3.intValue()
,unit2.intValue()
);
}
if (this.getRightWall().getType() == Wall.TYPE.PATH) {
// 右面的墙
g.fillRect(
this.getRightWall().getHorizontalPx().intValue()-1
,this.getRightWall().getVerticalPx().add(unit).intValue()
,this.getRightWall().getWidthPx().intValue()+2
,unit2.intValue()
);
// 中间的墙
g.fillRect(
this.getCenterWall().getHorizontalPx().add(unit).intValue()
,this.getCenterWall().getVerticalPx().add(unit).intValue()
,unit3.intValue()
,unit2.intValue()
);
}
}
g.setColor(color);
}
/**
* @return the topWall
*/
public Wall getTopWall() {
return topWall;
}
/**
* @param topWall the topWall to set
*/
public void setTopWall(Wall topWall) {
Wall wall = new Wall();
wall.setType(topWall.getType());
wall.setHeightPx(topWall.getHeightPx());
wall.setHorizontalPx(topWall.getHorizontalPx());
wall.setVerticalPx(topWall.getVerticalPx());
wall.setWidthPx(topWall.getWidthPx());
this.topWall = wall;
}
/**
* @return the bottomWall
*/
public Wall getBottomWall() {
return bottomWall;
}
/**
* @param bottomWall the bottomWall to set
*/
public void setBottomWall(Wall bottomWall) {
Wall wall = new Wall();
wall.setType(bottomWall.getType());
wall.setHeightPx(bottomWall.getHeightPx());
wall.setHorizontalPx(bottomWall.getHorizontalPx());
wall.setVerticalPx(bottomWall.getVerticalPx());
wall.setWidthPx(bottomWall.getWidthPx());
this.bottomWall = wall;
}
/**
* @return the leftWall
*/
public Wall getLeftWall() {
return leftWall;
}
/**
* @param leftWall the leftWall to set
*/
public void setLeftWall(Wall leftWall) {
Wall wall = new Wall();
wall.setType(leftWall.getType());
wall.setHeightPx(leftWall.getHeightPx());
wall.setHorizontalPx(leftWall.getHorizontalPx());
wall.setVerticalPx(leftWall.getVerticalPx());
wall.setWidthPx(leftWall.getWidthPx());
this.leftWall = wall;
}
/**
* @return the rightWall
*/
public Wall getRightWall() {
return rightWall;
}
/**
* @param rightWall the rightWall to set
*/
public void setRightWall(Wall rightWall) {
Wall wall = new Wall();
wall.setType(rightWall.getType());
wall.setHeightPx(rightWall.getHeightPx());
wall.setHorizontalPx(rightWall.getHorizontalPx());
wall.setVerticalPx(rightWall.getVerticalPx());
wall.setWidthPx(rightWall.getWidthPx());
this.rightWall = wall;
}
/**
* @return the leftTopWall
*/
public Wall getLeftTopWall() {
return leftTopWall;
}
/**
* @param leftTopWall the leftTopWall to set
*/
public void setLeftTopWall(Wall leftTopWall) {
this.leftTopWall = leftTopWall;
}
/**
* @return the leftBottomWall
*/
public Wall getLeftBottomWall() {
return leftBottomWall;
}
/**
* @param leftBottomWall the leftBottomWall to set
*/
public void setLeftBottomWall(Wall leftBottomWall) {
this.leftBottomWall = leftBottomWall;
}
/**
* @return the rightTopWall
*/
public Wall getRightTopWall() {
return rightTopWall;
}
/**
* @param rightTopWall the rightTopWall to set
*/
public void setRightTopWall(Wall rightTopWall) {
this.rightTopWall = rightTopWall;
}
/**
* @return the rightBottomWall
*/
public Wall getRightBottomWall() {
return rightBottomWall;
}
/**
* @param rightBottomWall the rightBottomWall to set
*/
public void setRightBottomWall(Wall rightBottomWall) {
this.rightBottomWall = rightBottomWall;
}
/**
* @return the centerWall
*/
public Wall getCenterWall() {
return centerWall;
}
/**
* @param centerWall the centerWall to set
*/
public void setCenterWall(Wall centerWall) {
this.centerWall = centerWall;
}
/**
* @return the destroyed
*/
public boolean isDestroyed() {
return destroyed;
}
/**
* @param destroyed the destroyed to set
*/
public void setDestroyed(boolean destroyed) {
this.destroyed = destroyed;
}
/**
* @return the horizontal
*/
public int getHorizontal() {
return horizontal;
}
/**
* @param horizontal the horizontal to set
*/
public void setHorizontal(int horizontal) {
this.horizontal = horizontal;
}
/**
* @return the vertical
*/
public int getVertical() {
return vertical;
}
/**
* @param vertical the vertical to set
*/
public void setVertical(int vertical) {
this.vertical = vertical;
}
/**
* @return the width
*/
public BigDecimal getWidth() {
return width;
}
/**
* @param width the width to set
*/
public void setWidth(BigDecimal width) {
this.width = width;
}
}
Start.java
package maze.view;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.channels.FileLock;
public class Start {
private static FileLock lock = null;
// 判断该应用是否已启动
public static boolean isRunning() {
try {
// 获得实例标志文件
File flagFile = new File(".lock");
// 如果不存在就新建一个
if (!flagFile.exists())
flagFile.createNewFile();
// 获得文件锁
lock = new FileOutputStream(flagFile).getChannel().tryLock();
// 返回空表示文件已被运行的实例锁定
if (lock == null)
return false;
} catch (Exception ex) {
ex.printStackTrace();
}
return true;
}
public static void main(String[] args) {
MainFrame mf = null;
// 保证只有一个主窗体运行
if (isRunning()) {
mf = new MainFrame();
mf.addWindowListener(new WindowAdapter() {
@Override
public void windowClosed(WindowEvent e) {
super.windowClosing(e);
try {
lock.release();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
});
}
}
}
Wall.java
package maze.view;
import java.math.BigDecimal;
public class Wall {
/** 墙体类型 */
public static enum TYPE {
/** 被砸过的墙,显示迷宫背景色 */
DESTROYED
/** 正常的墙,显示墙的颜色 */
, WALL
/** 路,显示路的颜色 */
, PATH
, START
, END
}
/** 墙体垂直像素位置 */
private BigDecimal verticalPx;
/** 墙体水平像素位置 */
private BigDecimal horizontalPx;
/** 墙体像素宽度 */
private BigDecimal widthPx;
/** 墙体像素高度 */
private BigDecimal heightPx;
/** 墙的类型 */
private TYPE type;
public Wall() {
// 墙体类型默认是透明,显示迷宫背景色
this.type = TYPE.DESTROYED;
}
/**
* @return the verticalPx
*/
public BigDecimal getVerticalPx() {
return verticalPx;
}
/**
* @param verticalPx the verticalPx to set
*/
public void setVerticalPx(BigDecimal verticalPx) {
this.verticalPx = verticalPx;
}
/**
* @return the horizontalPx
*/
public BigDecimal getHorizontalPx() {
return horizontalPx;
}
/**
* @param horizontalPx the horizontalPx to set
*/
public void setHorizontalPx(BigDecimal horizontalPx) {
this.horizontalPx = horizontalPx;
}
/**
* @return the widthPx
*/
public BigDecimal getWidthPx() {
return widthPx;
}
/**
* @param widthPx the widthPx to set
*/
public void setWidthPx(BigDecimal widthPx) {
this.widthPx = widthPx;
}
/**
* @return the heightPx
*/
public BigDecimal getHeightPx() {
return heightPx;
}
/**
* @param heightPx the heightPx to set
*/
public void setHeightPx(BigDecimal heightPx) {
this.heightPx = heightPx;
}
/**
* @return the type
*/
public TYPE getType() {
return type;
}
/**
* @param type the type to set
*/
public void setType(TYPE type) {
this.type = type;
}
}
WallWorker.java
package maze.view;
/**
* 迷宫砸墙工人类
*
* @author 见瑞彬
*
*/
public class WallWorker {
/** 砸墙工人水平坐标 */
private int horizontal;
/** 砸墙工人垂直坐标 */
private int vertical;
/** 砸墙工人所在的迷宫 */
private Room[][] maze;
/**
*
* @param startHorizontal 起点水平坐标
* @param startVertical 起点垂直坐标
* @param maze 迷宫
*/
public WallWorker(Room[][] maze) {
// 取得迷宫
this.maze = maze;
// 设定 砸墙工人的起点房间
this.setVertical(0);
this.setHorizontal(0);
maze[0][0].setDestroyed(true);
}
/**
* 所有的房间是否都被砸过墙
*
* @return
*/
public boolean destroyAllRoom() {
for (int i = 0; i < maze.length; i++) {
for (int j = 0; j < maze.length; j++) {
// 当判定该房间没有的墙没有被砸过,则继续砸墙
if (!maze[i][j].isDestroyed()) {
return false;
}
}
}
return true;
}
/**
* 就传送到一个被砸过的房间里
*/
public void gotoAnyDestroyedRoom() {
while (true) {
// 随机位置
int vertical = (int) (Math.random() * maze.length);
int horizontal = (int) (Math.random() * maze.length);
// 已访问判定
if (maze[vertical][horizontal].isDestroyed()) {
// 访问这个房间
this.setVertical(vertical);
this.setHorizontal(horizontal);
break;
}
}
}
/**
* 当前位置是否已经不在迷宫
*
* @param vertical
* @param horizontal
* @return
*/
private boolean isOutMaze(int vertical, int horizontal) {
if (vertical >= 0 && vertical < maze.length && horizontal >= 0 && horizontal < maze.length) {
// 不出界,返回false
return false;
}
// 出界返回true
return true;
}
/**
* 砸开房间上面的墙
*
* @return
*/
public boolean destroyTopWall() {
// 上面房间的垂直、水平坐标
int nextVertical = this.getVertical() - 1;
int nextHorizontal = this.getHorizontal();
// 出界
if (isOutMaze(nextVertical, nextHorizontal)) {
return false;
}
// 如果已经被砸过
if (maze[nextVertical][nextHorizontal].isDestroyed()) {
return false;
}
// 砸墙
maze[getVertical()][getHorizontal()].getTopWall().setType(Wall.TYPE.DESTROYED);
maze[nextVertical][nextHorizontal].getBottomWall().setType(Wall.TYPE.DESTROYED);
maze[nextVertical][nextHorizontal].setDestroyed(true);
// 更新砸墙工人的位置
this.setVertical(nextVertical);
this.setHorizontal(nextHorizontal);
return true;
}
/**
* 砸开房间下面的墙
*
* @return
*/
public boolean destroyBottomWall() {
// 下面房间的垂直、水平坐标
int nextVertical = getVertical() + 1;
int nextHorizontal = getHorizontal();
// 出界
if (isOutMaze(nextVertical, nextHorizontal)) {
return false;
}
// 如果已经被砸过
if (maze[nextVertical][nextHorizontal].isDestroyed()) {
return false;
}
// 砸墙
maze[getVertical()][getHorizontal()].getBottomWall().setType(Wall.TYPE.DESTROYED);
maze[nextVertical][nextHorizontal].getTopWall().setType(Wall.TYPE.DESTROYED);
maze[nextVertical][nextHorizontal].setDestroyed(true);
// 更新砸墙工人的位置
this.setVertical(nextVertical);
this.setHorizontal(nextHorizontal);
return true;
}
/**
* 砸开房间左面的墙
*
* @return
*/
public boolean destroyLeftWall() {
// 左面房间的垂直、水平坐标
int nextVertical = getVertical();
int nextHorizontal = getHorizontal() - 1;
// 出界
if (isOutMaze(nextVertical, nextHorizontal)) {
return false;
}
// 如果已经被砸过
if (maze[nextVertical][nextHorizontal].isDestroyed()) {
return false;
}
// 砸墙
maze[getVertical()][getHorizontal()].getLeftWall().setType(Wall.TYPE.DESTROYED);
maze[nextVertical][nextHorizontal].getRightWall().setType(Wall.TYPE.DESTROYED);
maze[nextVertical][nextHorizontal].setDestroyed(true);
// 更新砸墙工人的位置
this.setVertical(nextVertical);
this.setHorizontal(nextHorizontal);
return true;
}
/**
* 砸开房间右面的墙
*
* @return
*/
public boolean destroyRightWall() {
// 右面房间的垂直、水平坐标
int nextVertical = getVertical();
int nextHorizontal = getHorizontal() + 1;
// 出界
if (isOutMaze(nextVertical, nextHorizontal)) {
return false;
}
// 如果已经被砸过
if (maze[nextVertical][nextHorizontal].isDestroyed()) {
return false;
}
// 砸墙
maze[getVertical()][getHorizontal()].getRightWall().setType(Wall.TYPE.DESTROYED);
maze[nextVertical][nextHorizontal].getLeftWall().setType(Wall.TYPE.DESTROYED);
maze[nextVertical][nextHorizontal].setDestroyed(true);
// 更新砸墙工人的位置
this.setVertical(nextVertical);
this.setHorizontal(nextHorizontal);
return true;
}
/**
* @return the horizontal
*/
public int getHorizontal() {
return horizontal;
}
/**
* @param horizontal the horizontal to set
*/
public void setHorizontal(int horizontal) {
this.horizontal = horizontal;
}
/**
* @return the vertical
*/
public int getVertical() {
return vertical;
}
/**
* @param vertical the vertical to set
*/
public void setVertical(int vertical) {
this.vertical = vertical;
}
/**
* @return the maze
*/
public Room[][] getMaze() {
return maze;
}
/**
* @param maze the maze to set
*/
public void setMaze(Room[][] maze) {
this.maze = maze;
}
}