java实现的A星算法

A星算法原理:

原理我就不再赘述,可以参考这篇博客:https://blog.csdn.net/hitwhylz/article/details/23089415

需要js代码的看这里:https://blog.csdn.net/qq_39687901/article/details/85697127

需要python代码的看这里:https://blog.csdn.net/qq_39687901/article/details/80753433

用法:

这里是八方寻路,如果想改成四方寻路,把AStar中对应的四行搜索代码注释掉就好了。

public class test {
    public static void main(String[] arg) {
        //创建一个寻路的二维数组,0是可行走区域,非0是障碍
        int[][] map2d = new int[10][10];
        //设置一些障碍
        map2d[4][0]= 1;
        map2d[4][1] = 1;
        map2d[4][2] = 1;
        map2d[4][3] = 1;
        map2d[4][4] = 1;
        map2d[4][5] = 1;
        map2d[4][6] = 1;
        //创建A星对象
        AStar astar = new AStar(map2d,new Point(0,0),new Point(9,0));
        //开始寻路
        ArrayList<Point> pointList = astar.start();
        //打印寻路结果
        for(Point point:pointList){
            System.out.println(point.x+","+ point.y);
        }
    }
}

运行结果:

1,1
2,2
3,3
3,4
3,5
3,6
4,7
5,7
5,6
6,6
7,6
8,6
8,5
9,5
9,4
9,3
9,2
9,1
9,0

源码:

一共3个java文件:AStar.java、Node.java、Point.java

Point.java:


//表示一个二维点
public class Point {
    public int x;
    public int y;

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

    //判断两个点是不是相同
    public boolean eq(Point p) {
        return this.x == p.x && this.y == p.y;
    }
}

Node.java:

public class Node implements Comparable<Node>{
    public Point point;     //节点自己的坐标
    public Node father;     //父节点
    //f=g+h
    int g;
    int h;

    public Node(Point point, Point endPoint, int g) {
        this.point = point;
        this.g = g;
        this.h = (Math.abs(endPoint.x - point.x) + Math.abs(endPoint.y - point.y)) * 10;
    }

    @Override
    public int compareTo(Node o) {
        if(o==null) return -1;
        if(this.g+this.h>o.g+o.h){
            return 1;
        }else if(this.g+this.h<o.g+o.h){
            return -1;
        }else{
            return 0;
        }
    }
}

AStar.java:

package com.mygdx.game.commons.AStar;


import java.util.ArrayList;
import java.util.Collections;
import java.util.PriorityQueue;

public class AStar {
    private PriorityQueue<Node> openList = new PriorityQueue<>();
    private ArrayList<Node> closeList = new ArrayList<>();
    private int[][] map;
    private Point startPoint;
    private Point endPoint;
    private int w;
    private int h;

    public AStar(int[][] map, Point startPoint, Point endPoint) {
        this.map = map;
        this.w = map.length;
        this.h = map[0].length;

        this.startPoint = startPoint;
        this.endPoint = endPoint;
    }

    //判断point是不是在关闭表中
    public Node pointInCloseList(Point point) {
        for (Node node : this.closeList) {
            if (node.point.eq(point)) {
                return node;
            }
        }
        return null;
    }

    //判断point是否在开启表中,如果在就返回它(不取出)
    public Node pointInOpenList(Point point) {
        for (Node node : this.openList) {
            if (node.point.eq(point)) {
                return node;
            }
        }
        return null;
    }

    //搜索周围节点
    private void searchNear(Node minNode, int offsetX, int offsetY) {
        //越界检测
        if (minNode.point.x + offsetX < 0 || minNode.point.x + offsetX >= this.w || minNode.point.y + offsetY < 0 || minNode.point.y + offsetY >= this.h) {
            return;
        }
        //如果是障碍就忽略
        if (this.map[minNode.point.x + offsetX][minNode.point.y + offsetY] != 0) {
            return;
        }
        //如果在closelist中就忽略
        Point currentPoint = new Point(minNode.point.x + offsetX, minNode.point.y + offsetY);
        if (this.pointInCloseList(currentPoint)!=null) {
            return;
        }
        //设置单位花费
        int step;
        if (offsetX == 0 || offsetY == 0) {
            step = 10;
        } else {
            step = 14;
        }
        Node currentNode = this.pointInOpenList(currentPoint);
        //如果不在openList中,就把它加入openList
        if (currentNode == null) {
            currentNode = new Node(currentPoint, this.endPoint, minNode.g + step);
            currentNode.father = minNode;
            this.openList.add(currentNode);
            return;
        }
        //如果在openList中,判断minNode到当前点的G是否更小
        if (minNode.g + step < currentNode.g) {
            //g值更小,重新计算g值并且改变father
            currentNode.g = minNode.g + step;
            currentNode.father = minNode;
        }
    }

    public ArrayList<Point> start() {
        //寻路结果
        ArrayList<Point> pointList = new ArrayList<>();

        //如果寻路终点是障碍,就直接中断寻路
        if (this.map[this.endPoint.x][this.endPoint.y] == 1) {
            return null;
        }

        //1.把起点放入开启表
        Node startNode = new Node(this.startPoint, this.endPoint, 0);
        this.openList.add(startNode);

        //2.主循环寻路
        while (true) {
            //从openlist中取出F值最小的节点
            Node minNode = this.openList.poll();
            //把这个点加入到closeList
            this.closeList.add(minNode);
            //搜索当前节点周围的节点
            this.searchNear(minNode, 0, -1);
            this.searchNear(minNode, 0, 1);
            this.searchNear(minNode, -1, 0);
            this.searchNear(minNode, 1, 0);
            this.searchNear(minNode, -1, -1);
            this.searchNear(minNode, 1, 1);
            this.searchNear(minNode, -1, 1);
            this.searchNear(minNode, 1, -1);

            //判断是否终止
            Node node = this.pointInCloseList(this.endPoint);
            if(node!=null){
                //终点在关闭表中,说明寻路成功
                while(true){
                    if(node.father!=null){
                        pointList.add(node.point);
                        node = node.father;
                    }else{
                        Collections.reverse(pointList);
                        return pointList;
                    }
                }
            }

            if (this.openList.size() == 0) {
                return null;
            }
        }
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值