A*算法的一种Java实现

A*寻路算法实现

       A*(A-Star)算法是一种静态路网中求解最短路最有效的方法。估价值与实际值越接近,估价函数取得就越好,就算法本身的描述不再赘述,本例中估价值采用曼哈顿取值法,只是为了验证使用,在实际使用中建议采用其他取值法实现。

       Map类和MapPoint类用于保存地图和每个地图坐标的信息:

import java.util.Vector;

/**
 *
 * @author xreztento@vip.sina.com
 */
public class Map {
    private int width = 0;
    private int length = 0;
    private Vector<MapPoint> mapPoints = null;

    public int getLength() {
        return length;
    }

    public Vector<MapPoint> getMapPoints() {
        return mapPoints;
    }

    public MapPoint getMapPoint(int x,int y)
    {
        int id = y * getWidth() + x;
        return mapPoints.get(id);
    }
    
    public int getWidth() {
        return width;
    }

    public void setLength(int length) {
        this.length = length;
    }

    public void setWidth(int width) {
        this.width = width;
    }

    public void setMapPoints(Vector<MapPoint> mapPoints) {
        this.mapPoints = mapPoints;
    }
}
/**
*
* @author xreztento@vip.sina.com
*/
public class MapPoint {

	private int x = 0;
    private int y = 0;
    private int id = 0;
    private float g_value = 0f;
    private float h_value = 0f;
    private float f_value = 0f;
    private boolean isPass = true;
    private boolean isRoad = false;
    private MapPoint rootPoint = null;
    
    public float getG_value() {
        return g_value;
    }

    public int getX() {
        return x;
    }

    public int getY() {
        return y;
    }

    public boolean isIsPass() {
        return isPass;
    }

    public void setG_value(float g_value) {
        this.g_value = g_value;
    }

    public void setIsPass(boolean isPass) {
        this.isPass = isPass;
    }

    public void setX(int x) {
        this.x = x;
    }

    public void setY(int y) {
        this.y = y;
    }

    public float getF_value() {
        return f_value;
    }

    public float getH_value() {
        return h_value;
    }

    public void setF_value(float f_value) {
        this.f_value = f_value;
    }

    public void setH_value(float h_value) {
        this.h_value = h_value;
    }
    
    
     public void setIsRoad(boolean isRoad) {
        this.isRoad = isRoad;
    }

    public boolean isIsRoad() {
        return isRoad;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public MapPoint getRootPoint() {
        return rootPoint;
    }

    public void setRootPoint(MapPoint rootPoint) {
        this.rootPoint = rootPoint;
    }
    
    
}
       AStarMethod类用于实现算法:

import java.util.Vector;

/**
 *
 * @author xreztento@vip.sina.com
 */
public class AStarMethod {
    Vector<Integer> openList = new  Vector<Integer>();
    Vector<Integer> closeList = new  Vector<Integer>();
    private MapPoint sPoint = null;
    private MapPoint dPoint = null;
    private Map map = null;
    
    public AStarMethod(MapPoint sPoint,MapPoint dPoint,Map map)
    {
        this.sPoint = sPoint;
        this.dPoint = dPoint;
        this.map = map;
    }
    
    public Vector<Integer> getRoadPoints()
    {
        closeList.add(sPoint.getId());
        while(!closeList.contains(dPoint.getId()))
        {
            searchNewRootPoint(map.getMapPoints().get(closeList.get(closeList.size() - 1)));
        }
       
        return closeList;

    }
    
    public void searchNewRootPoint(MapPoint rPoint)
    {
       int r_x = rPoint.getX();
       int r_y = rPoint.getY();
       
       //遍历周边节点,计算f_value
       for(int i = -1;i < 2;i++)
       {
           if(r_x + i < 0 || r_x + i >= map.getLength())//判断是否超出X轴边界
           {
               continue;
           }
           for(int j = -1;j < 2;j++)
           {
               if( r_y + j < 0 || r_y + j >= map.getWidth())//判断是否超出Y轴边界
               {
                   continue;
               }
               float f_value = 0f;
               float g_value = 0f;
               float h_value = 0f;
               
               
               int id = map.getMapPoint(r_x + i, r_y + j).getId();//周边节点ID
               if(map.getMapPoints().get(id).isIsPass() && !closeList.contains(id) && !openList.contains(id))//节点可通过、不在open和close列表
               {
                   map.getMapPoints().get(id).setRootPoint(rPoint);//
                   
                   h_value = getHvalue(map.getMapPoints().get(id));
                   if(h_value == 0)//如果h_value等于0,目前节点已经找到
                   {
                       dPoint.setRootPoint(rPoint);
                       closeList.add(dPoint.getId());//将节点加入close列表
                       return;
                   }
                   if(map.getMapPoints().get(id).getX() != r_x && map.getMapPoints().get(id).getY() != r_y)//判断节点为斜侧方向节点
                   {
                       g_value = rPoint.getG_value() + 14f;
                   }
                   else
                   {
                       g_value = rPoint.getG_value() + 10f;
                   }
                   f_value = g_value + h_value;
                  
                   map.getMapPoints().get(id).setF_value(f_value);
                   map.getMapPoints().get(id).setG_value(g_value);
                   map.getMapPoints().get(id).setH_value(h_value);
                   openList.add(id);//计算f_value值后,将节点加入open列表
               }
            }
       }
       
       for(int k = 0;k < openList.size() - 1;k++)//将open列表中具有最小f_value值的节点冒泡到列表最底部
       {
            float f_value_1 = map.getMapPoints().get(openList.get(k)).getF_value();
            float f_value_2 = map.getMapPoints().get(openList.get(k + 1)).getF_value();
            
            if(f_value_1 < f_value_2)
            {
                int tmp = openList.get(k);
                
                openList.set(k,openList.get(k + 1));
                openList.set(k + 1,tmp);
                
            }
       }
       
      if(openList.size() > 0)//如果open列表不为空
      {
           int id = openList.get(openList.size() - 1);
       
           openList.remove(openList.size() - 1);
           closeList.add(id);//将具有最小f_value值得节点加入close列表
      }
      else//如果open列表为空,未找到路径
      {
          closeList.add(dPoint.getId());
          return;
      }
      
    }
       
    public float getHvalue(MapPoint point)
    {
        //曼哈顿取值法
        return (Math.abs(point.getX() - dPoint.getX()) + Math.abs(point.getY() - dPoint.getY()))*10;
                
        //实际应用时使用其他取值法
    }
  
}
       MakeMap类用于初始化一张图:

import java.util.Vector;

/**
*制造一张图
* @author xreztento@vip.sina.com
*/
public class MakeMap {
    
    public void initialMap(Map map,int mapWidth,int mapLength)
    {
        map.setWidth(mapWidth);
        map.setLength(mapLength);
        java.util.Vector<MapPoint> mapPoints = new Vector<MapPoint>(mapWidth * mapLength);
       
        for(int i = 0;i < mapWidth;i++)
        {
            for(int j = 0;j < mapLength;j++)
            {
                MapPoint mp = new MapPoint();
                mp.setX(j);
                mp.setY(i);
                mp.setId(i * mapWidth + j);
                mapPoints.add(mp);
            }
        }
        
        map.setMapPoints(mapPoints);
        
    }
    
}
       AStar类用于使用算法和测试:

/**
 *
 * @author xreztento@vip.sina.com
 */
public class AStar {

    public static void main(String[] args) {

        MakeMap mm = new MakeMap();
        Map map = new Map();
        //Map map,int mapWidth,int mapLength
        mm.initialMap(map, 20,20);
       
        map.getMapPoint(3, 1).setIsPass(false);
        map.getMapPoint(3, 2).setIsPass(false);
        map.getMapPoint(3, 3).setIsPass(false);
        map.getMapPoint(3, 4).setIsPass(false);
       
        map.getMapPoint(0, 6).setIsPass(false);
        map.getMapPoint(1, 6).setIsPass(false);
        map.getMapPoint(2, 6).setIsPass(false);
        map.getMapPoint(3, 6).setIsPass(false);
        map.getMapPoint(4, 6).setIsPass(false);
        map.getMapPoint(5, 6).setIsPass(false);
        map.getMapPoint(6, 6).setIsPass(false);
         
        map.getMapPoint(3, 7).setIsPass(false);
        map.getMapPoint(4, 7).setIsPass(false);
        map.getMapPoint(5, 7).setIsPass(false);
        map.getMapPoint(6, 7).setIsPass(false);
        map.getMapPoint(7, 7).setIsPass(false);
        map.getMapPoint(8, 7).setIsPass(false);
        map.getMapPoint(9, 7).setIsPass(false);
        map.getMapPoint(10, 7).setIsPass(false);
        map.getMapPoint(11, 7).setIsPass(false);
        map.getMapPoint(12, 7).setIsPass(false);
        
        map.getMapPoint(9, 8).setIsPass(false);
        map.getMapPoint(9, 9).setIsPass(false);
        map.getMapPoint(9, 10).setIsPass(false);
        map.getMapPoint(9, 11).setIsPass(false);
        
        long beginTime = System.currentTimeMillis();
        AStarMethod asm = new AStarMethod(map.getMapPoint(0, 1),map.getMapPoint(8, 9),map);
        asm.getRoadPoints();
        searchRoad(map.getMapPoint(0, 1),map.getMapPoint(8, 9));
        long endTime = System.currentTimeMillis();
        System.out.println("A-star compute time is " + (endTime - beginTime) + "ms");
        for(int i = 0;i < map.getLength() * map.getWidth();i++)
        {
            MapPoint mp = map.getMapPoints().get(i);
            
            if((mp.getX() + 1) % (map.getLength()) == 0)
            {
                if(mp.isIsPass())
                {
                    if(mp.isIsRoad())
                    {
                        System.out.print("#\n");
                    }
                    else
                    {
                        System.out.print("*\n");
                    }
                }
                else
                {
                    System.out.print("+\n");
                }
            }
            else
            {
                  if(mp.isIsPass())
                {
                   if(mp.isIsRoad())
                    {
                        System.out.print("#");
                    }
                    else
                    {
                        System.out.print("*");
                    }
                }
                else
                {
                    System.out.print("+");
                }
            }
        }
       
    }
    
    
    public static void searchRoad(MapPoint s,MapPoint e)//从终点迭代每个节点所指向的父节点,直到起点
    {
        if(e.getRootPoint() == s)//如果到达起点,终止迭代
        {
            e.setIsRoad(true);
            return;
        }
        else
        {
            e.setIsRoad(true);
            searchRoad(s,e.getRootPoint());//迭代
        }
    }
}

       测试结果如下图所示:


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值