日期:2014-05-20  浏览次数:20633 次

A*寻路(J2ME实现)

这是很久前另一个BLOG上的,现在不用了。转过来吧,方便查看...

?

找工作未果,?闲来无事,先学学一些感兴趣的算法和弄些小东西~~

?

参考文章:

http://blog.vckbase.com/panic/archive/2005/03/20/3778.html

写得真的非常棒,翻译得也很好,整个实现就是跟着他来的。

?

直接上代码,效率问题没有仔细研究过,我是每次寻路完毕都进行一次资源释放,进一步的优化可以继续参考以上连接作者BLOG的其他关于A*的文章。

?

/***
?* A*寻路
?* @author univasity
?* 2008-10-01 0:19
?* QQ:595920004
?*/
public class PF_A_Start {
?
?/**构造函数*/
?public PF_A_Start(byte[][] map, byte[] blocks) {
??this.map = map;
??this.blocks = blocks;
?}

?/**
? * 根据指定的起始位置和目标寻路
? * @param sx 起始点X坐标
? * @param sy 起始点Y坐标
? * @param tx 目标点X坐标
? * @param ty 目标点Y坐标
? * @return 可行的路径,如果没有则返回空
? */
?public int[][] findPath(int sx, int sy, int tx, int ty){
??
??init();
??
??setFatherNode(sx, sy, sx, sy); // 起始点的父节点设置为自身
??value_G[sy][sx] = 0;
??value_H[sy][sx] = CalculationValueH(sx, sy, tx, ty);
??addToOpenList(sx, sy); // 把起始点加入开放列表
??
??while(num_open>0 && !(sucess = isInCloseList(tx, ty))){
???
???// 获取具有最小F值的节点,作为下一个移动目标
???int node1 = openList[0];
???int nx = node1%10;
???int ny = node1/10;
???for(int i=1; i<num_open-1; i++){
????int node2 = openList[i+1];
????int x2 = node2%10;
????int y2 = node2/10;
????if(ValueF(x2, y2)<ValueF(nx, ny)){
?????nx = x2;
?????ny = y2;
????}
???}
???
???// 把四周可到的节点加入开放列表,以待检测
???for(int i=0; i<8; i++){
????if(isBlock(nx+px[i], ny+py[i])) // 如果是障碍,跳过
?????continue;
????if(isInCloseList(nx+px[i], ny+py[i])) // 如果已存在关闭列表中,跳过
?????continue;
????if(isInOpenList(nx+px[i], ny+py[i])){ // 如果已存在开放列表中
?????int fatherNode = FatherNode(nx+px[i], ny+py[i]);
?????// 判断以当前节点为父节点,G值是否比原来小
?????setFatherNode(nx+px[i], ny+py[i], nx, ny);
?????if(CalculationValueG(nx+px[i], ny+py[i])<value_G[ny+py[i]][nx+px[i]]){ // 如果只是
??????value_G[ny+py[i]][nx+px[i]] = CalculationValueG(nx+px[i], ny+py[i]); // 更新G值,令父节点为当前节点
?????}else{ // 否则
??????setFatherNode(nx+px[i], ny+py[i], fatherNode%10, fatherNode/10); // 恢复父节点为初始值
?????}
????}else{ // 未被添加到开放列表
?????// 设置父节点为当前节点,计算G值和H值,并添加到开放列表中
?????setFatherNode(nx+px[i], ny+py[i], nx, ny);
?????value_G[ny+py[i]][nx+px[i]] = CalculationValueG(nx+px[i], ny+py[i]);
?????value_H[ny+py[i]][nx+px[i]] = CalculationValueH(nx+px[i], ny+py[i], tx, ty);
?????addToOpenList(nx+px[i], ny+py[i]);
????}
???}
???// 从开放列表删除该节点
???deleteFromOpenList(nx, ny);
???// 添加到关闭列表
???addToCloseList(nx, ny);
??} // 搜索结束
??
??// 读取路径
??int[][] path = null;
??if(sucess){
???int[][] temp = new int[num_open][2];
???int index = num_open-1;
???int nx = tx;
???int ny = ty;
???while(nx!=sx || ny!=sy){
????int node = FatherNode(nx, ny);
????nx = node%10;
????ny = node/10;
????temp[index][0] = nx;
????temp[index][1] = ny;
????index--;
???}
???path = new int[num_open-index-1][2];
???System.arraycopy(temp, index+1, path, 0, path.length);
??}
??
??release();
??
??return path;
?}
?
?/**资源初始化*/
?private void init() {
??num_open = num_close = 0;
??openList = new int[map.length*map[0].length]; // 开放列表
??closeList = new int[map.length*map[0].length]; // 关闭列表
??fatherNode = new int[map.length][map[0].length]; // 父节点列表
??value_G = new int[map.length][map[0].length]; // G值表
??value_H = new int[map.length][map[0].length]; // H值表
?}
?
?/**释放资源*/
?private void release() {
??openList = null;
??closeList = null;
??for(int i=0; i<fatherNode.length; i++){
???fatherNode[i] = null;
??}
??fatherNode = null;
??for(int i=0; i<value_G.length; i++){
???value_G[i] = null;
??}
??value_G = null;
??for(int i=0; i<value_H.length; i++){
???value_H[i] = null;
??}
??value_H = null;
??System.gc();
?}

?/**添加到开放列表*/
?private int addToOpenList(int x, int y){
??return (openList[num_open++] = y*10+x);
?}
?
?/**添加到关闭列表*/
?private int addToCloseList(int x, int y){
??return (closeList[num_close++] = y*10+x);
?}
?
?/**从开放列表中删除*/
?private void deleteFromOpenList(int x, int y){
??if(num_open<=0)
???return;
??int i;
??for(i=0; i<num_open; i++){
???if(openList[i]==y*10+x){
????openList[i] = 0;
????break;
???}
??}
??for(; i<num_open-1; i++){
???openList[i] = openList[i+1];
??}
??num_open--;
?}
?
?/**获取F值*/
?private int ValueF(int x, int y){
??return value_G[y][x]+value_H[y][x];
?}
?
?/**获取父节点*/
?private int FatherNode(int x, int y){
??return fatherNode[y][x];
?}
?
?private void setFatherNode(int x, int y, int fx, int fy){
??fatherNode[y][x] = fy*10+fx;
?}
?
?/**是否已存在于开放列表*/
?private boolean isInOpenList(int x, int y){
??for(int i=0; i<num_open; i++){
???if(openList[i]==y*10+x)
????return true;
??}
??return false;
?}
?
?/**是否已存在于关闭列表*/
?private boolean isInCloseList(int x, int y){
??for(int i=0; i<num_close; i++){
???if(closeList[i]==y*10+x)
????return true;
??}
??return false;
?}
?
?/**计算G值*/
?private int CalculationValueG(int x, int y){
??int node = FatherNode(x, y);
??int fx = node%10;
??int fy = node/10;
??for(int i=0; i<4; i++){
???if(fx+px[4+i]==x && fy+py[4+i]==y)
????return value_G[fy][fx] + 14;
??}
??return value_G[fy][fx] + 10;
?}
?
?/**计算H值*/
?private int CalculationValueH(int x, int y, int tx, int ty){
??return (Math.abs(y-ty)+Math.abs(x-tx))*10;
?}
?
?/**判断是否是障碍*/
?private boolean isBlock(int x, int y){
??if(x<0 || x>=map[0].length || y<0 || y>=map.length)
???return true;
??if(blocks==null)
???return false;
??for(int i=0; i<blocks.length; i++){
???if(map[y][x]==blocks[i])
????return true;
??}
??return false;
?}
?
?// 四周8个方位的位置偏移量
?private static final byte[] px = {-1,1,0,0,-1,-1,1,1};
?private static final byte[] py = {0,0,-1,1,-1,1,-1,1};
?
?private byte[][] map; // 地图数据
?private byte[] blocks; // 障碍ID
?
?private int[] openList;// 开放列表
?private int[] closeList; // 关闭列表
?private int num_open, num_close; // 数量标记
?
?private int[][] fatherNode; // 父节点列表
?private int[][] value_G; // G值表
?private int[][] value_H; // H值表
?
?private boolean sucess;
}