AStar 算法(erlang版本)
来源:互联网 发布:java二级考试 编辑:程序博客网 时间:2024/06/06 02:08
A* 算法的erlang实现,下面的代码在get_neighbour_coord函数里面使用到了判断坐标是否可走的map:is_movable_coord 函数,需要自己去实现并替换。
以下是源码:
%%=========================astar.erl=====================================
%% ====================================================================
%% API functions
%% ====================================================================
-export([find_path_by_astar/5]).
-record(pathcoord, {g=0,f=0,now_pos={},parent_coord={}}).
%%=========================================================
%% A*寻路算法 written by pjc
%%=========================================================
%% 假设下面是一张小地图
%% y ----------------------------------------------------------------------------------
%% * |(0,9) | (1,9) | (2,9) | (3,9) | (4,9) | (5,9) | (6,9) | (7,9) | (8,9) | (9,9) |
%% * |-------|--------|-------|-------|-------|--------|-------|-------|-------|-------|
%% * |(0,8) | (1,8) | (2,8) | (3,8) | (4,8) | (5,8) | (6,8) | (7,8) | (8,8) | (9,8) |
%% * |-------|--------|-------|-------|-------|--------|-------|-------|-------|-------|
%% * |(0,7) | (1,7) | (2,7) | (3,7) | (4,7) | (5,7) | (6,7) | (7,7) | (8,7) | (9,7) |
%% * |-------|--------|-------|-------|-------|--------|-------|-------|-------|-------|
%% * |(0,6) | (1,6) | (2,6) | (3,6) | (4,6) | (5,6) | (6,6) | (7,6) | (8,6) | (9,6) |
%% * |-------|--------|-------|-------|-------|--------|-------|-------|-------|-------|
%% * |(0,5) | (1,5) | (2,5) | (3,5) | (4,5) | (5,5) | (6,5) | (7,5) | (8,5) | (9,5) |
%% * |-------|--------|-------|-------|-------|--------|-------|-------|-------|-------|
%% * |(0,4) | (1,4) | (2,4) | (3,4) | (4,4) | (5,4) | (6,4) | (7,4) | (8,4) | (9,4) |
%% * |-------|--------|-------|-------|-------|--------|-------|-------|-------|-------|
%% * |(0,3) | (1,3) | (2,3) | (3,3) | (4,3) | (5,3) | (6,3) | (7,3) | (8,3) | (9,3) |
%% * |-------|--------|-------|-------|-------|--------|-------|-------|-------|-------|
%% * |(0,2) | (1,2) | (2,2) | (3,2) | (4,2) | (5,2) | (6,2) | (7,2) | (8,2) | (9,2) |
%% * |-------|--------|-------|-------|-------|--------|-------|-------|-------|-------|
%% * |(0,1) | (1,1) | (2,1) | (3,1) | (4,1) | (5,1) | (6,1) | (7,1) | (8,1) | (9,1) |
%% * |-------|--------|-------|-------|-------|--------|-------|-------|-------|-------|
%% * |(0,0) | (1,0) | (2,0) | (3,0) | (4,0) | (5,0) | (6,0) | (7,0) | (8,0) | (9,0) |
%% 0 ----------------------------------------------------------------------------------> x
find_path_by_astar(SceneId,Src_x,Src_y,Des_x,Des_y) ->
CheckDict = dict:new(),
UncheckDict = dict:new(),
SrcPathCoord =#pathcoord{g=0,f=0,now_pos={Src_x,Src_y}},
NewUncheckDict = dict:store({Src_x,Src_y}, SrcPathCoord, UncheckDict),
find_path_by_astar(SceneId,{Src_x,Src_y},{Des_x,Des_y},
CheckDict, NewUncheckDict,[SrcPathCoord]).
find_path_by_astar(SceneId,SrcCoord,DesCoord,CheckDict,UncheckDict,UncheckList) ->
Unlen = erlang:length(UncheckList),
if
Unlen =< 0 -> []; %%结束(未找到路径)
Unlen > 0 ->
CurrPathCoord = lists:last(UncheckList),
{CurX,CurY} = CurrPathCoord#pathcoord.now_pos,
UncheckList1=lists:delete(CurrPathCoord, UncheckList),
UncheckDict1 = dict:erase({CurX,CurY}, UncheckDict),
CheckDict1 = dict:store({CurX,CurY}, CurrPathCoord, CheckDict),
case {CurX,CurY} =:= DesCoord of
true-> generate_final_path(DesCoord,CheckDict1,[]);%%找到目标点
_ ->
NeiList1 = get_neighbour_coord(SceneId,CurX,CurY),
%%过滤已经在checkdict中坐标,转为pathcoord
NeiList2 = [{X,Y}|| {X,Y} <- NeiList1,dict:find({X,Y}, CheckDict1)==error],
NeiList3 = covert_to_path_coord(CurrPathCoord,DesCoord,NeiList2,[]),
%%判断是否在uncheckdict和 UncheckList中,比较G+F值的大小,如果更优,则加入uncheck list
Exist = [ PathCoord|| PathCoord <- NeiList3,
dict:find(PathCoord#pathcoord.now_pos, UncheckDict1)=/=error],
{UncheckList2,UncheckDict2} = filter_exist_coord(Exist,UncheckList1, UncheckDict1),
%%把新的坐标加到uncheck list和uncheck dict,然后排序uncheck list(逆序)
UncheckDict3 = add_new_coord(NeiList3, UncheckDict2),
UncheckList3 = lists:append(NeiList3, UncheckList2),
UncheckList4 = lists:sort(fun(Coord1,Coord2) ->
if Coord1#pathcoord.f =< Coord2#pathcoord.f -> false;
true -> true
end end, UncheckList3),
find_path_by_astar(SceneId,SrcCoord, DesCoord,CheckDict1, UncheckDict3,UncheckList4)
end
end.
generate_final_path(CurCoord,CheckDict,Path) ->
case erlang:tuple_size(CurCoord) =< 0 of
true-> Path;
_ ->
{ok,Value} = dict:find(CurCoord, CheckDict),
Path1 = lists:append([CurCoord], Path),
Parent = Value#pathcoord.parent_coord,
generate_final_path(Parent,CheckDict,Path1)
end.
covert_to_path_coord(ParentPathCoord,{DesX,DesY}=DesCoord,InList,OutList) ->
case erlang:length(InList)>0 of
false -> OutList;
_ ->
[{CurX,CurY}|LeftCoord]=InList,
{Px,Py}=ParentPathCoord#pathcoord.now_pos,
Tmp_g = ParentPathCoord#pathcoord.g + cal_a_star_g(CurX,CurY,Px,Py),
Tmp_f = cal_a_star_h(CurX,CurY,DesX,DesY)+Tmp_g,
NewPathCoord = #pathcoord{g=Tmp_g,f=Tmp_f,now_pos={CurX,CurY},parent_coord={Px,Py}},
OutList1 = lists:append([NewPathCoord],OutList),
covert_to_path_coord(ParentPathCoord,DesCoord,LeftCoord,OutList1)
end.
%% 把NewCoord加到Dict中
add_new_coord(NewCoordList,Dict) ->
case erlang:length(NewCoordList)>0 of
false -> Dict;
_ ->
[Coord|LeftCoord]=NewCoordList,
add_new_coord(LeftCoord, dict:store(Coord#pathcoord.now_pos, Coord, Dict))
end.
filter_exist_coord(ExistCoord,UncheckList,UncheckDict) ->
case erlang:length(ExistCoord)>0 of
false ->{UncheckList,UncheckDict};
_ ->
[Coord|LeftCoord]=ExistCoord,
{pathcoord,G,F,Pos,Parent} = Coord,
{Ret,UncheckDict3} =
case dict:find(Pos, UncheckDict) of
{ok,{pathcoord,G1,F1,Pos1,Parent1}} ->
if F < F1 ->
UncheckDict1=dict:erase(Pos1, UncheckDict),
{true,dict:store(Pos, Coord, UncheckDict1)};
true -> {false,UncheckDict}
end;
_ -> {false,UncheckDict}
end,
UncheckList1=
case Ret of
true -> lists:append([Coord], UncheckList);
_ -> UncheckList
end,
filter_exist_coord(LeftCoord,UncheckList1,UncheckDict3)
end.
%%根据9宫格算出{Coord_x,Coord_y}的相邻坐标中的可走坐标,返回数组[{x,y}]
get_neighbour_coord(SceneId,Coord_x,Coord_y) ->
Sudoku=[{-1,1},{0,1},{1,1},{-1,0},{1,0},{-1,-1},{0,-1},{1,-1}],
List = [{Coord_x+X, Coord_y+Y} || {X,Y} <- Sudoku],
[{X,Y} || {X,Y} <- List,X>=0,Y>=0,map:is_movable_coord(SceneId,X, Y)==true].
%%当前点到目标点都的h值
cal_a_star_h(Src_x,Src_y,Des_x,Des_y) ->
(abs((Src_x - Des_x))+abs((Src_y - Des_y)))*10.
%%相邻点的g值
cal_a_star_g(Src_x,Src_y,Des_x,Des_y) ->
if Src_x==Des_x,abs(Src_y-Des_y)=:=1
orelse Src_y==Des_y,abs(Src_x-Des_x)=:=1 -> 10;%%直线距离10
true -> 14 %%斜线距离14
end.
0 0
- AStar 算法(erlang版本)
- AStar A* 算法的Erlang实现
- (一)Astar算法
- Astar算法
- Astar算法
- AStar算法
- AStar算法
- 寻路(AStar/A星/A*)算法
- 寻路(AStar/A星/A*)算法
- JavaScript实现AStar算法
- C# Astar算法
- AStar(A星)算法
- AStar算法笔记
- astar算法伪代码
- AStar算法学习笔记
- cocos2dx(lua)ASTAR算法
- AStar寻径算法
- astar寻路算法
- VIM教程
- vs2010、sql2005、sql2008的斗争
- paypal 获取订单,获取交易信息 demo
- (14)Java网络编程-基础篇
- latex 单行或多行公式的排版
- AStar 算法(erlang版本)
- 修改Windows路由表
- Storm:多并行度下Spout和Blot实体间Tuple的定向传输(tuple在多流时的路由)
- PL/SQL:ORA-00980同义词转换不再有效
- Android-JNI开发总结
- 生产者与消费者得问题描述
- 语言模型
- C/C++不同文件夹下包含头文件的方法及#include的使用
- 博社村民用新康泰克制毒 小学生剥壳倒粉末月入1万