// #include "stdafx.h" #include <stdio.h> #include <Winsock2.h> #pragma comment (lib, "ws2_32") #include <thread> #include "tinyxml.h" #include <string> #include <vector> #include <iostream> #define UDP class DataStruct { public: int startx; int starty; int endx; int endy; }; class CCPoint { public: CCPoint(){}; CCPoint(float x, float y) : x(x), y(y) { } int x; int y; }; struct CCSize { int width; int height; }; struct MapXML { std::string m_data; CCSize m_size; }; class PathSprite { public: PathSprite():m_parent(NULL), m_child(NULL), m_costToSource(0), m_FValue(0), m_startX(0), m_startY(0), m_endX(0), m_endY(0) { }; public: PathSprite* m_parent;//父节点 PathSprite* m_child;//子节点 float m_costToSource;//到起始点的距离 int m_x;//地图坐标 int m_y; float m_FValue; int m_startX;//开始点 int m_startY; int m_endX;//结束点 int m_endY; }; class PathSearchInfo { public: PathSearchInfo(CCSize size, std::vector< std::vector<PathSprite*>> inspectArray):m_mapSize(size),m_inspectArray(inspectArray){}; ~PathSearchInfo(){}; CCSize m_mapSize; std::vector< std::vector<PathSprite*>> m_inspectArray; std::vector<CCPoint> m_pathList;//路径列表 std::vector<PathSprite*> m_haveInspectList;//检测过的列表 std::vector<PathSprite*> m_openList;//开放列表(里面存放相邻节点) std::function<void(const char* , int , int)> sendData; void calculatePath(int startX, int startY, int endX, int endY)//计算路径 { clearPath(); #ifndef NOMAL_SEARCH_PATH //得到开始点的节点 PathSprite* _endNode= m_inspectArray[startX][startY]; //得到结束点的节点 PathSprite* _startNode = m_inspectArray[endX][endY]; //因为是开始点 把到起始点的距离设为0, F值也为0 _startNode->m_costToSource = 0; _startNode->m_FValue = 0; //把已经检测过的点从检测列表中删除 m_inspectArray[endX][endY] = NULL; //把该点放入已经检测过点的列表中 m_haveInspectList.push_back(_startNode); //然后加入开放列表 m_openList.push_back(_startNode); PathSprite* _node = NULL; while (true) { //得到离起始点最近的点(如果是第一次执行, 得到的是起点) _node = getMinPathFormOpenList(); if (!_node) { //不到路径 break; } //把计算过的点从开放列表中删除 removeObjFromOpenList( _node); int _x = _node->m_x; int _y = _node->m_y; // if (_x ==startX && _y == startY) { break; } //检测8个方向的相邻节点是否可以放入开放列表中 PathSprite* _adjacent = NULL; _adjacent = getObjFromInspectArray( _x +1, _y); inspectTheAdjacentNodes(_node, _adjacent, _endNode); _adjacent = getObjFromInspectArray( _x , _y -1); inspectTheAdjacentNodes(_node, _adjacent, _endNode); _adjacent = getObjFromInspectArray( _x -1, _y); inspectTheAdjacentNodes(_node, _adjacent, _endNode); _adjacent = getObjFromInspectArray( _x , _y+1); inspectTheAdjacentNodes(_node, _adjacent, _endNode); _adjacent = getObjFromInspectArray( _x + 1, _y + 1); inspectTheAdjacentNodes(_node, _adjacent, _endNode); _adjacent = getObjFromInspectArray( _x +1, _y-1); inspectTheAdjacentNodes(_node, _adjacent, _endNode); _adjacent = getObjFromInspectArray( _x -1, _y - 1); inspectTheAdjacentNodes(_node, _adjacent, _endNode); _adjacent = getObjFromInspectArray( _x -1, _y+1); inspectTheAdjacentNodes(_node, _adjacent, _endNode); } while (_node) { //把路径点加入到路径列表中 m_pathList.push_back(CCPoint(_node->m_x, _node->m_y) ); _node = _node->m_parent; } #else //得到开始点的节点 PathSprite* _startNode = m_inspectArray[startX][startY]; //得到结束点的节点 PathSprite* _endNode = m_inspectArray[endX][endY]; //因为是开始点 把到起始点的距离设为0, F值也为0 _startNode->m_costToSource = 0; _startNode->m_FValue = 0; //把已经检测过的点从检测列表中删除 m_inspectArray[startX][startY] = NULL; //把该点放入已经检测过点的列表中 m_haveInspectList.push_back(_startNode); //然后加入开放列表 m_openList.push_back(_startNode); PathSprite* _node = NULL; while (true) { //得到离起始点最近的点(如果是第一次执行, 得到的是起点) _node = getMinPathFormOpenList(); if (!_node) { break; } //把计算过的点从开放列表中删除 removeObjFromOpenList( _node); int _x = _node->m_x; int _y = _node->m_y; // if (_x ==endX && _y == endY) { break; } //检测8个方向的相邻节点是否可以放入开放列表中 PathSprite* _adjacent = NULL; _adjacent = getObjFromInspectArray( _x +1, _y); inspectTheAdjacentNodes(_node, _adjacent, _endNode); _adjacent = getObjFromInspectArray( _x , _y -1); inspectTheAdjacentNodes(_node, _adjacent, _endNode); _adjacent = getObjFromInspectArray( _x -1, _y); inspectTheAdjacentNodes(_node, _adjacent, _endNode); _adjacent = getObjFromInspectArray( _x , _y+1); inspectTheAdjacentNodes(_node, _adjacent, _endNode); _adjacent = getObjFromInspectArray( _x + 1, _y + 1); inspectTheAdjacentNodes(_node, _adjacent, _endNode); _adjacent = getObjFromInspectArray( _x +1, _y-1); inspectTheAdjacentNodes(_node, _adjacent, _endNode); _adjacent = getObjFromInspectArray( _x -1, _y - 1); inspectTheAdjacentNodes(_node, _adjacent, _endNode); _adjacent = getObjFromInspectArray( _x -1, _y+1); inspectTheAdjacentNodes(_node, _adjacent, _endNode); } while (_node) { //把路径点加入到路径列表中 m_pathList.insert(m_pathList.begin(),CCPoint(_node->m_x, _node->m_y) ); _node = _node->m_parent; } #endif CCPoint _pArray[200]; for (int i = 0 ; i < m_pathList.size(); i ++) { _pArray[i] = m_pathList[i]; } sendData((const char*)&_pArray, sizeof(CCPoint)*m_pathList.size(), NULL); } PathSprite* getMinPathFormOpenList() { if (m_openList.size()>0) { PathSprite* _sp =* m_openList.begin(); for ( std::vector<PathSprite*>::iterator iter = m_openList.begin(); iter != m_openList.end(); iter++) { if ((*iter)->m_FValue < _sp->m_FValue) { _sp = *iter; } } return _sp; } else { return NULL; } } bool removeObjFromOpenList( PathSprite* sprite ) { if (!sprite) { return false; } for ( std::vector<PathSprite*>::iterator iter = m_openList.begin(); iter != m_openList.end(); iter++) { if (*iter == sprite) { m_openList.erase(iter); return true; } } return false; } PathSprite* getObjFromInspectArray( int x, int y ) { if (x >=0 && y >=0 && x < m_mapSize.width && y < m_mapSize.height) { return m_inspectArray[x][y]; } return NULL; } void PathSearchInfo::inspectTheAdjacentNodes( PathSprite* node, PathSprite* adjacent, PathSprite* endNode ) { if (adjacent) { float _x = abs(endNode->m_x - adjacent->m_x); float _y = abs(endNode->m_y - adjacent->m_y); float F , G, H1, H2, H3; adjacent->m_costToSource = node->m_costToSource + calculateTwoObjDistance(node, adjacent);//获得累计的路程 G = adjacent->m_costToSource; //三种算法, 感觉H2不错 H1 = _x + _y; H2 = hypot(_x, _y); H3 = max(_x, _y); #if 1 //A*算法 = Dijkstra算法 + 最佳优先搜索 F = G + H1; #endif #if 0//Dijkstra算法 F = G; #endif #if 0//最佳优先搜索 F = H2; #endif adjacent->m_FValue = F; adjacent->m_parent = node;//设置父节点 m_haveInspectList.push_back(adjacent); node->m_child = adjacent;//设置子节点 PathSearchInfo::m_inspectArray[adjacent->m_x][adjacent->m_y] = NULL;//把检测过的点从检测列表中删除 PathSearchInfo::m_openList.push_back(adjacent);//加入开放列表 } } float PathSearchInfo::calculateTwoObjDistance( PathSprite* obj1, PathSprite* obj2 ) { float _x = abs(obj2->m_x - obj1->m_x); float _y = abs(obj2->m_y - obj1->m_y); return _x + _y; } void PathSearchInfo::clearPath( ) { resetInspectArray(); //把移除了障碍物的地图放入检测列表中 m_openList.clear(); m_pathList.clear(); m_haveInspectList.clear(); } void PathSearchInfo::resetInspectArray() { for (std::vector<PathSprite*>::iterator iter = m_haveInspectList.begin(); iter != m_haveInspectList.end(); iter++) { (*iter)->m_costToSource = 0; (*iter)->m_FValue = 0; (*iter)->m_parent = NULL; (*iter)->m_child = NULL; m_inspectArray[(*iter)->m_x][(*iter)->m_y] = (*iter); } } }; void getMapdataFromXML(MapXML& data) { std::string wirtePath = "mapData.xml"; TiXmlDocument* myDocument = new TiXmlDocument(wirtePath.c_str()); myDocument->LoadFile(); TiXmlElement* MapDataElement = myDocument->RootElement(); // MapData std::string _strwidth = MapDataElement->Attribute("width"); //获得student的name属性 std::string _strheight = MapDataElement->Attribute("height"); //获得student的name属性 data.m_size.width =std::atoi( _strwidth.c_str() ); data.m_size.height =std::atoi( _strheight.c_str() ); TiXmlElement* dataElement = MapDataElement->FirstChildElement(); data.m_data = dataElement->GetText(); delete myDocument; } class createMapData { public: MapXML m_mapXml; std::vector< std::vector<PathSprite*>> m_inspectArray; createMapData(std::string mapPath) { getMapdataFromXML(mapPath); std::string & _str = m_mapXml.m_data; int _width = m_mapXml.m_size.width; int _height = m_mapXml.m_size.height; int index = 0; for (int j = 0; j < _width; j++) { std::vector<PathSprite*> _pathSprite; m_inspectArray.push_back(_pathSprite); for (int i = 0; i < _height; i++) { index = j * _height + i; if (_str[index]=='1') { PathSprite* _pathSprite = new PathSprite(); _pathSprite->m_x = j; _pathSprite->m_y =i; m_inspectArray[j].push_back(_pathSprite); //把地图中所有的点一一对应放入检测列表中 } else { m_inspectArray[j].push_back(NULL); } } } } void getMapdataFromXML(std::string mapPath) { std::string wirtePath = mapPath;//"mapData.xml"; TiXmlDocument* myDocument = new TiXmlDocument(wirtePath.c_str()); myDocument->LoadFile(); TiXmlElement* MapDataElement = myDocument->RootElement(); // MapData std::string _strwidth = MapDataElement->Attribute("width"); //获得student的name属性 std::string _strheight = MapDataElement->Attribute("height"); //获得student的name属性 m_mapXml.m_size.width =std::atoi( _strwidth.c_str() ); m_mapXml.m_size.height =std::atoi( _strheight.c_str() ); TiXmlElement* dataElement = MapDataElement->FirstChildElement(); // CCLOG("%s",dataElement->GetText()); m_mapXml.m_data = dataElement->GetText(); delete myDocument; } }; class ServerSocate { public: SOCKET sockConn; std::function<void(int,int,int,int)> calculatePath; struct sockaddr_in from; int fromlen ; ServerSocate() { fromlen =sizeof(from); } void startServer() { #if 0 WSADATA wsaData; if (WSAStartup(MAKEWORD(2,1),&wsaData)) //调用Windows Sockets DLL { printf("Winsock无法初始化!\n"); WSACleanup(); return; } SOCKET sockSrv=socket(AF_INET,SOCK_STREAM,0); //2:绑定套接字到一个IP地址和一个端口上(bind()); SOCKADDR_IN addrSrv; addrSrv.sin_addr.S_un.S_addr=htonl(INADDR_ANY); addrSrv.sin_family=AF_INET; addrSrv.sin_port=htons(6000); bind(sockSrv,(SOCKADDR*)&addrSrv,sizeof(SOCKADDR)); //3:将套接字设置为监听模式等待连接请求(listen()); listen(sockSrv,5); //4:请求到来后,接受连接请求,返回一个新的对应于此次连接的套接字(accept()); SOCKADDR_IN addrClient; int len=sizeof(SOCKADDR); sockConn=accept(sockSrv,(SOCKADDR*)&addrClient,&len); #endif #if 1 WSADATA wsaData; if (WSAStartup(MAKEWORD(2,1),&wsaData)) //调用Windows Sockets DLL { printf("Winsock无法初始化!\n"); WSACleanup(); return; } printf("服务器开始创建SOCKET。\n"); struct sockaddr_in local; local.sin_family=AF_INET; local.sin_port=htons(6000); ///监听端口 local.sin_addr.s_addr=INADDR_ANY; ///本机 sockConn=socket(AF_INET,SOCK_DGRAM,0); bind(sockConn,(struct sockaddr*)&local,sizeof(local)); #endif //多线程 std::function<void(SOCKET &)> _recv = std::bind(&ServerSocate::recvFunction, this, std::placeholders::_1); std::thread recvThread(_recv,sockConn); recvThread.detach(); while(1) { } } #if 0 void sendFuction(SOCKET &sockConn) { while (true) { } } #endif void sendData(const char* buf, int len, int flags) { sendto(sockConn, buf, len, flags,(struct sockaddr*)&from,fromlen); } void recvFunction(SOCKET& sockClient) { while (true) { char buffer[2048]="\0"; printf("waiting for message from others-------------\n"); if (recvfrom(sockClient,buffer,sizeof(buffer),0,(struct sockaddr*)&from,&fromlen)!=SOCKET_ERROR) { DataStruct *_data = (DataStruct *)buffer; printf("%s\n",inet_ntoa(from.sin_addr)); printf("%d\n",_data->startx); printf("%d\n",_data->starty); printf("%d\n",_data->endx); printf("%d\n",_data->endy); calculatePath(_data->startx,_data->starty,_data->endx,_data->endy); } } } }; void main() { createMapData* MapData = new createMapData("mapData.xml"); PathSearchInfo* _pathSearch = new PathSearchInfo(MapData->m_mapXml.m_size,MapData->m_inspectArray); ServerSocate* _server = new ServerSocate; _pathSearch->sendData = std::bind(&ServerSocate::sendData, _server, std::placeholders::_1,std::placeholders::_2,std::placeholders::_3); _server->calculatePath = std::bind(&PathSearchInfo::calculatePath, _pathSearch, std::placeholders::_1,std::placeholders::_2,std::placeholders::_3, std::placeholders::_4); _server->startServer(); }