Java实现可视化迷宫
需求
使用深度优先算法求解迷宫路径,使用Java实现求解过程的可视化,可单步运行,形象直观。
演示效果
红色格子为迷宫终点,迷宫可放大缩小,为了录屏选择了较小的尺寸,有多种不同难度的迷宫可以加载。
- 简单迷宫
- 复杂迷宫
项目运行
文件中有两个运行脚本,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<Location> path = new Stack<>(); // 存储走过的路径
private ArrayList<Node> 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<Actor> 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<Actor> gr = getGrid();
if (gr == null)
return null;
// 将每个方向走过的次数从大到小排序,下一步优先选次数多的方向走
Location adjLocation;
arr.sort(new Comparator<Node>() {
@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<Actor> 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<Actor> 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实现可视化迷宫
注:本文著作权归作者,由demo大师代发,拒绝转载,转载需要作者授权
Java实现可视化迷宫的更多相关文章
- 超级好用的 Java 数据可视化库:Tablesaw
本文适合刚学习完 Java 语言基础的人群,跟着本文可了解和使用 Tablesaw 项目.示例均在 Windows 操作系统下演示 本文作者:HelloGitHub-秦人 HelloGitHub 推出 ...
- 【JAVA】可视化计算器
import java.awt.Color; import java.awt.Font; import java.awt.GridLayout; import java.awt.event.Actio ...
- java的WindowBuilder可视化插件
一直做在安卓用xml作界面,对于java的控件不熟悉,也不习惯用代码做UI尤其是布局. 找了一下发现可以安装windowbuilder来实现java的可视化编程,但是很多资料里的连接都失效了. 刚自己 ...
- java可视化编程-eclipse安装windowbuilder插件(转载)
原文地址:http://blog.csdn.net/jason0539/article/details/21219043 一直做在安卓用xml作界面,对于java的控件不熟悉,也不习惯用代码做UI尤其 ...
- 基于Java visualvm的可视化监控的使用
1 Java visualVM可视化监控工具打开方式 ctrl + r 快捷键调出运行窗口,输出 jvisualvm指令,即可打开java visualVM工具.详情如下图: 2 Java Visua ...
- 归并排序算法 java 实现
归并排序算法 java 实现 可视化对比十多种排序算法(C#版) [直观学习排序算法] 视觉直观感受若干常用排序算法 算法概念 归并排序是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Di ...
- [2]R语言在数据处理上的禀赋之——可视化技术
本文目录 Java的可视化技术 R的可视化技术 二维做图利器plot的参数配置 *权限机制 *plot独有的参数 *plot的type介绍 *title介绍 *公共参数集合--par *par的权限机 ...
- 7个Java项目,或许你的大学老师就会布置
前言: 有天吃饭和朋友聊天,说到大学老师布置的开发项目,结果我们一干人说出来的都基本一样,入门级别的计算器啦,稍微大一点的记事本啦,然后到后面的图书管理系统啊,购物网站啊-- 发现这些项目都是大学老师 ...
- 并发编程 || Java线程详解
通用线程模型 在很多研发当中,实际应用是基于一个理论再进行优化的.所以,在了解JVM规范中的Java线程的生命周期之前,我们可以先了解通用的线程生命周期,这有助于我们后续对JVM线程生命周期的理解. ...
随机推荐
- 模拟出ios中流行的黑色背景底
[activityIndicatorView setBackgroundColor:[UIColor colorWithRed: green: blue: alpha:0.4]]; 用上面的语法,可以 ...
- mac 下 outlook 邮箱 服务器端口设置
- hadoop安装入门
1.jdk安装和配置 1.1下载最新jdk文件 http://www.oracle.com/technetwork/java/javase/downloads/jdk7-downloads-18802 ...
- FFmpeg的H264编码有内存泄漏吗??!!!
靠,内存泄漏好严重.开始怀疑是自己代码问题,调试了半天,又反复改写和优化代码,还是泄漏严重. 拿网上现成的FFMPEG H264编码的范例来测试,同样泄漏很严重. 百度了一下,有很多人遇到同样的问题, ...
- 【BZOJ】【3489】A simple rmq problem
KD-Tree(乱搞) Orz zyf教给蒟蒻做法 蒟蒻并不会这题正解……(可持久化树套树?...Orz 对于每个点,我们可以求出pre[i],nex[i],那么询问的答案就是:求max (a[i]) ...
- Objective-C:对象之间循环引用会造成死循环
对象之间的循环引用 两个对象A.B,有可能会出现一种特殊的情况:A中包含B的实例变量:B中又包含A的实例变量,如果两个实例变量都是强引用(A有B实例变量的所有权,B也有A的实例变量的所有 ...
- [20] 鼓状物(Drum)图形的生成算法
顶点数据的生成 bool YfBuildDrumVertices ( Yreal radius, Yreal assistRadius, Yuint slices, Yuint stacks, YeO ...
- 中国大学MOOC-陈越、何钦铭-数据结构-笔记
中国大学MOOC-陈越.何钦铭-数据结构-2017春 跟着<中国大学MOOC-陈越.何钦铭-数据结构-2017春>学习,平时练习一下pat上的作业外:在这里记录一下:平时学习视屏的收获. ...
- https://leetcode-cn.com/
https://leetcode-cn.com/ 码,马不停蹄,码不停题 英文版:https://leetcode.com/
- libsvm svmtrain函数运行出错问题
我安装的是matlab R2013a 安装上libsvm后需要设置set path 为libsvm的所有文件夹加载上,但是发现每次重新打开之后,之前加载的又不见了,所有导致出现,使用svmsrai ...