二维地图的寻路算法2
2008-08-26 11:47
309 查看
二维地图的寻路算法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步就完成。
所以,本算法不是一个最优解算法。
另外,评价值函数的影响很大,本文中简单的使用了距离的平方作为评价值,比较粗糙。
大家可以多想想,提出宝贵意见。
首先需要说明本算法得到的解不一定是最优解,但是比普通的回溯算法速度要快。
代码如下:
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步就完成。
所以,本算法不是一个最优解算法。
另外,评价值函数的影响很大,本文中简单的使用了距离的平方作为评价值,比较粗糙。
大家可以多想想,提出宝贵意见。
相关文章推荐
- 二维地图寻路算法
- [寻路][导航][算法][地图开发]寻路算法的对比优势1
- A*地图寻路算法实现
- [寻路][导航][算法][地图开发]寻路算法的对比优势2
- 基于六边形地图的A*寻路算法实现
- 游戏地图寻路算法 -- A*(分析 + 实现 + 教学视频连接)
- cocos2d-x学习日志(14) --A星寻路算法之45度地图
- Html5斜45度地图+3D模型ARPG系列教程(6)-- 寻路算法及平滑处理
- 地图服务之图片切割算法
- 关于寻路算法的一些思考(11):寻路算法的其他应用
- 二维矢量图形算法加速标准 OpenVG
- A*(也叫A star, A星)寻路算法-Java版
- 华为codecraft算法大赛---寻路
- 两个二维矩阵相乘的算法
- A*寻路算法入门(六)
- 如何在Cocos2D游戏中实现A*寻路算法(三)
- 如何在Cocos2D游戏中实现A*寻路算法(六)
- J2ME平台A-RPG游戏怪物寻路算法初探
- 如何在Cocos2D游戏中实现A*寻路算法(八)
- unity自带的导航构建一个简单的地图寻路