自己实现的一个寻径算法的框架,具体算法采用动态库模式,可以非常方便灵活地尝试多种寻径算法
2011-09-09 19:22
926 查看
/** * 寻径算法框架 * by lxslove * e-mail:moodlxs@163.com * 用法: * 注意:编译本框架需要加上-ldl选项 * g++ -ldl src.cpp * * 地图文件格式为不同符号的矩阵,具体什么符号代表可通行,什么符号代表不可通行,由自己决定。举个例子: * ################### * # ###### ######## * # ###### ########## * # ########## * ######## # #### * ## #### ## ###### * ### # ######### ## * ###### ##### # # ## * #### # ##### ###### * ###### ####### * ################### * 以上的例子,假设空格是可通行的,#是不可通行的。 * * 具体的算法采用插件的形式,插件(so文件)需要提供find_path函数接口,该函数的形式为: * extern "C" * int find_path(size_t start_pos, size_t end_pos, vector<char>* map_data, vector<char>* path_list) * { * return 0; //成功则返回0 * } * 编译so文件的方式例子如下: * g++ -fPIC -shared -o 1.so 1.cpp 1.h * * start_pos/end_pos为地图数据在map_data中的位置,path_list暂时没用到 * 在得到路径时,需要在find_path接口方法中修改map_data的符号,标志其为路径,具体修改为什么符号由自己决定,举个例子: * ################### * #@######@ ######## * #@######@########## * #@@@@@@@@########## * ######## # #### * ## #### ## ###### * ### # ######### ## * ###### ##### # # ## * #### # ##### ###### * ###### ####### * ################### * 以上例子中,将相应位置的符号修改为@ * 框架会直接显示地图数据,是什么符号就显示什么符号。 * */ #define DL cout #include <stdio.h> #include <string.h> #include <libgen.h> #include <dlfcn.h> #include <sys/time.h> #include <string> #include <fstream> #include <iostream> #include <vector> using namespace std; /// 插件接口 // 参数为: // 开始位置,结束位置,地图数据列表, 路径列表,暂时不用,固定为NULL typedef int (*pfunc)(size_t, size_t, vector<char>*, vector<char>*); const char* const FUNC_NAME = "find_path"; class XJFrame { private: string m_map_path; /// 地图位置 pfunc p_func; /// 插件的接口函数 vector<char> m_map_data; /// 地图数据指针 vector<size_t>* m_p_path_data; /// 路径数据指针 size_t m_map_width; /// 地图宽度 size_t m_map_heigh; /// 地图高度 void * m_p_module; /// 模块指针 struct timeval m_use_time; /// 算法耗时 public: size_t get_map_width() { return m_map_width; } size_t get_map_heigh() { return m_map_heigh; } const struct timeval* get_use_time() { return &m_use_time; } private: XJFrame(const XJFrame& rv); XJFrame& operator=(const XJFrame& rv); public: XJFrame() :m_map_width(0), m_map_heigh(0), m_p_module(NULL), m_p_path_data(NULL) { } XJFrame(const string& map_path) :m_map_path(map_path), m_map_width(0), m_map_heigh(0), m_p_module(NULL), m_p_path_data(NULL) { } ~XJFrame() { if (m_p_module) { dlclose(m_p_module); m_p_module = NULL; } if (m_p_path_data) { delete m_p_path_data; m_p_path_data = NULL; } } void set_map_path(const string & map_path) { m_map_path = map_path; } int open_module(const string & module_path) { if (module_path.empty()) { DL << "module_path not setting!\n"; return -1; } if (m_p_module) { dlclose(m_p_module); m_p_module = NULL; } void* m_p_module = dlopen(module_path.c_str(), RTLD_LAZY ); if( !m_p_module ) { DL << "can't open module: " << module_path <<", error:" << dlerror() << "\n"; return -1; } p_func = (pfunc)dlsym(m_p_module, FUNC_NAME); const char *dlsym_error = dlerror(); if (dlsym_error) { DL << "load symbol: " << FUNC_NAME << "! err: " << dlsym_error << "\n"; return -1; } return 0; } int init_map() { if (m_map_path.empty()) { DL << "map_path not setting!\n"; return -1; } m_map_data.clear(); ifstream in_file(m_map_path.c_str()); if (!in_file) { DL << "open file error:" << m_map_path << "\n"; return -1; } size_t len; char buffer[1024]; while (!in_file.eof()) { in_file.getline(buffer, sizeof(buffer)); len = strlen(buffer); if (len == 0) { break; } //根据第一次的宽度计算地图宽度 if (!m_map_width) { m_map_width = len; } else if (m_map_width != len) { DL << "map format error!0\n"; return -1; } //计算地图高度 ++m_map_heigh; //读取地图信息 for (size_t i = 0; i < len; ++i) { if ((*(buffer + i)) != ' ' && (*(buffer + i)) != '#') { DL << "map format error!2\n"; return -1; } else { m_map_data.push_back(*(buffer + i)); } } } in_file.close(); return 0; } void display_map() { if (m_map_data.empty()) { DL << "Please load map before!" << endl; return ; } DL << "Map Info: width:" << m_map_width << ", heigh:" << m_map_heigh << endl; for (int i = 0; i < m_map_data.size(); ++i) { DL << m_map_data[i]; if ((i + 1) % m_map_width == 0) { DL << "\n"; } } } int find_path(size_t start_pos, size_t end_pos) { if (m_map_data.empty()) { DL << "Please load map before!" << endl; return -1; } struct timeval tvs, tve; gettimeofday(&tvs, NULL); int ret = p_func(start_pos, end_pos, &m_map_data, NULL); gettimeofday(&tve, NULL); if (tve.tv_usec < tvs.tv_usec) { --tve.tv_sec; tve.tv_usec+=1000; } m_use_time.tv_sec = tve.tv_sec - tvs.tv_sec; m_use_time.tv_usec = tve.tv_usec - tvs.tv_usec; } }; int main(int argc, char** argv) { XJFrame xjframe; int user_select; bool is_exit = false; if (argc == 3) { xjframe.set_map_path(argv[1]); xjframe.init_map(); xjframe.open_module(argv[2]); xjframe.display_map(); } do { cout << "MENU:\nSetMap(1)\tSetModule(2)\tDisplayMap(3)\tFindPath(4)\tExit(0)" << endl; cout << "Input:" << flush; while (!(cin >> user_select)) { cout <<"Input error, retry:"<< flush; cin.clear(); cin.ignore(10000,'\n'); } string str; int ret; switch (user_select) { case 1: cout << "Your Map Path:"; cin >> str; xjframe.set_map_path(str); ret = xjframe.init_map(); if (ret != 0) { cout << "Set Map Error" << endl; } else { cout << "Set Map Success" << endl; } break; case 2: cout << "Your Module Path:"; cin >> str; ret = xjframe.open_module(str); if (ret != 0) { cout << "Set Module Error" << endl; } else { cout << "Set Module Success" << endl; } break; case 3: xjframe.display_map(); break; case 4: cout << "Enter the start position and end position,format:x y x y"; { int sx,sy,ex,ey; if (!(cin >> sx >> sy >> ex >> ey)) { cout << "Input Error!" << endl; break; } else { int start_pos = sy * xjframe.get_map_width() + sx; int end_pos = ey * xjframe.get_map_width() + ex; ret = xjframe.find_path(start_pos, end_pos); if (ret != 0) { cout << "can not find any path!" << endl; } else { cout << "path find!" << endl; xjframe.display_map(); } cout << "Use Time:" << xjframe.get_use_time()->tv_sec << " second " << xjframe.get_use_time()->tv_usec << " microsecond" << endl; } } break; case 0: is_exit = true; break; default: break; } cin.clear(); cin.ignore(10000,'\n'); }while (!is_exit); cout << "byebye" << endl; return 0; }
相关文章推荐
- 自己实现的一个寻径算法的框架,具体算法采用动态库模式,可以非常方便灵活地尝试多种寻径算法
- 写一个算法,使对象可以像数组一样进行foreach循环,要求属性必须是私有的(Interator模式的PHP5实现,写一类实现Interator接口)
- 配合.NET MVC 写自己的框架,实现动态配置页面数据源及方便可扩展性
- 群上出的一个算法题,上我的解,大家可以用自己会的语言实现一下哦,我用的php
- 一个非常方便的在线工具可以用来可见化调节混合模式工具
- 一个非常方便的在线工具可以用来可见化调节混合模式工具
- 一个自己开发的简单,快速,方便,小巧的php web框架
- 教材上关于模式匹配中的求next数组的算法不易理解,本人自己编写了一个具有相同功能的子函数
- 渣渣用JavaScript开发的消消乐,由于没有按照正规消消乐形式生成,是随机产生图形,所以存在一个算法bug,具体看下面,高手想到可以告诉我
- XP中java swing 在中文输入的时候总有一个输入窗口,非常难看,可以采用此种方法处理
- iOS开发UIScrollView的底层实现-你也可以自己实现一个scrollView
- android两种方式中自己画一个圆,实现单点触控时拖动图片,跟着拖动点走,并且可以放大或缩小
- 一个自己实现的rpc框架
- 创建一个CPoint类,代表平面直角坐标系中的点,创建构造函数和运算符重载函数, 运算符重载为类重载(非友元重载),可以实现计算两个点之间的距离。可以根据需要 加入自己的成员变量或成员函数
- 扔掉log4j、log4j2,自己动手实现一个多功能日志记录框架,包含文件,数据库日志写入,实测5W+/秒日志文件写入,2W+/秒数据库日志写入,虽然它现在还没有logback那么强大
- 如何才能学到Qt的精髓(信号槽之间的无关性),QT的GUI全是自己的一套,并且完全开源,提供了一个绝好机会窥视gui具体实现
- (4.6.22.1)来吧,是时候撸一份自己的RxJava框架啦:观察者模式实现链式调用
- 提供自己写的一个类,用MFC可以方便设置窗口全屏显示 - Gods_巨蚁
- 一个查重算法的多种实现思路
- (4.6.22.2)来吧,是时候撸一份自己的RxJava框架啦:代理模式实现线程调度