Stuck /一般帮助在2D网格上开发A *

时间:2018-03-15 15:55:52

标签: c++ path-finding a-star

我认为我已接近完成A *的实施,但我的思绪正在变得油腻,我正在寻找关于我应该做些什么来完成它的指示。

我当前的问题是,我在A *中运行的函数仍然停留在同一节点上,因为当前节点永远不会进入任何其他开放节点。

这是我的主要功能,请注意,启发式(Node& n1,Node& n2)功能当前设置为始终返回0,因此它当前应该更像Dijkstra算法而不是A *。此外,移动仅限于NESW平面,没有对角移动,因此distance_between(Node& n1,Node& n2)始终返回1.

void astar(Node start_, Node end_) {

    Node start = start_;
    Node end = end_;

    // compute f,g,h for the start node
    start.g = 0;
    start.h = heuristic(start, end);
    start.f = start.g + start.h;

    // insert start node into the open set
    openNodes.insert(&start);

    // while the set of open nodes is not empty
    while (openNodes.size() > 0) {

        // pick the most promising node to look at next
        Node currentNode;

        cout << "currentNode before: ";
        currentNode.displaylocation();

        // go through all the open nodes and find the one with the smallest 'f' value
        Node* minf = (*openNodes.begin()); // set initial value for minimum f to be the first node in the set of open nodes

        for (auto n : openNodes) {
            if (n->f <= minf->f) {
                minf = n;
            }
        }
        currentNode = *minf; // set the current node to the node that holds the smallest 'f' value

        cout << "currentNode after: ";
        currentNode.displaylocation();

        // if the current node is the end node, then we have found a path
        if (currentNode.type == -3) {
            break;
        }

        // remove the current node from the set of open nodes, and add it to the set of closed nodes
        openNodes.erase(&currentNode);
        closedNodes.insert(&currentNode);

        // go through the currents node's neighbours
        for (auto n : neighbours(currentNode)) {
            cout << "neighbour local: " << n.location.x << "," << n.location.y << "\n";

            if (closedNodes.count(&n) == 0 && n.type != -2) { // if this node is neither closed or a blocker
                int new_g = currentNode.g + distance_between(currentNode, n);

                if (openNodes.count(&n) != 0) { // if we have not seen this node before, add to the open set
                    openNodes.insert(&n);
                }
                else if (new_g >= n.g) { // else if we have seen this node before, and already found a shorter path to it from the starting node

                }
                n.g = new_g;
                n.f = n.g + heuristic(n, end);
                n.parent_ = &currentNode;
            }
        }

        cout << "\n A* run success! \n";
        //break;
    }
}

这是Node结构和全局变量之类的减速:

// The size of the grid
#define WIDTH 6
#define HEIGHT 6

// Holds values for x and y locations on the grid
struct Coord {
    int x, y;
};

// holds data for each node required for A*
struct Node {
    int type; // used for defining if this node is a blocker, empty, start or end
    Coord location;
    int g = 0;
    int h = 0;
    int f = g + h;
    Node *parent_; // pointer to this node's parent

    std::string debugmessage;

    void displaylocation() {
        std::cout << "I am the node at: " << location.x << "," << location.y << "\n";
    }
};

// The 2D grid array for A*, requiring a Node struct to store the data of each cell
Node astarArray[WIDTH][HEIGHT];

// Sets for A*
std::set<Node *> openNodes; // contains the nodes that are yet to be considered (if this is empty, then there are no more paths to consider or there is no path)
std::set<Node *> closedNodes; // contains the nodes that have already been considered (if the end node is placed in here, a path has been found)    

// stores the start and end values for A*
Node start_A, end_A;

void astar(Node start_, Node end_);
int distance_between(Node& n1, Node& n2);
int heuristic(Node& n1, Node& n2);
std::list<Node> neighbours(Node& n_);


// returns the distance between two nodes for A*
int distance_between(Node& n1, Node& n2) {
    return 1; // always return 1 as we are working in a grid restricted to NSEW movement
}


int heuristic(Node& n1, Node& n2) {
    return 0; // return 0 to work as a Dijkstra algorithm rather than A*
}


// finds a node's neighbours for A*
std::list<Node> neighbours(Node& n_) {

    std::list<Node> neighbours_;

    int x = n_.location.x;
    int y = n_.location.y;
    // start at the location belonging to 'n_'
    //for (int y = n_.location.y; y < HEIGHT; y++) {
        //for (int x = n_.location.x; x < WIDTH; x++) {

            // east
            if (x < WIDTH - 1) {
                neighbours_.push_back(astarArray[x + 1][y]);
            }
            // west
            if (x > 0) {
                neighbours_.push_back(astarArray[x - 1][y]);
            }
            // south
            if (y < HEIGHT - 1) {
                neighbours_.push_back(astarArray[x][y + 1]);
            }
            // north
            if (y > 0) {
                neighbours_.push_back(astarArray[x][y -1]);
            }
        //}
    //}

    return neighbours_;
}

非常感谢您的阅读和任何帮助。如果需要,我会提供更多代码。

1 个答案:

答案 0 :(得分:0)

您遇到的主要问题是您正在使用指针(mem地址)来确定节点是否在您的集合中。

currentNode = *minf; // set the current node to the node that holds the smallest 'f' value

然后将minf的内容复制到currentNode。 currentNode将具有与指向minf的指针不同的地址

openNodes.erase(&currentNode);不会删除minf,因为currentNode没有相同的地址。

  • 我建议您进一步研究如何实施A *,因为您缺少一些步骤。寻找优先级队列
  • 使用网格(pos.x * numCols) + pos.y
  • 中该节点的位置索引,而不是节点的mem地址