您的位置:首页 > 编程语言 > C语言/C++

A star 寻路算法实现(C++版本)

2013-10-12 22:23 567 查看
rpg游戏中的寻路算法,写出来测试了一下,A*算法的理论我就不讲了

下面直接是代码,在centos 6.2 上编译测试,其他平台应该也没有问题。

---------------------------------------------Astar.h-----------------------------------------------------------

#include <stdlib.h>

#include <list>

//移动坐标

class MoveCoord

{

public:

    MoveCoord(int grid_x=-1, int grid_y=-1);

    MoveCoord& operator+(const MoveCoord& coord);

    MoveCoord& operator+=(const MoveCoord& coord);

    bool operator==(const MoveCoord coord);

    bool operator!=(const MoveCoord& coord);

    MoveCoord& operator=(const MoveCoord& coord);

public:

    int grid_x;//格子坐标x

    int grid_y;//格子坐标y

};

//寻路坐标

class PathCoord

{

public:

    PathCoord(void);

    PathCoord(MoveCoord parent,MoveCoord cur);

    virtual ~PathCoord();

    int get_f(void) const;

    MoveCoord parent;//父坐标

    MoveCoord cur;//当前坐标

    int g_value;//起点到该点的G值

    int h_value;//该点到目标点都f值

};

typedef std::list<MoveCoord> CoordList;

typedef bool (*IsMovableCoord)(int scene_id,int coord_x,int coord_y);

class AStar

{

public:

    AStar(void){};

    virtual ~AStar(void){};

    

    /* 在场景scene_id中寻找从src 到 dst的路径,找到之后保存再coord_list中,返回true。否则返回false

     * 参数 IsMovableCoord:判断坐标是否可走的函数,可走返回true,否则返回false

     */

    static bool FindPath(const int scene_id,MoveCoord src,MoveCoord dst,IsMovableCoord is_movable,CoordList& coord_list);

};

#endif

---------------------------------------------Astar.cpp-----------------------------------------------------------

#include <queue>

#include <map>

#include "AStar.h"

MoveCoord::MoveCoord(int grid_x, int grid_y)

{

    this->grid_x = grid_x;

    this->grid_y = grid_y;

}

MoveCoord& MoveCoord::operator+(const MoveCoord& coord)

{

    this->grid_x +=coord.grid_x;

    this->grid_y +=coord.grid_y;

    return *this;

}

MoveCoord& MoveCoord::operator+=(const MoveCoord& coord)

{

    *this = *this + coord;

    return *this;

}

bool MoveCoord::operator==(const MoveCoord coord)

{

    return (this->grid_x==coord.grid_x

        && this->grid_y==coord.grid_y);

}

bool MoveCoord::operator!=(const MoveCoord& coord)

{

    return !(*this==coord);

}

MoveCoord& MoveCoord::operator=(const MoveCoord& coord)

{

    this->grid_x =coord.grid_x;

    this->grid_y =coord.grid_y;

    return *this;

}

PathCoord::PathCoord(void)

{

}

PathCoord::~PathCoord()

{

}

PathCoord::PathCoord(MoveCoord parent,MoveCoord cur)

{

    this->parent = parent;

    this->cur = cur;

    this->g_value = 0;

    this->h_value = 0;

}

int PathCoord::get_f(void) const

{

    return this->g_value + this->h_value;

}

//src ,dst 必须是相邻的格子

int cal_g(const MoveCoord src,const MoveCoord dst)

{

    int cur = 14;

    if(src.grid_x== dst.grid_x

            || src.grid_y == dst.grid_y)

    {

        cur = 10;

    }

    return cur;

}

/*manhattan 计算从当前方格横向或纵向移动到达目标所经过的方格数

忽略对角移动,然后把总数乘以 10*/

int cal_h(const MoveCoord src,const MoveCoord dst)

{

    int dx = abs(src.grid_x-dst.grid_x);

    int dy = abs(src.grid_y-dst.grid_y);

    return (dx+dy)*10;

}

// std::map 会根据key排序,因此定义自己的排序函数

bool operator<(const MoveCoord& lhs,const MoveCoord& rhs)

{

    if(lhs.grid_x < rhs.grid_x)

    {

        return true;

    }

    else if(lhs.grid_x == rhs.grid_x)

    {

        if(lhs.grid_y < rhs.grid_y)

        {

            return true;

        }

    }

    return false;

}

//定义 typedef std::map<MoveCoord,PathCoord,less> CoordMap;key为MoveCoord,自定义key的比较函数

struct less

{

    bool operator()(const MoveCoord& lhs,const MoveCoord& rhs) const

    {

        if(lhs.grid_x < rhs.grid_x)

        {

            return true;

        }

        else if(lhs.grid_x == rhs.grid_x)

        {

            if(lhs.grid_y < rhs.grid_y)

            {

                return true;

            }

        }

        return false;

    }

};

// 最小堆排序(比较F值)

bool operator<(const PathCoord& lhs,const PathCoord& rhs)

{

    return lhs.get_f() > rhs.get_f();

}

typedef std::map<MoveCoord,PathCoord,less> CoordMap;

typedef std::priority_queue<PathCoord> CoordHeap;

/* 在场景scene_id中寻找从src 到 dst的路径,找到之后保存再coord_list中

 * 返回true。否则返回false

*/

bool AStar::FindPath(const int scene_id,MoveCoord src,MoveCoord dst,

                     IsMovableCoord is_movable,CoordList& coord_list)

{

    if( src == dst)

    {

        return false;

    }

    

    coord_list.clear();

    //九宫格数组

    int coord_arr[9][2]={

        {0,0},

        {-1,1},{0,1},{1,1},

        {-1,0},{1,0},

        {-1,-1},{0,-1},{1,-1},

    };

    CoordHeap uncheck_coord_heap;

    CoordMap checked_map;

    CoordMap uncheck_map;

    PathCoord cur_path_coord(MoveCoord(-1,-1),src);

    uncheck_coord_heap.push(cur_path_coord);

    while(uncheck_coord_heap.empty()==false)

    {

        PathCoord cur_path_coord = uncheck_coord_heap.top();

        uncheck_coord_heap.pop();

        uncheck_map.erase(cur_path_coord.cur);

        checked_map[cur_path_coord.cur]= cur_path_coord;

        if(cur_path_coord.cur==dst)//到达目标点

        {

            while(cur_path_coord.parent!=MoveCoord(-1,-1))

            {

                coord_list.push_front(cur_path_coord.cur);

                cur_path_coord = checked_map[cur_path_coord.parent];

            }

            return true;

        }

        for (int i = 1; i <=8; i++)

        {

            MoveCoord cur_check = cur_path_coord.cur;

            cur_check += MoveCoord(coord_arr[i][0],coord_arr[i][1]);

            if(cur_check.grid_x<0 || cur_check.grid_y<0)

            {

                continue;

            }

            if(is_movable(scene_id,cur_check.grid_x,cur_check.grid_y)==false)

            {

                continue;

            }

            

            CoordMap::iterator iter1 = checked_map.find(cur_check);

            if (iter1 != checked_map.end())

            {

                continue;

            }

            CoordMap::iterator iter2 = uncheck_map.find(cur_check);

            int tmp_g = cal_g(cur_path_coord.cur,cur_check)+cur_path_coord.g_value;

            if(iter2==uncheck_map.end())

            {

                PathCoord path_coord(cur_path_coord.cur,cur_check);

                path_coord.g_value = tmp_g;

                path_coord.h_value = cal_h(cur_check,dst);

                uncheck_coord_heap.push(path_coord);

                uncheck_map[cur_check]=path_coord;

            }

            else

            {

                PathCoord &path = iter2->second;

                if (path.g_value > tmp_g)

                {

                    path.parent = cur_path_coord.cur;

                    path.g_value = tmp_g;

                    uncheck_coord_heap.push(path);

                }

            }

        }

    }

    return false;

}

----------------------------------------------main.cpp------------------------------------------------------------------------------

#include "AStar.h"

#include <tchar.h>

#include <iostream>

//假设下面是一张小地图

/*

 y ----------------------------------------------------------------------------------

 * |(0,9)  | (1,9)  | (2,9) | (3,9) | (4,9) | (5,9)  | (6,9) | (7,9) | (8,9) | (9,9) |

 * |-------|--------|-------|-------|-------|--------|-------|-------|-------|-------|

 * |(0,8)  | (1,8)  | (2,8) | (3,8) | (4,8) | (5,8)  | (6,8) | (7,8) | (8,8) | (9,8) |

 * |-------|--------|-------|-------|-------|--------|-------|-------|-------|-------|

 * |(0,7)  | (1,7)  | (2,7) | (3,7) | (4,7) | (5,7)  | (6,7) | (7,7) | (8,7) | (9,7) |

 * |-------|--------|-------|-------|-------|--------|-------|-------|-------|-------|

 * |(0,6)  | (1,6)  | (2,6) | (3,6) | (4,6) | (5,6)  | (6,6) | (7,6) | (8,6) | (9,6) |

 * |-------|--------|-------|-------|-------|--------|-------|-------|-------|-------|

 * |(0,5)  | (1,5)  | (2,5) | (3,5) | (4,5) | (5,5)  | (6,5) | (7,5) | (8,5) | (9,5) |

 * |-------|--------|-------|-------|-------|--------|-------|-------|-------|-------|

 * |(0,4)  | (1,4)  | (2,4) | (3,4) | (4,4) | (5,4)  | (6,4) | (7,4) | (8,4) | (9,4) |

 * |-------|--------|-------|-------|-------|--------|-------|-------|-------|-------|

 * |(0,3)  | (1,3)  | (2,3) | (3,3) | (4,3) | (5,3)  | (6,3) | (7,3) | (8,3) | (9,3) |

 * |-------|--------|-------|-------|-------|--------|-------|-------|-------|-------|

 * |(0,2)  | (1,2)  | (2,2) | (3,2) | (4,2) | (5,2)  | (6,2) | (7,2) | (8,2) | (9,2) |

 * |-------|--------|-------|-------|-------|--------|-------|-------|-------|-------|

 * |(0,1)  | (1,1)  | (2,1) | (3,1) | (4,1) | (5,1)  | (6,1) | (7,1) | (8,1) | (9,1) |

 * |-------|--------|-------|-------|-------|--------|-------|-------|-------|-------|

 * |(0,0)  | (1,0)  | (2,0) | (3,0) | (4,0) | (5,0)  | (6,0) | (7,0) | (8,0) | (9,0) |

 0 ----------------------------------------------------------------------------------> x

 */

bool MovableCoord(int scene_id,int x,int y)

{

    MoveCoord coord(x,y);

    //指定不可走点

    if(coord == MoveCoord(-1,-1)

        || coord == MoveCoord(5,4)

        || coord == MoveCoord(0,2)

        || coord == MoveCoord(1,2)

        || coord == MoveCoord(2,2)

        || coord == MoveCoord(3,2)

        || coord == MoveCoord(4,2)

        || coord == MoveCoord(5,2)

        || coord == MoveCoord(6,2)

        || coord == MoveCoord(7,2)

        || coord == MoveCoord(8,2))

        //|| coord == MoveCoord(1,8)

        //|| coord == MoveCoord(2,8)

        //|| coord == MoveCoord(3,8)

        //|| coord == MoveCoord(4,8))

    {

        return false;

    }

    return true;

}

int main(int argc, char* argv[])

{

    MoveCoord src(5,1);

    MoveCoord dst(5,5);

    

    CoordList path_list;

    if(AStar::FindPath(0,src,dst,MovableCoord,path_list))

    {

        CoordList::iterator iter = path_list.begin();

        for(;iter!= path_list.end();iter++)

        {

            std::cout<<"coord: " << iter->grid_x << " " << iter->grid_y << std::endl;

        }

    }

    return 0;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: