socket + A* + c++

//

#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();

}  

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章