您的位置:首页 > 其它

二维地图的寻路算法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步就完成。

所以,本算法不是一个最优解算法。

另外,评价值函数的影响很大,本文中简单的使用了距离的平方作为评价值,比较粗糙。

大家可以多想想,提出宝贵意见。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: