#ifndef?__ASTAR_SERACH_ALGO_H__
#define
?__ASTAR_SERACH_ALGO_H__
#include?
<
Algorithm
>
????
namespace
?fredazsq

{????
namespace
?linghuye

{????
????

/**/
/**/
/**/
/*
************************************************
**?尋路節點
************************************************
*/
template
<
typename?TNodeLocation
>
struct
?TAXNode

{????
????
float
???????G,?F;
????TNodeLocation??pos;
????TAXNode
*
???pParentNode;
????
bool
???????bClosed;????????
//
?使用狀態表明節點處于開放或關閉列表.
????
????
bool
?
operator
<
(
const
?TAXNode
&
?node)?
const
????
{????
????????
return
?pos?
<
?node.pos;
????}
????
}
;????
????

/**/
/**/
/**/
/*
*****************************************************************************
**??封裝A*尋路算法
*******************************************************************************
**??作為棋盤信息提供類TField必須實現下列函數:
**??1.?bool?IsFieldThrough(TNodeLocation?pos)?const;????????????????????????????????????在?pos?位置是否為空,可通行.
**??2.?float?EvaluateStepCost(TNodeLocation?posFrom,?TNodeLocation?posTo,?TNodeLocation?posLastStep)?const;????????計算pos1,pos2到單步代價.
**??3.?float?EvaluateProbableCost(TNodeLocation?posFrom,?TNodeLocation?posTo)?const;????計算pos1,pos2到估算代價.
**??4.?TNodeLocation*?QueryNeiborLocations(TNodeLocation?pos,?int&?nNodeCount);?const????詢問pos的相鄰可通節點集
*******************************************************************************
**??TNodeLocation,節點位置
**??1.支持<,==,=操作符,如int.
*******************************************************************************
**??0.?初始化時傳入棋盤信息提供類的實例引用.
**??1.?使用主函數SearchPath進行搜索,使用QueryResultPath取得結果.
*****************************************************************************
*/
template
<
class
?TField,?
class
?TNodeLocation
>
struct
?CAStar2DAlgo

{????
public
:
????typedef?std::vector
<
TNodeLocation
>
????CResultPath;
????typedef?TAXNode
<
TNodeLocation
>
????????CAXNode;
????typedef?std::
set
<
CAXNode
>
????????????CAXNodeSet;
????
????
struct
?CAXNodePriorityQueue????????????
//
?優先隊列?
????
{????
????????std::vector
<
CAXNode
*>
?m_heap;
????????
????????
static
?
bool
?AXNodeCostSortPred(CAXNode
*
?n1,?CAXNode
*
?n2)
 ????????
{????
????????????
return
?(n1
->
G?
+
?n1
->
F)?
>
?(n2
->
G?
+
?n2
->
F);
????????}
????????
????????
void
?push(CAXNode
*
?pNode)
 ????????
{
????????????m_heap.push_back(pNode);
????????????std::push_heap(m_heap.begin(),?m_heap.end(),?
&
CAXNodePriorityQueue::AXNodeCostSortPred);
????????}
????????
????????CAXNode
*
?pop()
 ????????
{????
????????????CAXNode
*
?pNode?
=
?m_heap.front();
????????????std::pop_heap(m_heap.begin(),?m_heap.end(),?
&
CAXNodePriorityQueue::AXNodeCostSortPred);
????????????m_heap.pop_back();
????????????
return
?pNode;
????????}
????????
????????
bool
?empty()
 ????????
{
????????????
return
?m_heap.empty();
????????}
????????
????????
void
?resort(CAXNode
*
?pNode)
 ????????
{????
????????????std::vector
<
CAXNode
*>
::iterator?it?
=
?std::find(m_heap.begin(),?m_heap.end(),?pNode);
????????????std::push_heap(m_heap.begin(),?it,?
&
CAXNodePriorityQueue::AXNodeCostSortPred);
????????}
????????
????????
void
?clear()
 ????????
{
????????????m_heap.clear();
????????}
????}
;????
????????
public
:????
????
const
?TField
&
?m_field;
????TNodeLocation??m_posTarget;
????CAXNode
*
?m_ptrTargetNode;????????????????????
//
?Result?Node
????????
????CAXNodeSet?m_setNodes;????????????????????????
//
?All?nodes?in?use?
????CAXNodePriorityQueue?m_queOpenNodes;????????
//
?Cost?sorted?open?list
????????
public
:????
????CAStar2DAlgo(
const
?TField
&
?field)?:?m_field(field),?m_ptrTargetNode(NULL)
 ????
{????????
????}
????
????????
????
~
CAStar2DAlgo()
 ????
{????
????}
????
????????
????
void
?Reset()
 ????
{????
????????m_setNodes.clear();
????????m_queOpenNodes.clear();
????????m_ptrTargetNode?
=
?NULL;
????}
????
????????
public
:????
????inline?CAXNode
*
?ClaimNode(TNodeLocation?pos,?CAXNode
*
?pParentNode?
=
?NULL)
 ????
{????
????????CAXNode?node;
????????node.pos?
=
?pos;
????????node.F?
=
?node.G?
=
?
0
;
????????node.bClosed?
=
?
false
;????
//
?Default?is?open
????????node.pParentNode?
=
?pParentNode;
????????
return
?
&
(
*
m_setNodes.insert(node).first);
????}
????
????????
????
bool
?SearchPath(TNodeLocation?posStart,?TNodeLocation?posTarget)
 ????
{????
????????CAXNode
*
?pCurNode;
????????m_posTarget?
=
?posTarget;
????????
????????
//
?Add?start?node?into?open?list
????????CAXNode
*
?pStartNode?
=
?ClaimNode(posStart);
????????m_queOpenNodes.push(pStartNode);
????????
????????
while
(
!
m_queOpenNodes.empty())
 ????????
{????
????????????
//
?Pick?lowest?cost?node
????????????pCurNode?
=
?m_queOpenNodes.pop();
????????????
????????????
//
?Check?search?target
????????????
if
(pCurNode
->
pos?
==
?m_posTarget)
 ????????????
{
????????????????m_ptrTargetNode?
=
?pCurNode;
????????????????
return
?
true
;
????????????}
????????????
????????????
//
?Switch?node?from?OpenList?to?CloseList
????????????pCurNode
->
bClosed?
=
?
true
;
????????????ProcessNeighborNodes(pCurNode);
????????}
????????
????????
return
?
false
;
????}
????????
????
void
?ProcessNeighborNodes(CAXNode
*
?pCurNode)
 ????
{????
????????CAXNode?tempNode;
????????
int
?nNodeCount?
=
?
0
;
????????TNodeLocation
*
?pLocs?
=
?m_field.QueryNeiborLocations(pCurNode
->
pos,?nNodeCount);
????????TNodeLocation?posLastStep?
=
?pCurNode
->
pParentNode
?
?pCurNode
->
pParentNode
->
pos?:?pCurNode
->
pos;
????????
????????
//
?For?each?neibors?
????????
for
(
int
?i?
=
?
0
;?i?
<
?nNodeCount;?
++
i)
 ????????
{????
????????????tempNode.pos?
=
?pLocs[i];
????????????
if
(m_field.IsFieldThrough(tempNode.pos))
 ????????????
{????
????????????????CAXNodeSet::iterator?it?
=
?m_setNodes.find(tempNode);
????????????????
if
(it?
==
?m_setNodes.end())
 ????????????????
{????
????????????????????CAXNode
*
?pNewNode?
=
?ClaimNode(tempNode.pos,?pCurNode);
????????????????????pNewNode
->
G?
=
?pCurNode
->
G?
+
?m_field.EvaluateStepCost(pCurNode
->
pos,?pNewNode
->
pos,?posLastStep);
????????????????????pNewNode
->
F?
=
?m_field.EvaluateProbableCost(pNewNode
->
pos,?m_posTarget);
????????????????????m_queOpenNodes.push(pNewNode);
????????????????}
????
????????????????
else
?
if
(
!
it
->
bClosed)
 ????????????????
{????
????????????????????CAXNode
&
?node?
=
?
*
it;
????????????????????
float
?G?
=
?pCurNode
->
G?
+
?m_field.EvaluateStepCost(pCurNode
->
pos,?node.pos,?posLastStep);
????????????????????
if
(G?
<
?node.G)
 ????????????????????
{????
????????????????????????node.G?
=
?G;
????????????????????????node.pParentNode?
=
?pCurNode;
????????????????????????m_queOpenNodes.resort(
&
node);
????????????????????}
????????????????}
????????????}
????????}
????}
????
 ????
/**/
/**/
/**/
/*
*****************************************************************
????**??取回最終結果
????*****************************************************************
*/
????
bool
?QueryResultPath(CResultPath
&
?path)
 ????
{????
????????
if
(
!
m_ptrTargetNode)?
return
?
false
;
????????
????????CAXNode
*
?pNode?
=
?m_ptrTargetNode;
????????
while
(pNode)
 ????????
{????
????????????path.push_back(pNode
->
pos);
????????????pNode?
=
?pNode
->
pParentNode;
????????}
????????
return
?
true
;
????}
}
;


/**/
/**/
/**/
/*
******************************************************************************
**??TNodeLocation,節點位置
**??1.支持<,==?操作符號.
*******************************************************************************
*/
template
<
typename?TNodeLocation
>
struct
?CShisenFieldImpl

{????
????TNodeLocation
*
?QueryNeiborLocations(TNodeLocation?pos,?
int
&
?nRetCount)?
const
????
{????
 ????????
static
?
const
?
int
?dy[
4
]?
=
?
{?
1
,?
0
,?
0
,?
-
1
?}
;
????????
static
?TNodeLocation?posNeibors[
4
];????
//
?Single?thread
????????????????
????????nRetCount?
=
?
4
;
????????
for
(
int
?i?
=
?
0
;?i?
<
?
4
;?i
++
)
 ????????
{
????????????posNeibors[i].x?
=
?pos.x?
+
?dx[i];
????????????posNeibors[i].y?
=
?pos.y?
+
?dy[i];
????????}
????????
return
?posNeibors;
????}
????
????
float
?EvaluateStepCost(TNodeLocation?posFrom,?TNodeLocation?posTo,?TNodeLocation?posLast)?
const
????
{????
????????
if
(((posFrom.x
-
posTo.x)??
&&
??(posLast.y
-
posFrom.y))??
||
??
???????????((posFrom.y
-
posTo.y)??
&&
??(posLast.x
-
posFrom.x)))
 ????????
{????
????????????
return
?
100
;
????????}
????????
else
?
return
?
1
;
????}
????
????
float
?EvaluateProbableCost(TNodeLocation?pos1,?TNodeLocation?pos2)?
const
????
{
????????
return
?
0
;
????}
????

/**/
/**/
/**/
/*
????平滑優化
????float?EvaluateStepCost(MY_POSITION?posFrom,?MY_POSITION?posTo,?MY_POSITION?posLast)?const
????{????
????????int?cx1?=?posTo.x?-?posFrom.x;
????????int?cy1?=?posTo.y?-?posFrom.y;
????????int?cx2?=?posFrom.x?-?posLast.x;
????????int?cy2?=?posFrom.y?-?posLast.y;
????????return?((cx1?==?cx2??&&??cy1?==?cy2)??0?:?10)?+?((cx1??&&??cy1)??14?:?10);
????}
*/
????
}
;????
????

/**/
/**/
/**/
/*
******************************************************************************
**??最小路徑
******************************************************************************
*/
template
<
typename?TNodeLocation
>
struct
?CShortestPathFieldImpl

{????
????TNodeLocation
*
?QueryNeiborLocations(TNodeLocation?pos,?
int
&
?nRetCount)?
const
????
{????
 ????????
static
?
const
?
int
?dx[
4
]?
=
?
{?
0
,?
-
1
,?
1
,??
0
?}
;
 ????????
static
?
const
?
int
?dy[
4
]?
=
?
{?
1
,??
0
,?
0
,?
-
1
?}
;
????????
static
?TNodeLocation?posNeibors[
4
];????
//
?Single?thread
????????????????
????????nRetCount?
=
?
4
;
????????
for
(
int
?i?
=
?
0
;?i?
<
?
4
;?i
++
)
 ????????
{
????????????posNeibors[i].x?
=
?pos.x?
+
?dx[i];
????????????posNeibors[i].y?
=
?pos.y?
+
?dy[i];
????????}
????????
return
?posNeibors;
????}
????
????
float
?EvaluateStepCost(TNodeLocation?posFrom,?TNodeLocation?posTo,?TNodeLocation?posLast)?
const
????
{????
????????
return
?
1
;
????}
????
????
float
?EvaluateProbableCost(TNodeLocation?pos1,?TNodeLocation?pos2)?
const
????
{
????????
return
?
0
;
????}
}
;


/**/
/**/
/**/
/*
******************************************************************************
**??最小路徑
******************************************************************************
*/
template
<
typename?TNodeLocation
>
struct
?CGamePathFieldImpl

{????
????TNodeLocation
*
?QueryNeiborLocations(TNodeLocation?pos,?
int
&
?nRetCount)?
const
????
{????
 ????????
static
?
const
?
int
?dx[
8
]?
=
?
{?
-
1
,?
0
,?
1
,?
-
1
,?
1
,?
-
1
,??
0
,??
1
?}
;
 ????????
static
?
const
?
int
?dy[
8
]?
=
?
{??
1
,?
1
,?
1
,??
0
,?
0
,?
-
1
,?
-
1
,?
-
1
?}
;
????????
static
?MY_POSITION?posNeibors[
8
];
????????
????????nRetCount?
=
?
8
;
????????
for
(
int
?i?
=
?
0
;?i?
<
?
8
;?i
++
)
 ????????
{
????????????posNeibors[i].x?
=
?pos.x?
+
?dx[i];
????????????posNeibors[i].y?
=
?pos.y?
+
?dy[i];
????????}
????????
return
?posNeibors;
????}
????
????
float
?EvaluateStepCost(TNodeLocation?posFrom,?TNodeLocation?posTo,?TNodeLocation?posLast)?
const
????
{????
????????
if
(posFrom.x
-
posTo.x??
&&
??posFrom.y
-
posTo.y)
 ????????
{
????????????
return
?
14
;
????????}
????????
else
?
return
?
10
;
????}
????
????
float
?EvaluateProbableCost(TNodeLocation?posFrom,?TNodeLocation?posTo)?
const
????
{
????????
return
?(abs(posFrom.x
-
posTo.x)?
+
?abs(posFrom.y
-
posTo.y))?
*
?
10
;
????}
}
;

}
//
?namespace?linghuye
}
//
?namespace?fredazsq
#endif
//
__FIELD_SERACH_ALGO_H__
|