A星算法是寻路的经典算法,在很多游戏中有使用,性能关键在于启发函数的设计。

函数式语言erlang实现一些算法上还是相当绕,有一些无可避免的地方需要用一些非典型的语法实现(变量不可变、无循环语法、无法在函数中return等),实现了一个基础的A星算法,启发式函数使用对角线估价法,先按对角线走,一直走到与终点水平或垂直平行后,再笔直的走。

随便构造一个地图文件来进行测试,用erlang的statistics函数进行性能测试。

在游戏服务端中,A星算法这种比较吃性能的函数,不宜大量使用,一般是情况下最好能做到在无法通过暴力寻路方式时才转入A星寻路。对这种运算量较大的地方可以进行统一管理,避免同一时间内的大量计算而导致CPU吃紧。

%%%-----------------------------------
%% @Description: 寻路逻辑
%%%-----------------------------------
-module(lib_path).
-define(BLOCK, 1).
-record(node, {x = 0, z = 0, g = 0, h = 0, f = 0, father = {-99999, -99999}
}).
-export([astar_search/5     %% A星寻路
]).%% A星寻路
%% return : [{PosX, PosZ}] , 列表从终点到起点排列)
astar_search(_MapId, StartX, StartZ, EndX, EndZ) ->case is_block(EndX, EndZ) of%% 终点为障碍点,返回空true -> [];false ->StartNode = #node{x = StartX, z = StartZ, g = 0, h = 0, f = 0, father = {-99999, -99999}},OpenList = [StartNode],CloseList = [],put(end_point, {EndX, EndZ}),start_search(OpenList, CloseList)end.%% ====================================================内部处理逻辑==================================================== %%
%% ====================================================内部处理逻辑==================================================== %%
%% ====================================================内部处理逻辑==================================================== %%
%% A星寻路核心逻辑
start_search([], _CloseList) -> []; %% 路径不存在
start_search(OpenList, CloseList) ->{MinNode, OpenList2} = get_min_node(OpenList),{EndX, EndZ} = get(end_point),case MinNode#node.x =:= EndX andalso MinNode#node.z =:= EndZ of%% 找到路径true -> build_path(MinNode, [], MinNode#node.f);false ->%% 查找八个方向{NewOpenList, CloseList2} = search_for_eight_dir(OpenList2, CloseList, MinNode, lists:seq(1, 8)),%% 节点放入到 close list 里面NewCloseList = CloseList2 ++ [MinNode],put({MinNode#node.x, MinNode#node.z}, MinNode),start_search(NewOpenList, NewCloseList)end.%% 在open_list中找到最佳点,并删除
get_min_node([]) -> {#node{}, []};
get_min_node(OpenList) ->MinI = get_min_node_i(9999, 0, 0, OpenList),Node = lists:nth(MinI, OpenList),NewOpenList = lists:delete(Node, OpenList),{Node, NewOpenList}.
get_min_node_i(_MinValue, MinNth, _NowNth, []) -> MinNth;
get_min_node_i(MinValue, MinNth, NowNth, [Node | RestList]) ->case Node#node.f < MinValue oftrue -> get_min_node_i(Node#node.f, NowNth + 1, NowNth + 1, RestList);false -> get_min_node_i(MinValue, MinNth, NowNth + 1, RestList)end.%% 计算路径
build_path(undefined, Paths, SumCost) -> {Paths, SumCost};
build_path(Node, Paths, SumCost) ->NewPaths = [{Node#node.x, Node#node.z} | Paths],build_path(get(Node#node.father), NewPaths, SumCost).%% 查找八个方向
search_for_eight_dir(OpenList, CloseList, _MinNode, []) -> {OpenList, CloseList};
search_for_eight_dir(OpenList, CloseList, MinNode, [Nth | Rest]) ->{X, Z} = case Nth of1 -> {MinNode#node.x,     MinNode#node.z + 1};2 -> {MinNode#node.x,     MinNode#node.z - 1};3 -> {MinNode#node.x + 1, MinNode#node.z    };4 -> {MinNode#node.x + 1, MinNode#node.z + 1};5 -> {MinNode#node.x + 1, MinNode#node.z - 1};6 -> {MinNode#node.x - 1, MinNode#node.z    };7 -> {MinNode#node.x - 1, MinNode#node.z + 1};8 -> {MinNode#node.x - 1, MinNode#node.z - 1}end,case is_block(X, Z) oftrue -> search_for_eight_dir(OpenList, CloseList, MinNode, Rest);false ->CurNode = get_fgh(MinNode, X, Z),Open = node_in_list(X, Z, OpenList),Close = node_in_list(X, Z, CloseList),case Open =:= false andalso Close =:= false of%% 不在OPEN表和CLOSE表中%% 添加特定节点到 open listtrue -> NewOpenList = OpenList ++ [CurNode],NewCloseList = CloseList;false -> case Open of%% 在CLOSE表中false ->CloseNode = Close,case CloseNode#node.f > CurNode#node.f oftrue -> NewOpenList = OpenList ++ [CurNode],NewCloseList = lists:delete(CloseNode, CloseList),put({CurNode#node.x, CurNode#node.z}, CurNode);false ->NewOpenList = OpenList,NewCloseList = CloseListend;%% 在OPEN表OpenNode ->case OpenNode#node.f > CurNode#node.f of%% 更新OPEN表中的估价值true -> NewOpenList = node_replace_list(OpenNode, CurNode, OpenList, []),NewCloseList = CloseList;false ->NewOpenList = OpenList,NewCloseList = CloseListendendend,search_for_eight_dir(NewOpenList, NewCloseList, MinNode, Rest)end.%% 获取 f ,g ,h
get_fgh(Father, X, Z) ->Cost = case Father#node.x =:= X orelse Father#node.z =:= Z oftrue -> 1;false -> 1.414end,G = Father#node.g + Cost,H = diagonal(X, Z),F = G + H,Node = #node{x = X, z = Z, g = G, h = H, f = F, father = {Father#node.x, Father#node.z}},Node.%% 对角线估价法,先按对角线走,一直走到与终点水平或垂直平行后,再笔直的走
diagonal(X, Z) ->{EndX, EndZ} = get(end_point),Dx = abs(X - EndX),Dz = abs(Z - EndZ),MinD = min(Dx, Dz),H = MinD * 1.414 + Dx + Dz - 2 * MinD,H.node_in_list(_X, _Z, []) -> false;
node_in_list(X, Z, [Node | RestList]) ->case Node#node.x =:= X andalso Node#node.z =:= Z oftrue -> Node;false -> node_in_list(X, Z, RestList)end.%% 用NewNode把List中的OldNode替换掉
node_replace_list(_OldNode, _NewNode, [], NewList) -> lists:reverse(NewList);
node_replace_list(OldNode, NewNode, [Node | RestList], NewList) -> case OldNode =:= Node oftrue -> node_replace_list(OldNode, NewNode, RestList, [NewNode | NewList]);false -> node_replace_list(OldNode, NewNode, RestList, [Node | NewList])end.%% 是否障碍点
is_block(X, Z) ->case map:get(X, Z) of?BLOCK -> true;_ ->X < map:get_min_x() orelse X > map:get_max_x() orelse Z < map:get_min_z() orelse Z > map:get_max_z()end.

erlang实现A星算法相关推荐

  1. A星算法(Java实现)

    2019独角兽企业重金招聘Python工程师标准>>> 一.适用场景 在一张地图中,绘制从起点移动到终点的最优路径,地图中会有障碍物,必须绕开障碍物. 二.算法思路 1. 回溯法得到 ...

  2. cocos2d-x游戏实例(5)-A星算法(1)

    小满(bill man)个人原创,欢迎转载,转载请注明地址,小满(bill man)的专栏地址http://blog.csdn.net/bill_man 继续上一篇地图上的处理,不过和本篇相比,我们之 ...

  3. cocos2d-x游戏实例(8)-A星算法(4)

    小满(bill man)个人原创,欢迎转载,转载请注明地址,小满(bill man)的专栏地址http://blog.csdn.net/bill_man 继续A星算法,我们在经历了地图的检测,并且检测 ...

  4. 北斗导航 | Select Satellite 选星算法

    ================================================ 博主github:https://github.com/MichaelBeechan 博主CSDN:h ...

  5. cocos2d-x游戏实例(9)-A星算法(5)

    小满(bill man)个人原创,欢迎转载,转载请注明地址,小满(bill man)的专栏地址http://blog.csdn.net/bill_man 上一篇我们已经完成了A星算法,那么如何使用呢, ...

  6. cocos2d-x游戏实例(7)-A星算法(3)

    小满(bill man)个人原创,欢迎转载,转载请注明地址,小满(bill man)的专栏地址http://blog.csdn.net/bill_man 继续上一篇的内容,我们再看我们上一篇进行的部分 ...

  7. cocos2d-x游戏实例(6)-A星算法(2)

    小满(bill man)个人原创,欢迎转载,转载请注明地址,小满(bill man)的专栏地址http://blog.csdn.net/bill_man 上一篇中我们研究了A星算法的基本概念,本篇介绍 ...

  8. c语言八数码A星算法代码解析,八数码问题c语言a星算法详细实验报告含代码解析...

    八数码问题c语言a星算法详细实验报告含代码解析 (13页) 本资源提供全文预览,点击全文预览即可全文预览,如果喜欢文档就下载吧,查找使用更方便哦! 14.9 积分 一.实验内容和要求 八数码问题:在3 ...

  9. Cocos2d-x 3.1.1 学习日志16--A星算法(A*搜索算法)学问

    A *搜索算法称为A星算法.这是一个在图形平面,路径.求出最低通过成本的算法. 经常使用于游戏中的NPC的移动计算,或线上游戏的BOT的移动计算上. 首先:1.在Map地图中任取2个点,開始点和结束点 ...

最新文章

  1. 解决Android Studio中DDMS缺少File Explore视窗的方法
  2. python为什么中文要encoding-python2.x 默认编码问题
  3. java调试jdk源码_JDK源码调试
  4. 第十节 字符串指针变量与字符数组的区别(十一)
  5. 封装一个信号量集操作函数的工具
  6. 失去循环标签的Python,我这样实现跳出外层循环
  7. matlab 局部图放大或缩小
  8. Go1.17 这个新特性竟是 6 年前提出来的
  9. iptables的详细介绍及配置方法
  10. CentOS 7.1.1503 varnish动静分离反代用户请求
  11. 十种可以成为知己的异性
  12. URDGN:Ultra-resolve Face Images by Discriminative Generative Networks
  13. Java main方法快捷键
  14. 自动化测试,你一定要知道的知识
  15. 可视化:小型有向网络HTML自动生成器
  16. Paper | Detail-revealing Deep Video Super-resolution
  17. 一加3T解锁OEM、刷入TWRP、第三方ROM以及ROOT
  18. java电影院购票系统概况_电影院售票管理系统
  19. Android OkHttp 全面详解
  20. buntu18.04无线网卡无法识别问题

热门文章

  1. DVWA SQL注入攻击
  2. jmeter压力测试并发数如何设置?
  3. android 代码设置铃声,在Android中设置铃声
  4. 抖音、微信关闭个性化推荐功能上线,用户真能摆脱“算法牢笼”吗?
  5. Kebernetes 学习总结(11) K8s 网络模型分析(1)
  6. squashfs─sfs镜像文件制作方法简要介绍
  7. 输给“深蓝”20年后,卡斯帕罗夫撰文呼吁对人工智能抱持乐观心态
  8. 电信无线网卡无服务器,优化电信3G无线上网卡网速的办法
  9. oracle中查询外键约束,Oracle外键约束信息的查询
  10. 5G NR PDCCH DCI