代码地址如下:
http://www.demodashi.com/demo/14547.html

需求

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

演示效果

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

  1. 简单迷宫

  2. 复杂迷宫

项目运行

文件中有两个运行脚本,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种走法并不是都是合法的,比如有些格子有障碍物,有些格式在边界之外,去掉这些剩下的才是合法的走法。

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

  1. 找出当前位置A下一步合法的的格子,选择其中一个,往前走一步到达B。
  2. 如果B相邻的有合法格子,重复第1步;如果没有合法的,后退一步回到A,选择A的其他合法格子走;
  3. 重复以上方法,直到找到迷宫终点;

算法优化:上面的方法选择下一步走的方向是随机的,或者按照上下左右的顺序选择。但是很多迷宫都有偏向性,比如如果有右偏向性,那么每次都优先往右走可以更快走出迷宫。所以在实现的时候,记录每个方向走的次数,每往一个方向走一步就加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实现可视化迷宫

代码地址如下:
http://www.demodashi.com/demo/14547.html

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

Java实现可视化迷宫的更多相关文章

  1. 超级好用的 Java 数据可视化库:Tablesaw

    本文适合刚学习完 Java 语言基础的人群,跟着本文可了解和使用 Tablesaw 项目.示例均在 Windows 操作系统下演示 本文作者:HelloGitHub-秦人 HelloGitHub 推出 ...

  2. 【JAVA】可视化计算器

    import java.awt.Color; import java.awt.Font; import java.awt.GridLayout; import java.awt.event.Actio ...

  3. java的WindowBuilder可视化插件

    一直做在安卓用xml作界面,对于java的控件不熟悉,也不习惯用代码做UI尤其是布局. 找了一下发现可以安装windowbuilder来实现java的可视化编程,但是很多资料里的连接都失效了. 刚自己 ...

  4. java可视化编程-eclipse安装windowbuilder插件(转载)

    原文地址:http://blog.csdn.net/jason0539/article/details/21219043 一直做在安卓用xml作界面,对于java的控件不熟悉,也不习惯用代码做UI尤其 ...

  5. 基于Java visualvm的可视化监控的使用

    1 Java visualVM可视化监控工具打开方式 ctrl + r 快捷键调出运行窗口,输出 jvisualvm指令,即可打开java visualVM工具.详情如下图: 2 Java Visua ...

  6. 归并排序算法 java 实现

    归并排序算法 java 实现 可视化对比十多种排序算法(C#版) [直观学习排序算法] 视觉直观感受若干常用排序算法 算法概念 归并排序是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Di ...

  7. [2]R语言在数据处理上的禀赋之——可视化技术

    本文目录 Java的可视化技术 R的可视化技术 二维做图利器plot的参数配置 *权限机制 *plot独有的参数 *plot的type介绍 *title介绍 *公共参数集合--par *par的权限机 ...

  8. 7个Java项目,或许你的大学老师就会布置

    前言: 有天吃饭和朋友聊天,说到大学老师布置的开发项目,结果我们一干人说出来的都基本一样,入门级别的计算器啦,稍微大一点的记事本啦,然后到后面的图书管理系统啊,购物网站啊-- 发现这些项目都是大学老师 ...

  9. 并发编程 || Java线程详解

    通用线程模型 在很多研发当中,实际应用是基于一个理论再进行优化的.所以,在了解JVM规范中的Java线程的生命周期之前,我们可以先了解通用的线程生命周期,这有助于我们后续对JVM线程生命周期的理解. ...

随机推荐

  1. 转 Objective-C中不同方式实现锁(一)

    为什么需要使用锁,当然熟悉多线程的你,自然不会对它觉得陌生. 那你在代码中是否很好的使用了锁的机制呢?你又知道几种实现锁的方法呢? 今天一起来探讨一下Objective-C中几种不同方式实现的锁,在这 ...

  2. 【spring cloud】spring cloud集成zipkin报错:Prometheus requires that all meters with the same name have the same set of tag keys.

    spring boot 2.0.X 的版本,整合zipkin2.10.1 zipkin服务启动后,访问zipkin的UI http://localhost:8002/zipkin/ 页面显示空白,cs ...

  3. dlib landmark+人面识别

    #include "stdafx.h" #include <dlib/image_processing/frontal_face_detector.h> #includ ...

  4. inline

    inline 大学在教科书上学习过inline函数,定义为inline函数之后,会省去函数调用的开销,直接嵌套汇编代码,取代函数调用,提高效率.工作后项目中也很少用到inline来定义函数,近几天在研 ...

  5. 【BZOJ】【3611】【HEOI2014】大工程

    虚树+树形DP 本题100W的点数……不用虚树真的好吗…… Orz ZYF 我的感悟: dp的过程跟SPOJ 1825 FTOUR2 的做法类似,依次枚举每个子树,从当前子树和之前的部分中各找一条最长 ...

  6. 第九章 Redis过期策略

    注:本文主要参考自<Redis设计与实现> 1.设置过期时间 expire key time(以秒为单位)--这是最常用的方式 setex(String key, int seconds, ...

  7. 第一章 Java工具类目录

    在这一系列博客中,主要是记录在实际开发中会常用的一些Java工具类,方便后续开发中使用. 以下的目录会随着后边具体工具类的添加而改变. 浮点数精确计算 第二章 Java浮点数精确计算 crc32将任意 ...

  8. hdu 4445 Crazy Tank

    #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> ...

  9. Splunk的安装与使用

    一.简单介绍         Splunk 是机器数据的引擎.使用 Splunk 可收集.索引和利用全部应用程序.server和设备(物理.虚拟和云中)生成的高速移动型计算机数据 .从一个位置搜索并分 ...

  10. RAID5工作原理介绍

    RAID 5是一种存储性能.数据安全和存储成本兼顾的存储解决方案.以四个硬盘组成的RAID 5为例,其数据存储方式如图4所示:图中,P0为D0,D1和D2的奇偶校验信息,P1为D3,D4,D5的奇偶校 ...