JS/HTML5游戏常用算法之路径搜索算法 A*寻路算法完整实例

非常感谢你对于本站文章的关注。下面是针对文章“JS/HTML5游戏常用算法之路径搜索算法 A*寻路算法完整实例”的完整攻略解析。

1. 介绍

本文主要讲解的是一种常用于解决路径搜索问题的算法—— A*寻路算法。使用该算法可以在搜索空间(如地图、游戏场景等)中找到一条最优路径,可应用于许多领域,如自动驾驶、游戏AI等。

2. 算法流程

该算法通过在搜索空间中创建一个节点集来实现。

  • 先将起点加入节点集。
  • 从节点集中选取离起点最近的节点,计算其相邻节点的路径距离,如果路径距离加上该节点到起点的距离小于该相邻节点到起点的距离,那么更新该相邻节点到起点的距离,并将该节点加入节点集。
  • 重复步骤2,直到到达终点或搜索完所有节点。

3. 代码实现

该算法实现中,需定义地图和节点对象。

//定义地图对象
var map = {
    width: 10,
    height: 10,
    obstacles: [{x:3,y:3},{x:4,y:3},{x:5,y:3},{x:4,y:4}]
};

//定义节点对象
function node(x, y, endX, endY) {
    this.x = x; //节点横坐标
    this.y = y; //节点纵坐标
    this.g = 0; //起点到当前节点的距离
    this.h = Math.abs(endX - x) + Math.abs(endY - y); //当前节点到终点的估算距离
    this.f = this.g + this.h; //节点综合评价函数
    this.parent = null; //当前节点的父节点
}

以上实现是一个简单示例,地图的width和height分别为地图的宽度和高度,obstacles表示地图上的障碍物,使用数组形式存储,每个障碍物包含x和y属性表示该障碍物在地图上的位置信息。节点对象包括x、y、g、h、f和parent属性。其中g表示起点到当前节点的距离,h表示当前节点到终点的估算距离,f表示g和h的综合评价函数,parent表示当前节点的父节点。

在实现中需要定义开始节点和结束节点,调用寻路函数进行搜索。

//开始节点
var start = new node(0, 0, 9, 9);

//结束节点
var end = new node(9, 9, 9, 9);

//寻路函数
function findPath(start, end) {
    var openList = [start]; //节点集合(初始状态只包含起点)
    var closedList = []; //已处理节点集合

    while (openList.length > 0) {
        //找到f值最小的节点
        var node = openList[0];
        for (var i = 1; i < openList.length; i++) {
            if (openList[i].f < node.f) {
                node = openList[i];
            }
        }

        //将该节点从节点集中删除并加入已处理集合
        openList.splice(openList.indexOf(node), 1);
        closedList.push(node);

        //如果该节点为终点
        if (node.x === end.x && node.y === end.y) {
            var path = [];
            while (node.parent) {
                path.push(node);
                node = node.parent;
            }
            return path.reverse();
        }

        //找到该节点相邻的节点,并计算路径距离
        var neighbors = getNeighbors(node, end);
        for (var j = 0; j < neighbors.length; j++) {
            var neighbor = neighbors[j];

            //如果该节点已在已处理集合中则跳过
            if (closedList.indexOf(neighbor) > -1) {
                continue;
            }

            //计算路径距离
            var g = node.g + (neighbor.x === node.x || neighbor.y === node.y ? 10 : 14);

            //如果路径距离加上该节点到终点的距离小于该相邻节点到起点的距离,则更新节点并加入节点集中
            if (g + neighbor.h < neighbor.f) {
                neighbor.g = g;
                neighbor.f = neighbor.g + neighbor.h;
                neighbor.parent = node;
                if (openList.indexOf(neighbor) === -1) {
                    openList.push(neighbor);
                }
            }
        }
    }

    //如果没有找到路径
    return null;
}

//计算当前节点相邻的节点
function getNeighbors(node, end) {
    var neighbors = [];
    var x = node.x,
        y = node.y;

    //左
    if (x > 0 && !(map.obstacles.filter(function(item){return item.x===x-1 && item.y===y}).length>0)){
        neighbors.push(new node(x - 1, y, end.x, end.y));
    }

    //右
    if (x < map.width - 1 && !(map.obstacles.filter(function(item){return item.x===x+1 && item.y===y}).length>0)){
        neighbors.push(new node(x + 1, y, end.x, end.y));
    }

    //上
    if (y > 0 && !(map.obstacles.filter(function(item){return item.x===x && item.y===y-1}).length>0)){
        neighbors.push(new node(x, y - 1, end.x, end.y));
    }

    //下
    if (y < map.height - 1 && !(map.obstacles.filter(function(item){return item.x===x && item.y===y+1}).length>0)){
        neighbors.push(new node(x, y + 1, end.x, end.y));
    }

    //左上
    if (x > 0 && y > 0 && !(map.obstacles.filter(function(item){return item.x===x-1 && item.y===y-1}).length>0)){
        neighbors.push(new node(x - 1, y - 1, end.x, end.y));
    }

    //右上
    if (x < map.width - 1 && y > 0 && !(map.obstacles.filter(function(item){return item.x===x+1 && item.y===y-1}).length>0)){
        neighbors.push(new node(x + 1, y - 1, end.x, end.y));
    }

    //左下
    if (x > 0 && y < map.height - 1 && !(map.obstacles.filter(function(item){return item.x===x-1 && item.y===y+1}).length>0)){
        neighbors.push(new node(x - 1, y + 1, end.x, end.y));
    }

    //右下
    if (x < map.width - 1 && y < map.height - 1 && !(map.obstacles.filter(function(item){return item.x===x+1 && item.y===y+1}).length>0)){
        neighbors.push(new node(x + 1, y + 1, end.x, end.y));
    }

    return neighbors;
}

4. 示例说明

以下是一个示例,以10*10的地图为例,地图中有四个障碍物,起点为左上角,终点为右下角。

0   1   2   3   4   5   6   7   8   9   
1   .   .   .   .   .   .   .   .   .   |   0
2   .   .   .   #   #   #   .   .   .   |   1
3   .   .   .   .   .   .   .   .   .   |   2
4   .   .   .   .   .   .   .   .   .   |   3
5   .   .   .   .   .   .   .   .   .   |   4
6   .   .   .   .   .   .   .   .   .   |   5
7   .   .   .   .   .   .   .   .   .   |   6
8   .   .   .   .   .   .   .   .   .   |   7
9   .   .   .   .   .   .   .   .   .   |   8
                             |  9
      0 1   2   3   4   5   6   7   8   9   

假设障碍物的坐标为对应位置的左上角坐标。

根据以上示例,在调用寻路函数后,实现的输出结果为:

[
    node {x: 9, y: 9, g: 40, h: 0, f: 40, parent: node{x:8,y:8,...}},
    node {x: 8, y: 8, g: 33, h: 2, f: 35, parent: node{x:7,y:7,...}},
    node {x: 7, y: 7, g: 26, h: 4, f: 30, parent: node{x:6,y:6,...}},
    ...
    node {x: 1, y: 1, g: 10, h: 10, f: 20, parent: node{x:0,y:0,...}},
    node {x: 0, y: 0, g: 0, h: 18, f: 18, parent: null}
]

输出结果包含了所有寻找到最短路径的节点。可以从后往前找到起点和终点间所需的节点数,实现路径的绘制。

5. 总结

以上就是本文对 A*寻路算法的完整分析及实现。希望通过阅读本文,读者可以完全了解本算法的实现过程和应用场景。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:JS/HTML5游戏常用算法之路径搜索算法 A*寻路算法完整实例 - Python技术站

(0)
上一篇 2023年5月19日
下一篇 2023年5月19日

相关文章

  • java排序算法图文详解

    Java排序算法图文详解 在Java编程中,排序算法是非常重要且常见的一部分。本文将详细讲解Java中的各种排序算法及其实现,帮助读者了解不同算法的特点和使用场景,提高程序的效率和可读性。 排序算法分类 在Java中,常用的排序算法主要可以分为以下几类: 冒泡排序 选择排序 插入排序 快速排序 归并排序 堆排序 冒泡排序 冒泡排序是一种简单的排序算法,其原理…

    算法与数据结构 2023年5月19日
    00
  • JS简单数组排序操作示例【sort方法】

    JS简单数组排序操作示例【sort方法】 操作说明 在JavaScript中,通过数组的sort()方法可以对数组进行排序操作。sort()方法会直接对原数组进行排序,返回排序后的原数组。 sort()方法通常需要传入一个比较函数,来指定排序规则。比较函数接收两个参数,分别表示待比较的两个元素,如果返回值小于0,则表示第一个元素排在第二个元素前面;如果返回值…

    算法与数据结构 2023年5月19日
    00
  • Lua中写排序算法实例(选择排序算法)

    让我为您详细讲解一下Lua中写排序算法实例(选择排序算法)的完整攻略。 什么是选择排序算法 选择排序是一种简单直观的排序算法,它的工作原理如下: 在待排序的数组中找到最小元素; 将其存放到数组的起始位置; 在剩余未排序的元素中继续寻找最小值,并放到已排序序列的末尾; 重复步骤3,直到待排序序列中的所有元素均已排序完毕。 选择排序的实现思路简单,但由于每次都要…

    算法与数据结构 2023年5月19日
    00
  • JavaScript之排序函数_动力节点Java学院整理

    JavaScript之排序函数_动力节点Java学院整理 背景 在JavaScript中,排序是一项非常常见的操作,在很多应用中都需要用到排序函数。了解和掌握排序函数的使用方法,可以大大提升我们编写JavaScript程序的效率。 排序函数的定义 在JavaScript中,排序函数是Array对象中的一个方法,用于对数组进行排序。其基本的语法格式如下: ar…

    算法与数据结构 2023年5月19日
    00
  • C语言详细讲解qsort函数的使用

    C语言详细讲解qsort函数的使用 qsort函数简介 在C语言中,qsort函数是一个标准库函数,用于将一个数组排序。它使用快速排序算法,实现了高效的排序。qsort函数的原型定义如下: void qsort (void* base, size_t num, size_t size, int (*compar)(const void*,const void…

    算法与数据结构 2023年5月19日
    00
  • C语言实现数组元素排序方法详解

    C语言实现数组元素排序方法详解 概述 数组元素排序是C语言中常见的操作,它将数组中的元素按照一定的规则进行排序,使其符合特定的要求。常见的排序方法包括冒泡排序、插入排序、选择排序、快速排序等。 本文将详细讲解C语言实现数组元素排序的方法,包括上述四种排序方法的原理、代码实现,帮助初学者快速入门。 冒泡排序 冒泡排序是一种简单的排序方法,它依次比较相邻的两个元…

    算法与数据结构 2023年5月19日
    00
  • JavaScript实现快速排序(自已编写)

    下面是详细的讲解JavaScript实现快速排序的完整攻略。 1. 什么是快速排序? 快速排序是一种常用的排序算法,通过分割(partition)和递归分治的思想来快速排序一个数组,在平均情况下它的时间复杂度为 $O(n\log n)$,也是一种不稳定的排序方法。 2. 快速排序的实现过程 2.1 分割 对一个数组进行快速排序的过程就是先将其从中间分割成两部…

    算法与数据结构 2023年5月19日
    00
  • 冒泡排序算法及Ruby版的简单实现

    冒泡排序是一种比较简单的排序算法,其基本思想是重复地遍历数列,每次比较相邻的两个元素,如果前一个元素比后一个元素大,则交换这两个元素的位置,直到遍历完整个数列,这样一次遍历后,数列中最大的元素就被排到了最后面。重复执行此过程,直到整个数列有序为止。 以下是冒泡排序算法的Ruby版简单实现: def bubble_sort(array) n = array.l…

    算法与数据结构 2023年5月19日
    00
合作推广
合作推广
分享本页
返回顶部