#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__
|