Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ A星搜索算法赢得';找不到有效的路径_C++_Algorithm_Path Finding_A Star - Fatal编程技术网

C++ A星搜索算法赢得';找不到有效的路径

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开始计算两个开平方,分

我正在尝试在我的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来存储我的封闭列表,但我认为这与问题无关。关于这些结构是什么,这里有一个简单而肮脏的例子:

  • PCell
    :保存单元格坐标
  • PPair
    :将单元格坐标保存为PCell和F值
  • FVectorInt
    :三维整数向量
  • FPathCell
    :保存父坐标以及f、g和h值
  • cellDetails
    FPathCell
  • closedMap
    是一个TMap,其
另外,
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