A star

A星算法步驟:
1.起點先添加到開啓列表中
2.開啓列表中有節點的話,取出第一個節點,即最小F值的節點
判斷此節點是否是目標點,是則找到了,跳出
根據此節點取得八個方向的節點,求出G,H,F值
判斷每個節點在地圖中是否能通過,不能通過則加入關閉列表中,跳出
判斷每個節點是否在關閉列表中,在則跳出
判斷每個節點是否在開啓列表中,在則更新G值,F值,還更新其父節點;不在則將其添加到開啓列表中,計算G值,H值,F值,添加其節點
3.把此節點從開啓列表中刪除,再添加到關閉列表中
4.把開啓列表中按照F值最小的節點進行排序,最小的F值在第一個
5.重複2,3,4步驟
直到目標點在開啓列表中,即找到了;目標點不在開啓列表中,開啓列表爲空,即沒找到

//A*算法
public class AStar {
    private int[][] map;//地圖(1可通過 0不可通過)
    private List<Node> openList;//開啓列表
    private List<Node> closeList;//關閉列表
    private final int COST_STRAIGHT = 10;//垂直方向或水平方向移動的路徑評分
    private final int COST_DIAGONAL = 14;//斜方向移動的路徑評分
    private int row;//行
    private int column;//列

    public AStar(int[][] map,int row,int column){
        this.map=map;
        this.row=row;
        this.column=column;
        openList=new ArrayList<Node>();
        closeList=new ArrayList<Node>();
    }

    //查找座標(-1:錯誤,0:沒找到,1:找到了)
    public int search(int x1,int y1,int x2,int y2){
        if(x1<0||x1>=row||x2<0||x2>=row||y1<0||y1>=column||y2<0||y2>=column){
            return -1;
        }
        if(map[x1][y1]==0||map[x2][y2]==0){
            return -1;
        }
        Node sNode=new Node(x1,y1,null);
        Node eNode=new Node(x2,y2,null);
        openList.add(sNode);
        List<Node> resultList=search(sNode, eNode);
        if(resultList.size()==0){
            return 0;
        }
        for(Node node:resultList){
            map[node.getX()][node.getY()]=-1;
        }
        return 1;
    }

    //查找核心算法
    private List<Node> search(Node sNode,Node eNode){
        List<Node> resultList=new ArrayList<Node>();
        boolean isFind=false;
        Node node=null;
        while(openList.size()>0){
            //取出開啓列表中最低F值,即第一個存儲的值的F爲最低的
            node=openList.get(0);
            //判斷是否找到目標點
            if(node.getX()==eNode.getX()&&node.getY()==eNode.getY()){
                isFind=true;
                break;
            }
            //上
            if((node.getY()-1)>=0){
                checkPath(node.getX(),node.getY()-1,node, eNode, COST_STRAIGHT);
            }
            //下
            if((node.getY()+1)<column){
                checkPath(node.getX(),node.getY()+1,node, eNode, COST_STRAIGHT);
            }
            //左
            if((node.getX()-1)>=0){
                checkPath(node.getX()-1,node.getY(),node, eNode, COST_STRAIGHT);
            }
            //右
            if((node.getX()+1)<row){
                checkPath(node.getX()+1,node.getY(),node, eNode, COST_STRAIGHT);
            }
            //左上
            if((node.getX()-1)>=0&&(node.getY()-1)>=0){
                checkPath(node.getX()-1,node.getY()-1,node, eNode, COST_DIAGONAL);
            }
            //左下
            if((node.getX()-1)>=0&&(node.getY()+1)<column){
                checkPath(node.getX()-1,node.getY()+1,node, eNode, COST_DIAGONAL);
            }
            //右上
            if((node.getX()+1)<row&&(node.getY()-1)>=0){
                checkPath(node.getX()+1,node.getY()-1,node, eNode, COST_DIAGONAL);
            }
            //右下
            if((node.getX()+1)<row&&(node.getY()+1)<column){
                checkPath(node.getX()+1,node.getY()+1,node, eNode, COST_DIAGONAL);
            }
            //從開啓列表中刪除
            //添加到關閉列表中
            closeList.add(openList.remove(0));
            //開啓列表中排序,把F值最低的放到最底端
            Collections.sort(openList, new NodeFComparator());
        }
        if(isFind){
            getPath(resultList, node);
        }
        return resultList;
    }

    //查詢此路是否能走通
    private boolean checkPath(int x,int y,Node parentNode,Node eNode,int cost){
        Node node=new Node(x, y, parentNode);
        //查找地圖中是否能通過
        if(map[x][y]==0){
            closeList.add(node);
            return false;
        }
        //查找關閉列表中是否存在
        if(isListContains(closeList, x, y)!=-1){
            return false;
        }
        //查找開啓列表中是否存在
        int index=-1;
        if((index=isListContains(openList, x, y))!=-1){
            //G值是否更小,即是否更新G,F值
            if((parentNode.getG()+cost)<openList.get(index).getG()){
                node.setParentNode(parentNode);
                countG(node, eNode, cost);
                countF(node);
                openList.set(index, node);
            }
        }else{
            //添加到開啓列表中
            node.setParentNode(parentNode);
            count(node, eNode, cost);
            openList.add(node);
        }
        return true;
    }

    //集合中是否包含某個元素(-1:沒有找到,否則返回所在的索引)
    private int isListContains(List<Node> list,int x,int y){
        for(int i=0;i<list.size();i++){
            Node node=list.get(i);
            if(node.getX()==x&&node.getY()==y){
                return i;
            }
        }
        return -1;
    }

    //從終點往返回到起點
    private void getPath(List<Node> resultList,Node node){
        if(node.getParentNode()!=null){
            getPath(resultList, node.getParentNode());
        }
        resultList.add(node);
    }

    //計算G,H,F值
    private void count(Node node,Node eNode,int cost){
        countG(node, eNode, cost);
        countH(node, eNode);
        countF(eNode);
    }
    //計算G值
    private void countG(Node node,Node eNode,int cost){
        if(node.getParentNode()==null){
            node.setG(cost);
        }else{
            node.setG(node.getParentNode().getG()+cost);
        }
    }
    //計算H值
    private void countH(Node node,Node eNode){
        node.setF(Math.abs(node.getX()-eNode.getX())+Math.abs(node.getY()-eNode.getY()));
    }
    //計算F值
    private void countF(Node node){
        node.setF(node.getG()+node.getF());
    }

}
//節點類
class Node {
    private int x;//X座標
    private int y;//Y座標
    private Node parentNode;//父類節點
    private int g;//當前點到起點的移動耗費
    private int h;//當前點到終點的移動耗費,即曼哈頓距離|x1-x2|+|y1-y2|(忽略障礙物)
    private int f;//f=g+h

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

    public int getX() {
        return x;
    }
    public void setX(int x) {
        this.x = x;
    }
    public int getY() {
        return y;
    }
    public void setY(int y) {
        this.y = y;
    }
    public Node getParentNode() {
        return parentNode;
    }
    public void setParentNode(Node parentNode) {
        this.parentNode = parentNode;
    }
    public int getG() {
        return g;
    }
    public void setG(int g) {
        this.g = g;
    }
    public int getH() {
        return h;
    }
    public void setH(int h) {
        this.h = h;
    }
    public int getF() {
        return f;
    }
    public void setF(int f) {
        this.f = f;
    }
   }
//節點比較類
class NodeFComparator implements Comparator<Node>{
    @Override
    public int compare(Node o1, Node o2) {
        return o1.getF()-o2.getF();
    }

}
http://www.educity.cn/wenda/145130.html
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章