二维地图的寻路算法2
来源:互联网 发布:unitedstack 知乎 编辑:程序博客网 时间:2024/03/29 14:14
二维地图的寻路算法2。
首先需要说明本算法得到的解不一定是最优解,但是比普通的回溯算法速度要快。
代码如下:
- import java.util.Stack;
- /**
- * 找到从地图上一个点到另一个点的路径
- *
- * @author cuilichen
- *
- */
- public class FindPath {
- /**
- * 用来存放操作步骤的栈
- */
- private Stack stack = new Stack();
- /**
- * 地图的宽度
- */
- private int wid = 8;
- /**
- * 找到从地图上一个点到另一个点的路径
- *
- * @param map
- * @param origin
- * @param target
- * @return
- */
- public String find(byte[] map, int origin, int target) {
- if (origin == target) {
- return "";
- }
- int[] step = new int[10];
- step[1] = origin;
- judge(map, step, target);
- stack.push(step);// 根节点
- if (!findPath(map, target)) {// 没有找到路径
- return null;
- }
- optimize(stack);
- StringBuffer sb = new StringBuffer();
- for (int i = 1; i < stack.size(); i++) {
- step = (int[]) stack.elementAt(i);
- sb.append((char) step[0]);
- }
- return sb.toString();
- }
- /**
- * 得到相邻4个点的评价值(距目标点的直线距离的平方),并按照从小到大的顺序排列。
- *
- * @param map
- * @param node
- * @param target
- */
- private void judge(byte[] map, int[] node, int target) {
- int origin = node[1];
- int x0 = origin % wid;
- int y0 = origin / wid;
- int x1 = target % wid;
- int y1 = target / wid;
- int distance = 0;
- distance = (x0 - 1 - x1) * (x0 - 1 - x1) + (y0 - y1) * (y0 - y1);// 左边
- node[2] = 'l';
- node[3] = distance;
- distance = (x0 + 1 - x1) * (x0 + 1 - x1) + (y0 - y1) * (y0 - y1);// 右边
- node[4] = 'r';
- node[5] = distance;
- distance = (x0 - x1) * (x0 - x1) + (y0 - 1 - y1) * (y0 - 1 - y1);// 上
- node[6] = 'u';
- node[7] = distance;
- distance = (x0 - x1) * (x0 - x1) + (y0 + 1 - y1) * (y0 + 1 - y1);// 下
- node[8] = 'd';
- node[9] = distance;
- int direct;
- for (int i = 2; i < node.length; i += 2) {// 冒泡法排序,按照评价值从小到大的顺序
- for (int j = i + 2; j < node.length; j += 2) {
- if (node[j + 1] < node[i + 1]) {
- direct = node[j];
- distance = node[j + 1];
- node[j] = node[i];
- node[j + 1] = node[i + 1];
- node[i] = direct;
- node[i + 1] = distance;
- }
- }
- }
- }
- /**
- * 在地图上找到从原点到目标位置的路径
- *
- * @param map
- * @param origin
- * @param target
- * @return
- */
- private boolean findPath(byte[] map, int target) {
- int[] node = (int[]) stack.peek();
- for (int i = 2; i < node.length; i += 2) {
- if (node[i + 1] >= 0) {
- if (canMoveTo(map, node, i, target)) {
- return true;
- } else {
- node[i + 1] = -1;
- }
- }
- }
- stack.pop();// 如果四个方向都试过,全部不行,那么把当前步骤弹出
- return false;
- }
- /**
- * 是否可以向指定方向移动
- *
- * @param map
- * @param origin
- * @param target
- * @param direct
- * @return
- */
- private boolean canMoveTo(byte[] map, int[] node, int index, int target) {
- int next = 0;
- switch (node[index]) {
- case 'l':
- next = node[1] - 1;
- break;
- case 'r':
- next = node[1] + 1;
- break;
- case 'u':
- next = node[1] - wid;
- break;
- case 'd':
- next = node[1] + wid;
- break;
- }
- if (map[next] == 0) {// 如果目标位置可以进入
- if (next == target) {
- int[] step = new int[10];
- step[0] = node[index];// 移动方向
- step[1] = next;// 到达的新位置
- stack.push(step);
- return true;
- }
- if (!inStack(next)) {
- int[] step = new int[10];
- step[0] = node[index];
- step[1] = next;
- this.judge(map, step, target);
- stack.push(step);
- if (findPath(map, target)) {
- return true;
- }
- }
- }
- return false;
- }
- /**
- * 检查这个位置是否在栈中已经存在了。为了防止在地图中转圈
- *
- * @param posi
- * @return
- */
- private boolean inStack(int posi) {
- int[] temp;
- for (int i = stack.size() - 1; i >= 0; i--) {
- temp = (int[]) stack.elementAt(i);
- if (posi == temp[1]) {
- return true;
- }
- }
- return false;
- }
- /**
- * 进行简单的优化,如果原始路径是“口”字形的三边,那么优化成走一条边
- *
- * @param stack
- */
- private void optimize(Stack stack) {
- for (int i = 0; i < stack.size() - 3; i++) {
- int[] step1 = (int[]) stack.elementAt(i);
- int[] step2 = (int[]) stack.elementAt(i + 1);
- int[] step3 = (int[]) stack.elementAt(i + 2);
- if (step1[0] != step2[0] && step1[0] != step3[0]
- && step2[0] != step3[0]) {
- int[] step = new int[10];
- step[0] = step2[0];
- step[1] = step3[1];
- stack.removeElementAt(i + 2);
- stack.removeElementAt(i + 1);
- stack.removeElementAt(i);
- stack.insertElementAt(step, i);
- }
- }
- }
- /**
- * 测试上述功能是否实现了
- *
- * @param args
- */
- public static void main(String[] args) {
- byte[] map = { 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 0, 0, 1, 1,
- 1, 0, 0, 0, 0, 0, 1, 1,
- 1, 0, 1, 1, 0, 0, 1, 1,
- 1, 0, 0, 0, 1, 0, 1, 1,
- 1, 0, 1, 0, 0, 0, 1, 1,
- 1, 0, 0, 0, 1, 0, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1 };
- FindPath ai = new FindPath();
- for (int i = 0; i < map.length; i++) {
- System.out.print(map[i] + " ");
- if (i % ai.wid == ai.wid - 1) {
- System.out.print("/n");
- }
- }
- System.out.print("/n");
- String s = ai.find(map, 13, 50);
- System.out.println(s);
- }
- }
The result as following:
1 1 1 1 1 1 1 1
1 1 1 1 0 0 1 1
1 0 0 0 0 0 1 1
1 0 1 1 0 0 1 1
1 0 0 0 1 0 1 1
1 0 1 0 0 0 1 1
1 0 0 0 1 0 1 1
1 1 1 1 1 1 1 1
dllllddddr
即,路径是:下,左,左,左,左,下,下,下,下,右。这个路径用了10步。
从地图中,我们可以看出有另一条路径:下,下,下,下,左,左,下,左。可以只用8步就完成。
所以,本算法不是一个最优解算法。
另外,评价值函数的影响很大,本文中简单的使用了距离的平方作为评价值,比较粗糙。
大家可以多想想,提出宝贵意见。
- 二维地图的寻路算法2
- 二维地图寻路算法
- 二维地图的制作
- 树形地图的A*寻路算法
- 绘制二维障碍栅格地图的一种方法2(全局地图的绘制)
- 天地图二维地图数据的接入
- 地图的格子算法
- 二维地图发布
- 二维地图性能排查
- 二维地图引擎
- 二维地图怎样运用到自己的网站上
- supermap二维地图缓存的配置文件sci解析
- tile地图的组合算法
- 关于寻路算法的一些思考(7):地图表示
- 关于寻路算法的一些思考(7):地图表示
- 绘制二维障碍栅格地图的一种方法1(局部地图的绘制)
- Cocos2d-x 地图行走的实现2:SPFA算法
- Cocos2d-x 地图行走的实现2:SPFA算法
- JAVA读取XML文件
- 值得回忆的一天
- XStream别名指南
- ASP实现禁止从外部提交数据
- Liferay源码--配置文件
- 二维地图的寻路算法2
- 利用udev在/dev/下动态生成/移除设备文件
- Moblin MID开发学习笔记 - 在VmWare下搭建开发环境
- java读取XML文件,使用3wc.dom.*包
- “机器狗”病毒驱动部分逆向分析注释(C代码)
- 小偷梦记
- 文件管理新体验,标签浏览器给你Web2.0的感觉
- C#中substring函数
- 用DirctShow抓取TS流中的视频图片