写在前面

障碍物在算法环境中是不可缺少的,可以看成是算法的约束条件。那么如何生成不重复的随机障碍点呢?接下来我就主要介绍这个办法,以及如何利用C++将坐标点数据在不同功能函数之间高效率传递。

结果展示

绿色:已搜索(待遍历)节点;
浅灰色:搜索过程中的最小F数值点;
红色:起点;
绿色:终点;
黄色:最终的生成路径;
黑色:障碍物(不可走坐标);

随机障碍物

我的思路是将地图上所有的坐标点都塞进一个vector里面,然后将这个vector乱序化,最终取vector前面的坐标点做为障碍物,这样可以保证取出的障碍点是无序且不重复的,C++实现如下图所示:


void Graph::set_obstacles_start_end()
{

    for (int i = 0; i <= graph_user_para.map_x; i++) {
        for (int j = 0; j <= graph_user_para.map_y; j++) {
            Point* obstacle = new Point(i, j);
            if (*obstacle != start && *obstacle != end) {
                obstacle_vector.push_back(obstacle);
            }
            else { delete obstacle; }
        }
    }

    std::random_device rd;
    std::mt19937 g(rd());
    std::shuffle(obstacle_vector.begin(), obstacle_vector.end(), rd);

    for (int i = 0; i < graph_user_para.obstacle_num; i++) {
        obstacle.push_back(obstacle_vector[0]);
        obstacle_vector.erase(obstacle_vector.begin());
    }

}

可以看到在第一个二重循环里面是在堆里面申请Point的内存,然后返回指向内存的指针,并且将指针塞进obstacle_vector里面,将所有坐标点(起点,终点除外)都申请了内存之后就得到了指向内存的指针的完整的obstacle_vector了。如果遇到了起点(start)或者终点(end),我们需要回收堆里面申请的内存,这点不能忘记了。

之后将obstacle_vector进行打乱顺序,写法如上所示,简单3句语句即可。打乱之后的操作就是按照顺序取出obstacle_vector中特定数量的内存指针放到obstacle里面去,将其做为最终的障碍点坐标集合。

std::vector<Point*> Graph::get_obstacle()
{
    return obstacle;
}

既然在算法开始之前申请了堆内的内存,那么在类的析构函数就需要回收申请的内存,避免内存溢出,养成良好习惯,从当下开始。

Graph::~Graph()
{
    for (int i = 0; i < obstacle_vector.size(); i++) {
        delete obstacle_vector[i];
        obstacle_vector.erase(obstacle_vector.begin());
    }


    for (int i = 0; i < obstacle.size(); i++) {
        obstacle.erase(obstacle.begin());
    }
}

坐标点传递

我在Graph里面生成障碍点的坐标,然后在A_star类里面进行算法的实现,所以就需要将Graph里面的障碍点坐标传到A_star类的函数里面去,那么这个是如何实现的呢?

我是将Graph类的obstacle直接传到了A_star类里面,因为obstacle里面存放的是指针,所以传递起来比较方便的,又因为是指针,所以要用的时候直接索引obstacle的里的指针就可以得到堆内的内存,也就是点的坐标。

void A_star::set_start_end_obs_map(Graph& user_graph)
{
    start = user_graph.get_start();
    end = user_graph.get_end();
    obstacleset = user_graph.get_obstacle();
    user_trajectory = user_graph.get_userPara();

    for (int i = 0; i <= user_trajectory.map_x; i++) {
        for (int j = 0; j <= user_trajectory.map_y; j++) {
            user_trajectory.map[i][j] = PATH;
        }
    }

    user_trajectory.map[start.x][start.y] = START;
    user_trajectory.map[end.x][end.y] = END;

    start.Gn = 0;
    start.Fn = start.Gn + calcu_Hn(start);

    for (int i = 0; i < obstacleset.size(); i++) {
        user_trajectory.map[obstacleset[i]->x][obstacleset[i]->y] = OBSTACLE;
    }

}