写C++代码将多个类坐标存节点用A星寻路
时间: 2024-01-26 07:05:08 浏览: 72
以下是一个简单的实现方法:
1. 定义节点类
```cpp
class Node {
public:
int x;
int y;
bool walkable; // 是否可行走
Node(int x, int y, bool walkable) {
this->x = x;
this->y = y;
this->walkable = walkable;
}
};
```
2. 定义 A* 寻路算法类
```cpp
class AStarPathFinder {
public:
vector<Node*> findPath(Node* startNode, Node* endNode) {
vector<Node*> path;
// TODO: 实现 A* 寻路算法
return path;
}
};
```
3. 实现 A* 寻路算法
```cpp
vector<Node*> AStarPathFinder::findPath(Node* startNode, Node* endNode) {
vector<Node*> path;
// 定义开放列表和关闭列表
vector<Node*> openList;
vector<Node*> closedList;
// 将起点加入开放列表
openList.push_back(startNode);
while (!openList.empty()) {
// 找到开放列表中 f 值最小的节点
int minF = INT_MAX;
Node* minNode = nullptr;
for (auto& node : openList) {
if (node->f < minF) {
minF = node->f;
minNode = node;
}
}
// 将该节点从开放列表中删除
openList.erase(std::remove(openList.begin(), openList.end(), minNode), openList.end());
// 将该节点加入关闭列表
closedList.push_back(minNode);
// 如果找到终点节点,构造路径并返回
if (minNode == endNode) {
Node* node = minNode;
while (node != startNode) {
path.push_back(node);
node = node->parent;
}
std::reverse(path.begin(), path.end());
return path;
}
// 遍历该节点周围的节点
for (int i = -1; i <= 1; i++) {
for (int j = -1; j <= 1; j++) {
if (i == 0 && j == 0) continue; // 跳过当前节点
int x = minNode->x + i;
int y = minNode->y + j;
if (x < 0 || x >= mapWidth || y < 0 || y >= mapHeight) continue; // 超出地图范围
Node* neighbor = nodes[x][y];
// 跳过不可行走的节点或已经在关闭列表中的节点
if (!neighbor->walkable || std::find(closedList.begin(), closedList.end(), neighbor) != closedList.end()) {
continue;
}
// 计算新的 g 值和 f 值
int newG = minNode->g + ((i == 0 || j == 0) ? 10 : 14); // 横向或竖向移动的节点 g 值增加 10,斜向移动的节点 g 值增加 14
int newH = abs(neighbor->x - endNode->x) + abs(neighbor->y - endNode->y); // 估算到终点的距离
int newF = newG + newH;
// 如果该节点不在开放列表中,将其加入开放列表,并更新 g 值、h 值、f 值和 parent
if (std::find(openList.begin(), openList.end(), neighbor) == openList.end()) {
neighbor->g = newG;
neighbor->h = newH;
neighbor->f = newF;
neighbor->parent = minNode;
openList.push_back(neighbor);
}
// 如果该节点已经在开放列表中,比较新的 g 值和原来的 g 值,如果新的 g 值更小,更新 g 值、h 值、f 值和 parent
else {
if (newG < neighbor->g) {
neighbor->g = newG;
neighbor->h = newH;
neighbor->f = newF;
neighbor->parent = minNode;
}
}
}
}
}
// 如果开放列表为空,表示无法到达终点
return path;
}
```
4. 调用 A* 寻路算法
```cpp
// 假设有一个 10x10 的地图,每个节点大小为 50x50 像素
const int mapWidth = 10;
const int mapHeight = 10;
const int nodeSize = 50;
// 初始化地图节点
vector<vector<Node*>> nodes;
for (int i = 0; i < mapWidth; i++) {
vector<Node*> row;
for (int j = 0; j < mapHeight; j++) {
bool walkable = true; // 假设所有节点都可行走
Node* node = new Node(i, j, walkable);
row.push_back(node);
}
nodes.push_back(row);
}
// 假设起点为 (1, 1),终点为 (8, 8)
Node* startNode = nodes[1][1];
Node* endNode = nodes[8][8];
// 调用 A* 寻路算法
AStarPathFinder pathFinder;
vector<Node*> path = pathFinder.findPath(startNode, endNode);
```
阅读全文