迷宫 动画 java_Java实现可视化迷宫

代码地址如下:

http://www.demodashi.com/demo/14547.html

需求

使用深度优先算法求解迷宫路径,使用Java实现求解过程的可视化,可单步运行,形象直观。

演示效果

红色格子为迷宫终点,迷宫可放大缩小,为了录屏选择了较小的尺寸,有多种不同难度的迷宫可以加载。

简单迷宫

40e24105c8e7781ce1a11e27e9c502e0.gif

复杂迷宫

f0bd7f245897cbb2f01b879f05c80933.gif

项目运行

文件中有两个运行脚本,Windows下直接双击win运行.bat即可,linux和Mac运行sh文件中的命令即可,喜欢用IDE的也可自行创建项目。

运行项目后,点击菜单栏左上角的Map加载迷宫地图, 点击右下角的Run开始解迷宫,Step可单步运行,可通过速度进度条调节速度。

项目结构

Maze

├── classes # 存放编译生成的class文件

├── lib.jar # 打包好的gui库

├── map # 迷宫地图文件

│ ├── EasyMaze.txt

│ ├── FinalMaze01.txt

│ ├── FinalMaze02.txt

│ ├── FinalMaze03.txt

│ ├── FinalMaze04.txt

│ └── FinalMaze05.txt

├── src

│ ├── MazeBug.java

│ └── MazeBugRunner.java

├── linux运行.sh # 运行脚本

└── win运行.bat # 运行脚本

原理方法

使用深度优先算法,每个格子下一步都有上下左右4种走法,但是这4种走法并不是都是合法的,比如有些格子有障碍物,有些格式在边界之外,去掉这些剩下的才是合法的走法。

深度优先算法的思想就是:

找出当前位置A下一步合法的的格子,选择其中一个,往前走一步到达B。

如果B相邻的有合法格子,重复第1步;如果没有合法的,后退一步回到A,选择A的其他合法格子走;

重复以上方法,直到找到迷宫终点;

算法优化:上面的方法选择下一步走的方向是随机的,或者按照上下左右的顺序选择。但是很多迷宫都有偏向性,比如如果有右偏向性,那么每次都优先往右走可以更快走出迷宫。所以在实现的时候,记录每个方向走的次数,每往一个方向走一步就加1,如果回退就该方向减1,每次走都优先走次数最多的方向,当迷宫有偏向性时,该方法效率更高。

以项目中的迷宫为例,大部分情况下偏向性所需步数更少。

普通方法: 534 1175 350 973 1052

偏向性: 552 761 330 175 420

代码实现

/*

* 节点:存储方向和该方向所走的次数

* 往一个方向前进则加1,后退则减1

*/

class Node {

private int dir; // 方向,角度值

private int ct; // 该方向所走次数

public Node(int initdir, int initct) {

dir = initdir;

ct = initct;

}

public int getDir() {

return dir;

}

public int getCt() {

return ct;

}

public void setCt(int deta) {

ct += deta;

}

}

// 深度优先算法解迷宫,并且以小甲虫的形式呈现

public class MazeBug extends Bug {

private Location next; // 下一步要走的格子

private Integer stepCount = 0; // 所走的步数

private boolean isEnd = false; // 是否到达迷宫出口

private boolean hasShown = false; // 是否显示了结束信息

private Stack path = new Stack<>(); // 存储走过的路径

private ArrayList arr = new ArrayList<>();

public MazeBug() {

setColor(Color.GREEN);

arr.add(new Node(0, 0));

arr.add(new Node(90, 0));

arr.add(new Node(270, 0));

arr.add(new Node(180, 0));

}

// 周期性执行

public void act() {

boolean willMove = canMove(); // 是否还能继续移动

if (isEnd) { // 是否结束

if (!hasShown) { // 是否显示结束消息

String msg = stepCount.toString() + " steps";

JOptionPane.showMessageDialog(null, msg);

hasShown = true;

}

return;

} else if (willMove) { // 向前移动一个,步数加1

move();

++stepCount;

} else { // 不能移动,后退一步,将该方向的计数器减1

Grid grid = getGrid();

Location loc = this.getLocation();

Location top = path.pop();

++stepCount;

grid.remove(top);

this.setDirection(loc.getDirectionToward(top));

this.moveTo(top);

// 在走过的死路留下一朵白花

Flower flower = new Flower(Color.WHITE);

flower.putSelfInGrid(getGrid(), loc);

// 方向计数器减1

int dir = 180 + ((getDirection() / 90) % 2) * 180 - getDirection();

for (Node node : arr)

if (node.getDir() == dir) {

node.setCt(-1);

return;

}

}

}

// 找出和当前位置相邻的、合法的并且从未走过的格子

public Location getValid(Location loc) {

Grid gr = getGrid();

if (gr == null)

return null;

// 将每个方向走过的次数从大到小排序,下一步优先选次数多的方向走

Location adjLocation;

arr.sort(new Comparator() {

@Override

public int compare(Node a, Node b) {

return (a.getCt() < b.getCt()) ? 1 : -1;

}

});

for (Node node : arr) {

adjLocation = this.getLocation().getAdjacentLocation(node.getDir());

if (gr.isValid(adjLocation)

&& (gr.get(adjLocation) == null || gr.get(adjLocation).getColor().equals(Color.RED))) {

node.setCt(1);

return adjLocation;

}

}

return null;

}

// 判断当前位置是否可以继续移动

public boolean canMove() {

Grid gr = getGrid();

Actor adj;

Location loc = this.getValid(this.getLocation());

if (loc != null) {

adj = gr.get(loc);

next = loc;

isEnd = adj != null && adj.getColor().equals(Color.RED);

return true;

}

return false;

}

// 将甲虫的方向转向下一格,往前移动一步,将原来的位置压栈,并放置一朵绿花,表示走过的路径

public void move() {

Grid gr = getGrid();

if (gr == null)

return;

Location loc = this.getLocation();

path.push(loc);

this.setDirection(loc.getDirectionToward(next));

this.moveTo(next);

Flower flower = new Flower(this.getColor());

flower.putSelfInGrid(gr, loc);

}

}

其他:

跟算法无关的代码,比如GUI方面的都打包成lib.jar了,如果想要自己更改可以自行解压。Java实现可视化迷宫

代码地址如下:

http://www.demodashi.com/demo/14547.html

注:本文著作权归作者,由demo大师代发,拒绝转载,转载需要作者授权

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值