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

/**
 * 寻径算法框架
 * 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;
}
		







  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值