您的位置:首页 > 其它

自己实现的一个寻径算法的框架,具体算法采用动态库模式,可以非常方便灵活地尝试多种寻径算法

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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐