- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我已经开始研究算法和软件开发,作为一个小型 self 评估项目,我决定用 C++ 编写 A* 搜索算法。它在视觉部分使用 Qt 和 OpenGL(但这并不重要)。
主要使用这个来源: A* Pathfinding for Beginners
我写了一个小应用程序,但是我发现了一个我无法修复的错误。似乎由于某种原因,靠近墙的节点的父节点被设置为墙。(?)由于我存储信息的方式,墙的父节点被设置为起点(?)。
我在其中使用了 stateMatrix[][]
1 = entrance green;
2 = exit;
3 = wall and;
4 = path;
我还使用矩阵来表示 openNodes 和 closedNode。 closedNodes 矩阵是 bool 矩阵,openNode 矩阵也存储了一些信息:
openNodes 指令是:
openNodes[100][100][6];
0 - bool open or closed
1 - F
2 - G
3 - H
4 - parentX
5 - parentY
我知道有更好的编码方法,但我还没有上过这节课 ;)
这是 astar 文件的代码:
#include <math.h>
#include "apath.h"
aPath::aPath()
{
gridSize = 100;
int i, j, k;
for(i = 0; i < gridSize; i++)
for(j = 0; j < gridSize; j++)
{
stateMatrix[i][j] = 0;
for(int k = 0; k < 6; k++) openNodes[i][j][k] = 0;
closedNodes[i][j] = 0;
}
targetX = targetY =
openX = openY = entranceX = entranceY = 0;
}
void aPath::start()
{
bool testOK = false;
int G = 0;
openNodes[entranceX][entranceY][0] = 1;
openNodes[entranceX][entranceY][2] = 14;
openNodes[entranceX][entranceY][3] = euclidean(entranceX,
entranceY);
openNodes[entranceX][entranceY][1] =
openNodes[entranceX][entranceY][2] +
openNodes[entranceX][entranceY][3];
openNodes[entranceX][entranceY][4] = entranceX;
openNodes[entranceX][entranceY][5] = entranceY;
int i, j, x, y;
while(closedNodes[targetX][targetY] == 0)
{
searchLessOpen();
closedNodes[openX][openY] = 1;
openNodes[openX][openY][0] = 0;
//Check the 8 squares around
for(i = openX - 1; i <= openX + 1; i++)
for(j = openY - 1; j <= openY + 1; j++)
{
//check if the square is in the limits,
//is not a wall and is not in the closed list
if((i >= 0) && (j >= 0) &&
(i < gridSize) && (j < gridSize) &&
(stateMatrix[i][j] != 3) &&
(closedNodes[i][j] == 0))
{
//G calculus. If it is in the edge it costs more
x = i - openX + 1;
y = j - openY + 1;
if((x == 0 && y == 0) ||
(x == 0 && y == 2) ||
(x == 2 && y == 0) ||
(x == 2 && y == 2))
{
G = 14;
}
else G = 10;
//check if node is already open
if(openNodes[i][j][0] == 0)
{
openNodes[i][j][0] = 1;
openNodes[i][j][2] = G;
openNodes[i][j][3] = euclidean(i,j);
openNodes[i][j][1] = openNodes[i][j][2] + openNodes[i][j][3];
openNodes[i][j][4] = openX;
openNodes[i][j][5] = openY;
}
else //if node is open, check if this path is better
{
if(G < openNodes[i][j][2])
{
openNodes[i][j][2] = G;
openNodes[i][j][1] = openNodes[i][j][2] + openNodes[i][j][3];
openNodes[i][j][4] = openX;
openNodes[i][j][5] = openY;
}
}
}
}
}
reconstruct();
}
void aPath::reconstruct()
{
bool test = false;
int x = openNodes[targetX][targetY][4];
int y = openNodes[targetX][targetY][5];
do
{
stateMatrix[x][y] = 4;
x = openNodes[x][y][4];
y = openNodes[x][y][5];
if(x == entranceX && y == entranceY) test = true;
} while(test == false);
}
int aPath::euclidean(int currentX, int currentY)
{
int dx = targetX - currentX;
int dy = targetY - currentY;
return 10*sqrt((dx*dx)+(dy*dy));
}
void aPath::searchLessOpen()
{
int F = 1000000;
int i, j;
for(i = 0; i < gridSize; i++)
for(j = 0; j < gridSize; j++)
{
if(openNodes[i][j][0] == 1)
{
if(openNodes[i][j][1] <= F)
{
F = openNodes[i][j][1];
openX = i;
openY = j;
}
}
}
}
有人知道我做错了什么吗?
谢谢。编辑:这里有一些图片:
最佳答案
在aPath::start()
,你有:
openNodes[entranceX][entranceY][0] = 1;
openNodes[entranceX][entranceY][2] = 14;
openNodes[entranceX][entranceY][3] = euclidean(entranceX,
entranceY);
openNodes[entranceX][entranceY][3] =
openNodes[entranceX][entranceY][2] +
openNodes[entranceX][entranceY][3];
openNodes[entranceX][entranceY][4] = entranceX;
openNodes[entranceX][entranceY][5] = entranceY;
为什么下标[1]
没有值?还有为什么要给下标[3]
赋两个不同的值?另外,老实说,entranceX
和 entranceY
名字对于他们正在做的工作来说太长了;它们使代码的可读性降低(尽管我确定您被告知要使用有意义的好名称)。对于这些数组索引,我可能只使用 x
和 y
.
在代码处:
//Check the 8 squares around
for(i = openX - 1; i <= openX + 1; i++)
for(j = openY - 1; j <= openY + 1; j++)
{
我可能会确保 i
都不会也不j
使用以下代码接受无效值:
//Check the 8 squares around (openX, openY)
int minX = max(openX - 1, 0);
int maxX = min(openX + 1, gridsize);
int minY = max(openY - 1, 0);
int maxY = min(openY + 1, gridsize);
for (i = minX; i <= maxX; i++)
for (j = minY; j <= maxY; j++)
{
我不确定您是否需要显式检查 i == openX && j == openY
的情况(当前单元格);它不是当前单元格周围的 8 个单元格之一(因为它是当前单元格),但其他条件可能已经处理了它。如果不是:
if (i == openX && j == openY)
continue;
我注意到我们没有 openX
的定义和 openY
或许多其他非局部变量。这使得很难确定它们是类成员变量还是某种全局变量。我们也看不到它们是如何初始化的,也看不到它们代表什么的文档。
在aPath::SearchLessOpen()
,你有:
if(openNodes[i][j][0] == 1)
{
if(openNodes[i][j][6] <= F)
{
F = openNodes[i][j][7];
您在描述中指出 openNodes
上的下标最后一位的范围超过 0..5;但是,您的代码正在访问下标 6 和 7。这很容易导致您描述的那种困惑 - 您正在越界访问数据。我认为这很容易成为您麻烦的根源。当您访问 openNodes[i][j][6]
,这在技术上是未定义的行为,但最有可能的结果是它读取的数据与您编写的 openNodes[i][j+1][0]
相同。 (当 j < gridsize - 1
时)。同样,openNodes[i][j][7]
相当于访问openNodes[i][j+1][1]
, 具有相同的警告。
关于c++ - A* bug(A星搜索算法),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6825347/
我是一名优秀的程序员,十分优秀!