Java开源-astar:A 星算法(转)

原文地址:
https://buluo.qq.com/p/detail.html?bid=11148&pid=7659220-1500366685&from=share_copylink

先记录下,以后再慢慢研究=o=
AStar.java

/**
 *
 */
package A星算法;

import java.util.ArrayList;
import java.util.List;
import java.util.PriorityQueue;
import java.util.Queue;

/**
 * <p>Title:AStar </p>
 * <p>Description: </p>
 * <p>Company: </p>
 * @author st5983
 * @date 2017年7月19日
 */
public class AStar {
    public final static int BAR = 1; // 障碍值
    public final static int PATH = 2; // 路径
    public final static int DIRECT_VALUE = 10; // 横竖移动代价
    public final static int OBLIQUE_VALUE = 14; // 斜移动代价

    // OPEN表
    Queue<Node> openList = new PriorityQueue<Node>(); // 优先队列(升序)
    // CLOSE表
    List<Node> closeList = new ArrayList<Node>();


    static int[][] maps = {
            { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
            { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
            { 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0 },
            { 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0 },
            { 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0 },
            { 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0 },
            { 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0 }
            };



    /**
    * 判断结点是否是最终结点
    */
   private boolean isEndNode(Coord end,Coord coord)
   {        return coord != null && end.equals(coord);
   }   
   /**
    * 判断结点能否放入Open列表
    */
   private boolean canAddNodeToOpen(MapInfo mapInfo,int x, int y)
   {        // 是否在地图中
       if (x < 0 || x >= mapInfo.width || y < 0 || y >= mapInfo.hight) return false;        // 判断是否是不可通过的结点
       if (mapInfo.maps[y][x] == BAR) return false;        // 判断结点是否存在close表
       if (isCoordInClose(x, y)) return false;
       return true;
   }    /**
    * 判断坐标是否在close表中
    */
   private boolean isCoordInClose(Coord coord)
   {        
       return coord!=null&&isCoordInClose(coord.x, coord.y);
   }    
   /**
    * 判断坐标是否在close表中
    */
   private boolean isCoordInClose(int x, int y)
   {        
       if (closeList.isEmpty()) return false;
       for (Node node : closeList)
       {            
           if (node.coord.x == x && node.coord.y == y)
           {                
               return true;
           }
       }        
       return false;
   }
   // 计算H值,“曼哈顿” 法,坐标分别取差值相加
   private int calcH(Coord end,Coord coord){
       return Math.abs(end.x - coord.x) + Math.abs(end.y - coord.y);
   }
   // 从Open列表中查找结点
   private Node findNodeInOpen(Coord coord){    
       if (coord == null || openList.isEmpty()) return null;
       for (Node node : openList){        
           if (node.coord.equals(coord)){
               return node;
           }
       }    
       return null;
   }

   /**
    * 6 添加所有邻结点到open表
    */
   private void addNeighborNodeInOpen(MapInfo mapInfo,Node current){
       int x = current.coord.x;
       int y = current.coord.y;// 左
       addNeighborNodeInOpen(mapInfo,current, x - 1, y, DIRECT_VALUE);    // 上
       addNeighborNodeInOpen(mapInfo,current, x, y - 1, DIRECT_VALUE);    // 右
       addNeighborNodeInOpen(mapInfo,current, x + 1, y, DIRECT_VALUE);    // 下
       addNeighborNodeInOpen(mapInfo,current, x, y + 1, DIRECT_VALUE);    // 左上
       addNeighborNodeInOpen(mapInfo,current, x - 1, y - 1, OBLIQUE_VALUE);    // 右上
       addNeighborNodeInOpen(mapInfo,current, x + 1, y - 1, OBLIQUE_VALUE);    // 右下
       addNeighborNodeInOpen(mapInfo,current, x + 1, y + 1, OBLIQUE_VALUE);    // 左下
       addNeighborNodeInOpen(mapInfo,current, x - 1, y + 1, OBLIQUE_VALUE);
   }
   /**
    * 添加一个邻结点到open表
    */
   private void addNeighborNodeInOpen(MapInfo mapInfo,Node current, int x, int y, int value){
       if (canAddNodeToOpen(mapInfo,x, y)){
           Node end=mapInfo.end;
           Coord coord = new Coord(x, y);
           int G = current.G + value; // 计算邻结点的G值
           Node child = findNodeInOpen(coord);
           if (child == null){
               int H=calcH(end.coord,coord); // 计算H值
               if(isEndNode(end.coord,coord)){
                   child=end;
                   child.parent=current;
                   child.G=G;
                   child.H=H;
               }
               else{
                   child = new Node(coord, current, G, H);
               }
               openList.add(child);
           }        
           else if (child.G > G){
               child.G = G;
               child.parent = current;            // 重新调整堆
               openList.add(child);
           }
       }
   }
   /**
    * (7) 回溯法绘制路径
    */
   private void drawPath(int[][] maps, Node end){
       if(end==null||maps==null) return;
       System.out.println("总代价:" + end.G);
       while (end != null){
           Coord c = end.coord;
           maps[c.y][c.x] = PATH;
           end = end.parent;
       }
   }
   /**
    * (8) 开始算法,循环移动结点寻找路径,设定循环结束条件,Open表为空或者最终结点在Close表
    */
   public void start(MapInfo mapInfo){
       if(mapInfo==null) return;    // clean
       openList.clear();
       closeList.clear();    // 开始搜索
       System.out.println("开始搜索");
       openList.add(mapInfo.start);
       moveNodes(mapInfo);
    }
   /**
    * 移动当前结点
    */
   private void moveNodes(MapInfo mapInfo){
       while (!openList.isEmpty()){
           if (isCoordInClose(mapInfo.end.coord)){
               drawPath(mapInfo.maps, mapInfo.end); 
               break;
           }
           Node current = openList.poll();
           closeList.add(current);
           addNeighborNodeInOpen(mapInfo,current);
       }    
   }
   public static void main(String[] args) {
       Node start = new Node(1, 2);
       Node end = new Node(5, 5);
       int width = 15;
       int hight = 7;
       MapInfo mapInfo = new MapInfo(maps, width, hight, start, end);
       AStar astar = new AStar();
       astar.start(mapInfo);

   }
}

Coord.java

/**
 *
 */
package A星算法;

/**
 * <p>Title:Coord </p>
 * <p>Description: </p>
 * <p>Company: </p>
 * @author st5983
 * @date 2017年7月19日
 */
public class Coord {
    public int x;
    public int y;

    public Coord(int x, int y) {
        this.x = x;
        this.y = y;
    }

    /**
     * 重写方法
     */
    @Override
    public boolean equals(Object obj) { 
        if (obj == null) {
            return false;
        }

        if (obj instanceof Coord) {
            Coord c = (Coord) obj;

            return (x == c.x) && (y == c.y);
        }

        return false;
    }
}

MapInfo.java

/**
 *
 */
package A星算法;

/**
 * <p>Title:MapInfo </p>
 * <p>Description: </p>
 * <p>Company: </p>
 * @author st5983
 * @date 2017年7月19日
 */
public class MapInfo {
    public int[][] maps; // 二维数组的地图
    public int width; // 地图的宽
    public int hight; // 地图的高
    public Node start; // 起始结点
    public Node end; // 最终结点

    public MapInfo(int[][] maps, int width, int hight, Node start, Node end) {
        this.maps = maps;
        this.width = width;
        this.hight = hight;
        this.start = start;
        this.end = end;
    }
}

Node.java

/**
 *
 */
package A星算法;

/**
 * <p>Title:Node </p>
 * <p>Description: </p>
 * <p>Company: </p>
 * @author st5983
 * @date 2017年7月19日
 */
public class Node implements Comparable<Node> {
    public Coord coord; // 坐标
    public Node parent; // 父结点
    public int G; // 是个准确的值,是起点到当前结点的代价
    public int H; // 是个估值,当前结点到目的结点的估计代价

    public Node(int x, int y) {
        this.coord = new Coord(x, y);
    }

    public Node(Coord coord, Node parent, int g, int h) {
        this.coord = coord;
        this.parent = parent;
        G = g;
        H = h;
    }

    @Override
    public int compareTo(Node o) {
        if (o == null) {
            return -1;
        }

        if ((G + H) > (o.G + o.H)) {
            return 1;
        } else if ((G + H) < (o.G + o.H)) {
            return -1;
        }

        return 0;
    }
}

研究完后再回来写心得====

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值