需求
之前做过一个无人车需要自主寻找最佳路径,所以研究了相关的寻路算法,最终选择A算法,因为其简单易懂,是入门级的寻路算法。
但是在验证的算法的时候,没有直观的感受,总是觉得会有什么问题,所以我就写了一个可视化的A算法验证,界面基于Qt开发。
项目说明
本项目主要分为2个部分,Qt绘制网格和A算法实现。下面可以看到,界面的实现和A算法的实现基本上是分离的。也就是说可以单独使用,比如Qt网格绘制,可以用于扫雷游戏,A*算法的代码可以直接拷贝,稍作修改就可以直接用于游戏,或者无人车。
效果
操作说明
鼠标右键:设置障碍物;鼠标左键:设置起点和终点。
项目文件截图
项目实现
程序的实现流程:定义一个最小网格类->通过鼠标设置起点、终点和障碍物,并实时绘制->寻找路径->绘制路径。
定义最小网格类
首先,我们需要定义一个最小网格类,用于绘制网格地图(GridMap)。
网格地图是将二维场景中的地图划分为一个个小网格,这个小网格是最小的空间单位,我们可以设置该网格为障碍物、起点或终点。
下面是最小网格类。
class Item
{
public:
Item();
Item(QPoint pos);
QPoint m_pos; //position
bool m_bIsObstacle; //whether is obstacle
int m_nObjectType; //the object type , Nothing,Robot or goal
};
可以看出最小网格对象很简单,只需要一个位置信息,障碍物标志位,机器人或目标点标志。以上就是最小网格的全部属性,当然如果想要实现更加复杂的功能,可以添加属性。
初始化地图
初始化地图是指将2维地图划分为网格的过程,其实就是new Item的过程。
void MainWindow::InitItems()
{
for(int i=0; i<m_nColumes; i++)
{
QVector<Item*> rowItems;
for(int j=0; j<m_nRows; j++)
{
QPoint pos = QPoint(i,j);
Item* pItem = new Item(pos);
rowItems.append(pItem);
}
m_items.append(rowItems);
}
}
其中m_nColumes和m_nRows是在初始化地图之前设置的长宽。
设置障碍物
在寻路之前,我们要先设置好障碍物、起点和终点。设置障碍物用鼠标右键,单击右键,设置小网格为障碍物,再次单击取消障碍物;设置起点和终点用鼠标左键,单击左键1次,设置小网格为起点,再次单击为终点,再次单击为空白,依次循环。
这里我们用鼠标事件实现,可以看到其实就是根据鼠标事件来设置相应位置Item对象的属性。代码很简单。在设置起点和终点是需要特别标记,因为如果地图中没有标定起点和终点,就无法寻路了。
void MainWindow::mousePressEvent(QMouseEvent * e)
{
//得到鼠标处的格子坐标
QPoint pt;
pt.setX( (e->pos().x() - START_X ) / RECT_WIDTH);
pt.setY( (e->pos().y() - START_X