C++ A星搜索算法赢得';找不到有效的路径
我正在尝试在我的3D网格中实现一个A*算法用于寻路。我一直在遵循一个教程,但我没有得到一个有效的路径。我已经检查了我的代码以了解发生了什么,但我不知道如何解决这个问题。对于最基本的测试,我只是使用二维网格(它是三维的,但是只有一个Z选项,所以基本上是二维的) 下面是它正在做的事情: 所以我们从0,0(橙色)开始,想得到1,2(绿色)。首先,它计算橙色正方形的两个选项:北和东,并为F值3和2.414获取2和1.414的距离。它移动到东广场(0,1)。伟大的但是现在它从0,1开始计算两个开平方,分别是1,1和0,2,它们的g值都是2,h值(距离)都是1,使得它们的F值都是3 由于其F值为3,并且我们已经有一个F值为3(从起点算起为1,0)的选项,因此这两个选项被忽略,即使它们显然是最佳选项 然后继续前进,切换到移动到1,0,然后再次将1,1计算为3,将2,0计算为4.236。1,1的f值不大于当前的f值,因此被忽略,我们向上移动到2,0 2,0只能向右移动 2,1只能向下移动,因为2,2是一个无效的正方形,但是移动到1,1的f值保存为3,因此再次忽略它,使我们在0,0和1,2之间没有有效的路径。我错过了什么 这是我的路径循环的一个片段。这里有很多自定义结构,我使用来自虚幻引擎的TMap来存储我的封闭列表,但我认为这与问题无关。关于这些结构是什么,这里有一个简单而肮脏的例子:C++ A星搜索算法赢得';找不到有效的路径,c++,algorithm,path-finding,a-star,C++,Algorithm,Path Finding,A Star,我正在尝试在我的3D网格中实现一个A*算法用于寻路。我一直在遵循一个教程,但我没有得到一个有效的路径。我已经检查了我的代码以了解发生了什么,但我不知道如何解决这个问题。对于最基本的测试,我只是使用二维网格(它是三维的,但是只有一个Z选项,所以基本上是二维的) 下面是它正在做的事情: 所以我们从0,0(橙色)开始,想得到1,2(绿色)。首先,它计算橙色正方形的两个选项:北和东,并为F值3和2.414获取2和1.414的距离。它移动到东广场(0,1)。伟大的但是现在它从0,1开始计算两个开平方,分
:保存单元格坐标PCell
:将单元格坐标保存为PCell和F值PPair
:三维整数向量FVectorInt
:保存父坐标以及f、g和h值FPathCell
是cellDetails
FPathCell
是一个TMap,其closedMap
为
locationIsWalkable(FVectorInt,StepDirection)
只是检查玩家是否可以从某个方向走到某个单元格的代码。你可以忽略这一部分
std::set<PPair> openList;
PPair originPair = PPair();
originPair.cell = PCell(i, j, k);
originPair.f = 0.0;
openList.insert(originPair);
bool foundDestination = false;
FPathCell destPair;
FVectorInt destCell;
while (!openList.empty() && !foundDestination)
{
iterations++;
PPair p = *openList.begin();
//Remove vertex
openList.erase(openList.begin());
//Add vertex to closed list
i = p.cell.i;
j = p.cell.j;
k = p.cell.k;
closedMap.Remove(FIntVector(i, j, k));
closedMap.Add(FIntVector(i, j, k), true);
double gNew, hNew, fNew;
//Generate movement options
//Option 1: NORTH (+X)
//Process if valid movement
if (locationIsWalkable(FVectorInt(i + 1, j, k), StepDirection::North))
{
FVectorInt check = FVectorInt(i + 1, j, k);
//If this cell is the destination
if (check == destination)
{
foundDestination = true;
//Set the parent of the destination cell
cellDetails[check.x][check.y][check.z].parent_i = i;
cellDetails[check.x][check.y][check.z].parent_j = j;
cellDetails[check.x][check.y][check.z].parent_k = k;
destPair = cellDetails[check.x][check.y][check.z];
destCell = check;
break;
}
//Else if this cell is not in the closed list
else if (!closedMap.FindRef(FIntVector(check.x, check.y, check.z)))
{
gNew = cellDetails[i][j][k].g + 1;
hNew = calculateHValue(check, destination);
fNew = gNew + hNew;
if (cellDetails[check.x][check.y][check.z].f == FLT_MAX ||
cellDetails[check.x][check.y][check.z].f > fNew) {
PPair cellPair = PPair();
cellPair.cell = PCell(check.x, check.y, check.z);
cellPair.f = fNew;
openList.insert(cellPair);
cellDetails[check.x][check.y][check.z].f = fNew;
cellDetails[check.x][check.y][check.z].g = gNew;
cellDetails[check.x][check.y][check.z].h = hNew;
cellDetails[check.x][check.y][check.z].parent_i = i;
cellDetails[check.x][check.y][check.z].parent_j = j;
cellDetails[check.x][check.y][check.z].parent_k = k;
}
}
}
//11 other movement options
}
std::设置openList;
PPair originPair=PPair();
originPair.cell=PCell(i,j,k);
原始配对f=0.0;
openList.insert(originPair);
bool foundDestination=false;
FPathCell对;
Fvector细胞;
而(!openList.empty()&&!foundDestination)
{
迭代++;
PPair p=*openList.begin();
//删除顶点
擦除(openList.begin());
//将顶点添加到闭合列表
i=p.cell.i;
j=p.cell.j;
k=p.cell.k;
关闭地图。移除(FIntVector(i,j,k));
closedMap.Add(FIntVector(i,j,k),true);
双gNew,hNew,fNew;
//生成移动选项
//备选方案1:北部(+X)
//处理是否有效移动
if(位置可行走(FVectorInt(i+1,j,k),步进方向::北))
{
FVectorInt检查=FVectorInt(i+1,j,k);
//如果此单元格是目标
如果(检查==目的地)
{
foundDestination=true;
//设置目标单元格的父级
cellDetails[check.x][check.y][check.z].parent_i=i;
cellDetails[check.x][check.y][check.z].parent_j=j;
cellDetails[check.x][check.y][check.z].parent_k=k;
destPair=cellDetails[check.x][check.y][check.z];
destCell=检查;
打破
}
//否则,如果此单元格不在关闭列表中
否则如果(!closedMap.FindRef(FIntVector(check.x,check.y,check.z)))
{
gNew=cellDetails[i][j][k].g+1;
hNew=计算值(检查,目的地);
fNew=gNew+hNew;
if(cellDetails[check.x][check.y][check.z].f==FLT_MAX||
单元格详细信息[check.x][check.y][check.z].f>fNew){
PPair cellPair=PPair();
cellPair.cell=PCell(check.x,check.y,check.z);
细胞对f=fNew;
openList.insert(cellPair);
cellDetails[check.x][check.y][check.z].f=fNew;
cellDetails[check.x][check.y][check.z].g=gNew;
cellDetails[check.x][check.y][check.z].h=hNew;
cellDetails[check.x][check.y][check.z].parent_i=i;
cellDetails[check.x][check.y][check.z].parent_j=j;
cellDetails[check.x][check.y][check.z].parent_k=k;
}
}
}
//11其他移动选项
}
内联布尔运算符
由于其F值为3,并且我们已经有一个F值为3(从起点算起为1,0)的选项,因此这两个选项被忽略,即使它们显然是最佳选项
这一定是你的错。这些选项不应被“忽略”,而应“推迟到它们成为下一个最佳选项”。这样做的方式是,在A*的每次迭代中,您应该选择F分数最低的开放单元
在您的示例中,一旦展开0,1
(要获得0,2
和1,1
),打开的集合应该如下所示:
(1,0):3 (1,1):3 (0,2):3
(也可以是这些元素的任何其他排列,因为它们具有相同的分数。)
现在假设它选择访问1,0
。它将2,0
添加到队列中,但1,1
和0,2
仍应存在:
(1,1):3 (0,2):3 (2,0):4.236
因为2,0
的F得分高于1,1
或0,2(1,1):3 (0,2):3 (2,0):4.236