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线程生命周期的理解. ...
随机推荐
- JVM内存模型及垃圾回收算法
国内私募机构九鼎控股打造APP,来就送 20元现金领取地址:http://jdb.jiudingcapital.com/phone.html内部邀请码:C8E245J (不写邀请码,没有现金送)国内私 ...
- @selector 如何调用在另一个类中的静态函数?
可以在同一个类的methodName这个函数中再调用另一个类中的静态方法
- ie不支持max-height的解决之法
.div{ max-height: 100px; _height:expression(this.scrollHeight > 100 ? "100px" : "a ...
- Java开发工具全面比较
1.JDK (Java Development Kit)Java开发工具集 从初学者角度来看Java开发工具,采用JDK开发Java程序能够很快理解程序中各部分代码之间的关系,有利于理解Java面向对 ...
- 解决sqoop导入报错:Caused by: java.sql.SQLException: Protocol violation
报错信息: -- ::, INFO [main] org.apache.hadoop.mapred.MapTask: Ignoring exception during close for org.a ...
- Jquery源码分析之匿名函数的自执行
匿名函数的格式: 格式: (function(){ //代码 })(); //和这个基于jQuery的比较下: $(function(){ alert("this is a test&quo ...
- Coursera课程《Python数据结构》中课件
You can access the Google Drive containing all of the current and in-progress lecture slides for thi ...
- 3D屏保:N皇后
前几天园子里有人发表关于8皇后的算法.只有代码,没有能运行的DEMO多枯燥.于是我这两天抽时间写了个N皇后的屏保程序.程序启动后会从4皇后到14皇后显示其所有排列,每隔0.5秒自动切换一次.按下空格键 ...
- Nginx zabbix 的监控
Nginx zabbix 的监控 Nginx 配置 Nginx 必须包含:http_stub_status_module 模块 ./nginx -V |grep http_stub_status_mo ...
- Android -- uses-sdk:minSdkVersion 10 cannot be smaller than version L declared in library com.android.support:appcompat-v7:21.0.0-rc1
这是一个报错,是我在Android Studio上添加完Support-v4和v7包之后爆出的错误,百度了好久也没有百度到.当时我的项目有minSdkVersion 19. 设置版本最小为L的时候也会 ...