A 星寻路算法代码 --java 版(A* 搜索算法)

本贴最后更新于 1272 天前,其中的信息可能已经物是人非
import java.util.*;

/**
 * @author sunze
 * @date 2020/10/26 4:55 下午
 */
public class Astar {

    /**
     * 公式 :F=G+H
     *
     * 含义:G:起点到当前点的距离 H :当前点到终点的距离。
     *
     * F:等于前面两者之和,用于判定下一节点该往哪里走。如下图,此时,我们先不考虑障碍物先。
     */

    /**
     * 初始化地图
     */
    public static final String[][] MAP={
    //              0  1  2  3  4  5  6  7  8
            /*0*/ { "0", "0", "0", "0", "0", "0", "0", "0", "0" },
            /*1*/ { "0", "0", "0", "0", "0", "0", "0", "0", "0" },
            /*2*/ { "0", "0", "0", "0", "0", "0", "0", "0", "0" },
            /*3*/ { "0", "0", "0", "1", "0", "0", "0", "0", "0" },
            /*4*/ { "0", "0", "0", "1", "0", "0", "0", "0", "0" },
            /*5*/ { "0", "0", "0", "1", "0", "0", "0", "0", "0" },
            /*6*/ { "0", "0", "0", "1", "0", "0", "0", "0", "0" },
            /*7*/ { "0", "0", "0", "1", "0", "0", "0", "0", "0" },
            /*8*/ { "0", "0", "0", "1", "0", "0", "0", "0", "0" }
    };

    /**
     * 横着走所需能量
     */
    public static final Integer HORIZONTAL_STEP= 10;
    /**
     * 斜着走所需能量
     */
    public static final Integer OBLIQUE_STEP= 14;

    /**
     * 可使用列表
     */
    public static List<Node> OPEN=new ArrayList<>();
    /**
     * 不可使用列表
     */
    public static List<Node> CLOSE=new ArrayList<>();

    private static final Node END_NODE=new Node(6,7);
    private static final Node START_NODE=new Node(7,1);

//    private static void
//                0  1  2  3  4  5  6  7  8
    //    /*0*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0 },
    //    /*1*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0 },
    //    /*2*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0 },
    //    /*3*/ { 0, 0, 0, 1, 0, 0, 0, 0, 0 },
    //    /*4*/ { 0, 0, 0, 1, 0, 0, 0, 0, 0 },
    //    /*5*/ { 0, 0, 0, 1, 0, 0, 0, 0, 0 },
    //    /*6*/ { 0, 0, 0, 1, 0, 0, 0, 0, 0 },
    //    /*7*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0 },
    //    /*8*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0 }
    public static void main(String[] args) {
        //将开始节点加入可使用列表
        START_NODE.parent=START_NODE;
        OPEN.add(START_NODE);
        while (CLOSE.indexOf(END_NODE)<0){
            //查找open中的F值最小的节点
            Node minFNodeInOpenList = OPEN.remove(0);
            //将这个节点放到close节点中
            CLOSE.add(0,minFNodeInOpenList);
            //获取这个节点周围的可移动节点并放入到open中
            findNeighborNodes(minFNodeInOpenList);
        }

        //回溯查找最短路径
        Node temp = CLOSE.get(0);
        List<Node> result = new ArrayList<>();
        while (temp.parent!=null&&temp!=temp.parent){
            result.add(0,temp);
            temp=temp.parent;
        }
        result.add(0,START_NODE);
        String[][] resultMap = MAP;
        for (Node node : result) {
            resultMap[node.x][node.y]="$";
        }
        showResult(resultMap);
        System.out.println("-------------------");
        String[][] tempMap = MAP;
        for (Node node : CLOSE) {
            System.out.println(node.x+":"+node.y);
            tempMap[node.x][node.y]="*";
        }
        showResult(tempMap);
    }


    private static void showResult(String[][] arr){
        for (int i = 0, j = 0; i < arr.length;) {
            System.out.print(arr[i][j]+" ");
            j++;
            if (j >= arr[i].length) {
                i++;
                j = 0;
                System.out.print("\n");
            }
        }
    }

    /**
     * 包括斜着周围一共有8个节点
     * @param currentNode
     */
    public static void findNeighborNodes(Node currentNode) {
        List<Node> temp = new ArrayList<>();
        int x = currentNode.x;
        int y = currentNode.y;
        //
        for (int i=x-1>=0?x-1:0;i<=(x+1<=8?x+1:8);i++){
            for (int j=y-1>=0?y-1:0;j<=(y+1<=8?y+1:8);j++){
                //去除当前节点并且此节点不在close列表中
                if(!(i==x&&j==y)&&CLOSE.indexOf(new Node(i,j))<0&&OPEN.indexOf(new Node(i,j))<0){
                    //除去障碍物
                    if(MAP[i][j]!="1"){
                        //计算F值
                        Node node = new Node(i, j);
                        node.parent=currentNode;
                        int g = calcG(currentNode, node);
                        int h = calcH(END_NODE, node);
                        node.H=h;
                        node.G=g;
                        node.calcF();
                        temp.add(node);
                    }
                }
            }
        }
        OPEN.addAll(temp);
        Collections.sort(OPEN);
    }

    private static int calcG(Node start, Node node) {
        if(start.x==node.x||start.y==node.y){
            return HORIZONTAL_STEP+node.parent.G;
        }else{
            return OBLIQUE_STEP+node.parent.G;
        }
    }

    /**
     *     这个是最简单粗暴的计算H值得方法,当然还有其它方法,这里先理解AStar的思想先,以后可以自己改进这个计算H值得方法
      */
    private static int calcH(Node end, Node node) {
        int step = Math.abs(node.x - end.x) + Math.abs(node.y - end.y);
        return step * HORIZONTAL_STEP;
    }

    public static class Node implements Comparable<Node>{
        public Node(int x, int y) {
            this.x = x;
            this.y = y;
        }

        public int x;
        public int y;

        public int F;
        public int G;
        public int H;

        public void calcF() {
            this.F = this.G + this.H;
        }

        public Node parent;

        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;
            Node node = (Node) o;
            return x == node.x &&
                    y == node.y;
        }

        @Override
        public int hashCode() {
            return Objects.hash(x, y);
        }

        @Override
        public int compareTo(Node o) {
            if(this.F > o.F){
                return 1;
            }
            if(this.F < o.F){
                return -1;
            }
            return 0;
        }
    }

}

demo:https://github.com/sunzeJAVA/AStar.git

  • 算法
    388 引用 • 254 回帖 • 22 关注

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...

推荐标签 标签

  • 职场

    找到自己的位置,萌新烦恼少。

    126 引用 • 1699 回帖
  • Java

    Java 是一种可以撰写跨平台应用软件的面向对象的程序设计语言,是由 Sun Microsystems 公司于 1995 年 5 月推出的。Java 技术具有卓越的通用性、高效性、平台移植性和安全性。

    3168 引用 • 8207 回帖 • 1 关注
  • Solo

    Solo 是一款小而美的开源博客系统,专为程序员设计。Solo 有着非常活跃的社区,可将文章作为帖子推送到社区,来自社区的回帖将作为博客评论进行联动(具体细节请浏览 B3log 构思 - 分布式社区网络)。

    这是一种全新的网络社区体验,让热爱记录和分享的你不再感到孤单!

    1425 引用 • 10043 回帖 • 472 关注
  • sts
    2 引用 • 2 回帖 • 148 关注
  • 外包

    有空闲时间是接外包好呢还是学习好呢?

    26 引用 • 232 回帖 • 6 关注
  • 机器学习

    机器学习(Machine Learning)是一门多领域交叉学科,涉及概率论、统计学、逼近论、凸分析、算法复杂度理论等多门学科。专门研究计算机怎样模拟或实现人类的学习行为,以获取新的知识或技能,重新组织已有的知识结构使之不断改善自身的性能。

    76 引用 • 37 回帖
  • 面试

    面试造航母,上班拧螺丝。多面试,少加班。

    324 引用 • 1395 回帖 • 1 关注
  • 资讯

    资讯是用户因为及时地获得它并利用它而能够在相对短的时间内给自己带来价值的信息,资讯有时效性和地域性。

    53 引用 • 85 回帖
  • TensorFlow

    TensorFlow 是一个采用数据流图(data flow graphs),用于数值计算的开源软件库。节点(Nodes)在图中表示数学操作,图中的线(edges)则表示在节点间相互联系的多维数据数组,即张量(tensor)。

    20 引用 • 19 回帖
  • CodeMirror
    1 引用 • 2 回帖 • 116 关注
  • Hadoop

    Hadoop 是由 Apache 基金会所开发的一个分布式系统基础架构。用户可以在不了解分布式底层细节的情况下,开发分布式程序。充分利用集群的威力进行高速运算和存储。

    82 引用 • 122 回帖 • 616 关注
  • 开源

    Open Source, Open Mind, Open Sight, Open Future!

    396 引用 • 3413 回帖
  • Wide

    Wide 是一款基于 Web 的 Go 语言 IDE。通过浏览器就可以进行 Go 开发,并有代码自动完成、查看表达式、编译反馈、Lint、实时结果输出等功能。

    欢迎访问我们运维的实例: https://wide.b3log.org

    30 引用 • 218 回帖 • 606 关注
  • RESTful

    一种软件架构设计风格而不是标准,提供了一组设计原则和约束条件,主要用于客户端和服务器交互类的软件。基于这个风格设计的软件可以更简洁,更有层次,更易于实现缓存等机制。

    30 引用 • 114 回帖 • 3 关注
  • CAP

    CAP 指的是在一个分布式系统中, Consistency(一致性)、 Availability(可用性)、Partition tolerance(分区容错性),三者不可兼得。

    11 引用 • 5 回帖 • 563 关注
  • 快应用

    快应用 是基于手机硬件平台的新型应用形态;标准是由主流手机厂商组成的快应用联盟联合制定;快应用标准的诞生将在研发接口、能力接入、开发者服务等层面建设标准平台;以平台化的生态模式对个人开发者和企业开发者全品类开放。

    15 引用 • 127 回帖 • 1 关注
  • FlowUs

    FlowUs.息流 个人及团队的新一代生产力工具。

    让复杂的信息管理更轻松、自由、充满创意。

    1 引用 • 2 关注
  • 支付宝

    支付宝是全球领先的独立第三方支付平台,致力于为广大用户提供安全快速的电子支付/网上支付/安全支付/手机支付体验,及转账收款/水电煤缴费/信用卡还款/AA 收款等生活服务应用。

    29 引用 • 347 回帖
  • Logseq

    Logseq 是一个隐私优先、开源的知识库工具。

    Logseq is a joyful, open-source outliner that works on top of local plain-text Markdown and Org-mode files. Use it to write, organize and share your thoughts, keep your to-do list, and build your own digital garden.

    4 引用 • 55 回帖 • 7 关注
  • Maven

    Maven 是基于项目对象模型(POM)、通过一小段描述信息来管理项目的构建、报告和文档的软件项目管理工具。

    185 引用 • 318 回帖 • 350 关注
  • WordPress

    WordPress 是一个使用 PHP 语言开发的博客平台,用户可以在支持 PHP 和 MySQL 数据库的服务器上架设自己的博客。也可以把 WordPress 当作一个内容管理系统(CMS)来使用。WordPress 是一个免费的开源项目,在 GNU 通用公共许可证(GPLv2)下授权发布。

    45 引用 • 113 回帖 • 317 关注
  • SQLServer

    SQL Server 是由 [微软] 开发和推广的关系数据库管理系统(DBMS),它最初是由 微软、Sybase 和 Ashton-Tate 三家公司共同开发的,并于 1988 年推出了第一个 OS/2 版本。

    19 引用 • 31 回帖 • 3 关注
  • Lute

    Lute 是一款结构化的 Markdown 引擎,支持 Go 和 JavaScript。

    25 引用 • 191 回帖 • 20 关注
  • H2

    H2 是一个开源的嵌入式数据库引擎,采用 Java 语言编写,不受平台的限制,同时 H2 提供了一个十分方便的 web 控制台用于操作和管理数据库内容。H2 还提供兼容模式,可以兼容一些主流的数据库,因此采用 H2 作为开发期的数据库非常方便。

    11 引用 • 54 回帖 • 641 关注
  • 区块链

    区块链是分布式数据存储、点对点传输、共识机制、加密算法等计算机技术的新型应用模式。所谓共识机制是区块链系统中实现不同节点之间建立信任、获取权益的数学算法 。

    91 引用 • 751 回帖
  • B3log

    B3log 是一个开源组织,名字来源于“Bulletin Board Blog”缩写,目标是将独立博客与论坛结合,形成一种新的网络社区体验,详细请看 B3log 构思。目前 B3log 已经开源了多款产品:SymSoloVditor思源笔记

    1083 引用 • 3461 回帖 • 287 关注
  • ngrok

    ngrok 是一个反向代理,通过在公共的端点和本地运行的 Web 服务器之间建立一个安全的通道。

    7 引用 • 63 回帖 • 599 关注