AStar A* 算法的Erlang实现
来源:互联网 发布:朗文字典 for mac 编辑:程序博客网 时间:2024/06/04 18:47
%% @author rolong@vip.qq.com%% 本代码来自 瑞仙的Erlang开发博客%% http://blog.csdn.net/zhongruixian-module(astar1).-export([ find_path/2 ,test/2 ]).-record(state, { open_trees %% 开启列表 ,close_sets %% 关闭列表 ,parents_trees %% 父节点列表 ,xy %% 目标点 }).-record(point, { xy = {0, 0} ,g = 0 ,h = 0 ,f = 0 }).%% 1为向上,按顺时针依次为1~8-define(DIRS, [1,2,3,4,5,6,7,8]).%%' APItest(XY1, XY2) -> Path = find_path(XY1, XY2), io:format("Path:~n~p~n", [Path]), show_path(Path).find_path(XY1, XY2) -> State = #state{ open_trees = gb_trees:empty() ,close_sets = gb_sets:new() ,xy = XY2 ,parents_trees = gb_trees:empty() }, StartPoint = #point{xy = XY1}, OpenTrees = gb_trees:enter(XY1, {0, 0, 0}, State#state.open_trees), State1 = State#state{open_trees = OpenTrees}, find_next_point(StartPoint, State1).%%.%%' priv-spec walkable({X, Y}) -> true | false when X :: integer(), Y :: integer().%%'walkable函数根据具体点阵实现%% 示例如下:walkable({X, Y}) -> {Row, Col} = map(size), case X >= 0 andalso Y >= 0 andalso X < Row andalso Y < Col of true -> Block = map(block), Nth = X + Y * Row + 1, case string:substr(Block, Nth, 1) of "1" -> true; "0" -> false end; false -> false end;walkable(_) -> false.map(size) -> {20, 10};map(block) -> %01234567890123456789 "11111111111111111111" % 0 "11111111111111111111" % 1 "11111111111111111111" % 2 "11111111000111111111" % 3 "11111111000111111111" % 4 "11111111000111111111" % 5 "11111111000111111111" % 6 "11111111000111111111" % 7 "11111111000111111111" % 8 "11111111111111111111" % 9 .%%.find_next_point(#point{xy = XY}, #state{xy = XY} = State) -> get_path(XY, State#state.parents_trees, [XY]);find_next_point(#point{xy = XY} = CurPoint, State) -> State1 = open2close(CurPoint, State), %% 将周围点添加到开放列表中 AroundPoints = find_around_points(CurPoint, State1), State2 = add_open_trees(AroundPoints, XY, State1), case find_min_f_point(State2) of none -> io:format("Error coord:~w~n", [CurPoint#point.xy]), []; NextPoint -> find_next_point(NextPoint, State2) end.find_min_f_point(State) -> Iter = gb_trees:iterator(State#state.open_trees), find_min_f_point(Iter, -1, none).find_min_f_point(Iter, F, Point) -> case gb_trees:next(Iter) of none -> Point; {XY, {G1, H1, F1}, Iter1} -> case F1 < F orelse F =:= -1 of true -> Point1 = #point{ xy = XY ,g = G1 ,h = H1 ,f = F1 }, find_min_f_point(Iter1, F1, Point1); false -> find_min_f_point(Iter1, F, Point) end end.xy2point({CurX, CurY}, ParentPoint, {DstX, DstY}) -> #point{ xy = {X, Y} ,g = G } = ParentPoint, AddG = if CurX =:= X -> 10; CurY =:= Y -> 10; true -> 14 end, CurH = (erlang:abs(CurX - DstX) + erlang:abs(CurY - DstY)) * 10, CurG = G + AddG, #point{ xy = {CurX, CurY} ,g = CurG ,h = CurH ,f = CurG + CurH }.%% 找出周围点find_around_points(Point, State) -> #state{ close_sets = CloseSets } = State, #point{ xy = {X, Y} } = Point, F = fun(Dir, Acc) -> XY1 = get_next_coord(Dir, X, Y), case walkable(XY1) of true -> case gb_sets:is_element(XY1, CloseSets) of true -> Acc; false -> Point1 = xy2point(XY1, Point, State#state.xy), [Point1 | Acc] end; false -> Acc end end, lists:foldl(F, [], ?DIRS).add_open_trees([Point | Tail], ParentXY, State) -> case gb_trees:lookup(Point#point.xy, State#state.open_trees) of {_XY, {G, _H, _F}} -> case Point#point.g < G of true -> State1 = add_open_trees1(Point, ParentXY, State), add_open_trees(Tail, ParentXY, State1); false -> add_open_trees(Tail, ParentXY, State) end; none -> State1 = add_open_trees1(Point, ParentXY, State), add_open_trees(Tail, ParentXY, State1) end;add_open_trees([], _ParentXY, State) -> State.add_open_trees1(Point, ParentXY, State) -> #point{xy = XY, g = G, h = H, f = F} = Point, OpenTrees1 = gb_trees:enter(XY, {G, H, F}, State#state.open_trees), ParentsTrees1 = gb_trees:enter(XY, ParentXY, State#state.parents_trees), State#state{ open_trees = OpenTrees1 ,parents_trees = ParentsTrees1 }.open2close(Point, State) -> OpenTrees = gb_trees:delete(Point#point.xy, State#state.open_trees), CloseSets = gb_sets:add(Point#point.xy, State#state.close_sets), State#state{ open_trees = OpenTrees ,close_sets = CloseSets }.get_next_coord(1,X,Y)->{X,Y-1};get_next_coord(2,X,Y)->{X+1,Y-1};get_next_coord(3,X,Y)->{X+1,Y};get_next_coord(4,X,Y)->{X+1,Y+1};get_next_coord(5,X,Y)->{X,Y+1};get_next_coord(6,X,Y)->{X-1,Y+1};get_next_coord(7,X,Y)->{X-1,Y};get_next_coord(8,X,Y)->{X-1,Y-1}.get_path(XY, ParentsTrees, Acc) -> case gb_trees:lookup(XY, ParentsTrees) of none -> Acc; {value, XY1} -> get_path(XY1, ParentsTrees, [XY1 | Acc]) end.%%'用于测试打印show_path(XYs) -> Block = map(block), {Row, Col} = map(size), Len = Row * Col, show_path(XYs, Row, Col, Len, Block).show_path([{X, Y} | XYs], Row, Col, Len, Block) -> LeftLen = X + Y * Row, RightLen = Len - LeftLen - 1, Left = string:left(Block, LeftLen), Right = string:right(Block, RightLen), Block1 = Left ++ "*" ++ Right, show_path(XYs, Row, Col, Len, Block1);show_path([], Row, _Col, Len, Block) -> show_path1(Row, Len, Block, "").show_path1(_Row, Len, _Block, Acc) when Len =< 0 -> io:format("~n~s~n", [Acc]);show_path1(Row, Len, Block, Acc) -> Len1 = Len - Row, Left = string:left(Block, Row), Block1 = string:right(Block, Len1), Acc1 = Acc ++ Left ++ "\n", show_path1(Row, Len1, Block1, Acc1).%%.%%.%%% vim: set foldmethod=marker filetype=erlang foldmarker=%%',%%.:
1 0
- AStar A* 算法的Erlang实现
- A*(Astar)搜索算法的实现(C语言)
- AStar 算法(erlang版本)
- AStar(A星)算法
- erlang实现A星算法
- 用Astar(A*)算法 实现的迷宫最短路。代码比较规范,可作为模板
- JavaScript实现AStar算法
- 寻路(AStar/A星/A*)算法
- 寻路(AStar/A星/A*)算法
- 寻路算法 Astar A星算法
- Astar A*算法 最短路径算法
- 最短路径算法之AStar算法(二) A Star算法需要注意的问题
- Java开源-astar:A 星算法
- A*(AStar)或者也叫A星算法的寻路问题
- 通用Astar算法 通用A星算法 通用A*算法
- 用javascript实现astar算法和demo
- Astar算法
- Astar算法
- 出国程序---网上申报流程
- ubuntu 命令行下打开图形化文件夹
- UBIFS文件系统简介 与 利用mkfs.ubifs和ubinize两个工具制作UBI镜像 .
- python Linux 信号编程 signals
- Linux查看硬件信息以及驱动设备的命令
- AStar A* 算法的Erlang实现
- ibatis批量插入 批量删除 -iterate标签应用
- 第三章第十七题
- spring mvc jstl分页
- 10分钟教会你Apache Shiro
- hdu 2665 可持久化线段树求区间第K大值(函数式线段树||主席树)
- iOS Assertion failure in -[UITableView _classicHeightForRowAtIndexPath:]
- Docker学习笔记 — Weave实现跨主机容器互联
- java 根据当天时间 获取前7天之间的时间 和后多少天的查询时间,获娶近几周 周一的日期