失眠网,内容丰富有趣,生活中的好帮手!
失眠网 > C++实现简易(多人弹幕控制主播游戏人物类型 CMD_迷宫小游戏)(二)

C++实现简易(多人弹幕控制主播游戏人物类型 CMD_迷宫小游戏)(二)

时间:2018-10-12 03:54:14

相关推荐

C++实现简易(多人弹幕控制主播游戏人物类型 CMD_迷宫小游戏)(二)

更新内容:

1.迷宫地图使用prim算法生成看起来像回事的地图

2.修改后面启动的客户端不同步之前的客户端的游戏情况

逻辑实现:

1.服务器第一个接到客户端链接时,生成地图,初始坐标等信息。

2.有客户端链接时,给客户端发送地图,当前人物坐标等数据

3.客户端不生成地图,只接收服务器地图数据,每次成功行动后,发送坐标给服务器记录最新坐标

代码实现:

客户端

Game01 类#pragma once#include<cstdio>#include<string>#include<vector>#include"Common.h"using namespace std;class Game01{public:Game01();~Game01();void init(); //初始化地图和坐标数据void createMap(); //随机生成地图void refreshMap(NodeData *data); //刷新地图,重绘当前位置void refreshMap(MAPData *data); //接受服务器地图bool MapIsOk(); //判断生成地图是否可用,不可用则完善地图通道,使其可通过bool IsSuccess(); // 是否到达终点void GetPositionData(int* command); //获取服务器发送数据,并转换为下一步坐标void SetPosittionData(); // 给服务器发送下一步命令void PrintfMap(); //输出地图void GenerateAMap();void FindBlock();void setNewX(int x){m_newX = x;}void setNewY(int y){m_newY = y;}int getNewX(){return m_newX;}int getNewY(){return m_newY;}private:int m_newX; //当前X坐标int m_newY; //当前Y坐标int m_beginX; //起始X,Yint m_beginY;int m_endX; //终点X,Yint m_endY; int m_MAP[MAXDATA][MAXDATA];vector<block> myblock;int x_num = 1, y_num = 1;//矿工位置};#include "Game01.h"#include <ctime>#include"Client.h"Game01::Game01(){//初始化地图和坐标数据m_newX = 0;m_newY = 0;m_beginX = 0;m_beginY = 0;m_endX = 0;m_endY = 0;memset(m_MAP, 0, sizeof(m_MAP));}Game01::~Game01(){}//void Game01::init() //{////createMap(); //生成地图////if (MapIsOk()) //完善地图通道////{////int command[2] = { 0 };////while (!IsSuccess()) //未到达终点////{//// GetPositionData(command);//// if (command[0] == m_newX && command[1] == m_newY)//// {//// continue; //与当前坐标一致,则不移动//// }//// else//// {//// m_newX = command[0]; //接受服务器数据重新定位的当前位置//// m_newY = command[1];//// //refreshMap();//// }////}////}////}void Game01::init() {//将地图全部置为墙//memset(m_MAP, M_WALL, sizeof(m_MAP));//定义起始点m_MAP[1][1] = M_NOTHING;m_beginX = 0;m_beginY = 1;//m_newX = 1;//m_newY = 1;m_endX = M_WEIDHT;m_endY = M_HIGNTH + 1;m_MAP[m_beginX][m_beginY] = M_NOTHING;m_MAP[m_newX][m_newY] = 3;m_MAP[m_endX][m_endY] = M_NOTHING;//GenerateAMap();PrintfMap();}void Game01::GenerateAMap(){srand((unsigned)time(NULL));//随机数种子FindBlock();//第一步压入两堵墙(起点右边和起点下面)进入循环while (myblock.size()) {int BlockSize = myblock.size();//随机选择一堵墙(生成0 ~ BlockSize-1之间的随机数,同时也是vector里墙的下标)int randnum = rand() % BlockSize;block SelectBlock = myblock[randnum];x_num = SelectBlock.row;//矿工来到我们“选择的墙”这里y_num = SelectBlock.column;//根据当前选择的墙的方向进行后续操作//此时,起始点 选择的墙 目标块 三块区域在同一直线上//我们让矿工从“选择的墙”继续前进到“目标块”//矿工有穿墙能力 :)switch (SelectBlock.direction) {case M_down: {x_num++;break;}case M_right: {y_num++;break;}case M_left: {y_num--;break;}case M_up: {x_num--;break;}}//目标块如果是墙if (m_MAP[x_num][y_num] == M_WALL) {//打通墙和目标块m_MAP[SelectBlock.row][SelectBlock.column] = m_MAP[x_num][y_num] = M_NOTHING;//再次找出与矿工当前位置相邻的墙FindBlock();}else {//如果不是呢?说明我们的矿工挖到了一个空旷的通路上面 休息一下就好了//relax}//删除这堵墙(把用不了的墙删了,对于那些已经施工过了不必再施工了,同时也是确保我们能跳出循环)myblock.erase(myblock.begin() + randnum);}}void Game01::FindBlock() {//找出与当前位置相邻的墙if (x_num + 1 <= M_WEIDHT && m_MAP[x_num + 1][y_num] == M_WALL) {//downmyblock.push_back(block(x_num + 1, y_num, M_down));}if (y_num + 1 <= M_HIGNTH && m_MAP[x_num][y_num + 1] == M_WALL) {//rightmyblock.push_back(block(x_num, y_num + 1, M_right));}if (x_num - 1 >= 1 && m_MAP[x_num - 1][y_num] == M_WALL) {//upmyblock.push_back(block(x_num - 1, y_num, M_up));}if (y_num - 1 >= 1 && m_MAP[x_num][y_num - 1] == M_WALL) {//leftmyblock.push_back(block(x_num, y_num - 1, M_left));}}void Game01::createMap() //随机生成地图{int64_t new_time = 0;int randVlaue = 0;int commont[2] = { 0 };m_newY = 1;m_beginY = 1;m_endX = 48;m_endY = 49;m_MAP[0][1] = 0; //起始位置m_MAP[48][49] = 0; //终点位置while (!IsSuccess()) //未到达终点){GetPositionData(commont);if (commont[0] == m_newX && commont[1] == m_newY){continue; //与当前坐标一致,则不移动}else if (commont[0] == m_endX && commont[1] == m_endY){m_newX = commont[0]; //接受服务器数据重新定位的当前位置m_newY = commont[1];m_MAP[m_newX][m_newY] = 2;}else if ((commont[0] <= 0 || commont[0] >= 49 || commont[1] <= 0 || commont[1] >= 49)){continue;}//else if (m_MAP[commont[0]][commont[1]] == 2)//{//continue;//}else{//if(0)m_newX = commont[0]; //接受服务器数据重新定位的当前位置m_newY = commont[1];m_MAP[m_newX][m_newY] = 2;//refreshMap();}}for (int i = 0; i < MAP_VALUE; i++){for (int j = 0; j < MAP_VALUE; j++){if (i == 0 || i == 49 || (i > 0 && j == 0) || (i > 0 && j == 49)) {m_MAP[i][j] = 1;}else {//srand((int)time(0)); // 产生随机种子 把0换成NULL也行new_time = random(10000000);//GetSysTimeMicros();randVlaue = random(100);if(m_MAP[i][j] != 2)m_MAP[i][j] = ((new_time * randVlaue) % 37 > 17 ? 0 : 1); //随机生成迷宫数据 // 取余数 暂且可以预留为 难度标准//○}}}//m_newY = random(49);//m_beginY = m_newY;//m_endX = random(49);//m_endY = 49;//m_MAP[0][m_beginY] = 0; //起始位置//m_MAP[m_endX][49] = 0; //终点位置m_newX = 0;m_newY = 1;m_beginY = 1;m_endX = 48;m_endY = 49;m_MAP[0][1] = 0; //起始位置m_MAP[48][49] = 0; //终点位置m_MAP[m_newX][m_newY] = 3;PrintfMap();}void Game01::PrintfMap() //输出地图 0 可移动路径 1 墙壁 2 可通行路径 3 当前位置{system("cls");for (int i = 0; i < M_WEIDHT+2; i++){for (int j = 0; j < M_HIGNTH+2; j++){if (m_MAP[i][j] == M_WALL){printf("■");}//else if (m_MAP[i][j] == 2)//{////printf("○");//printf(" ");//}else if (m_MAP[i][j] == 3){printf("○");}else {printf(" ");}}printf("\n");}}void Game01::refreshMap(MAPData *data) //接受服务器地图{if (data != nullptr){if (data->massage == MassgeType::INITIALIZEMAZE){//同步前面客户端的地图memcpy(m_MAP, data->Map, sizeof(m_MAP));//PrintfMap();//IsSuccess();}}}void Game01::refreshMap(NodeData *data) //刷新地图,重绘当前位置{if (data == nullptr)return;char massage = data->massgeData[0];//给后出现的客户端统一数据//m_newX = data->New_X;//m_newY = data->New_Y;//int commandif (data->massage == MassgeType::COMMAND && data->massgeData == "OK")//是否成功{printf("成功了\n");}if (data->massage == MassgeType::MAPDATA){//同步前面客户端的位置m_newX = data->New_X;m_newY = data->New_Y;m_MAP[m_newX][m_newY] = 3;PrintfMap();IsSuccess();}if (data->massage == MassgeType::DIRECTION){int x = m_newX;int y = m_newY;switch (massage){case 'W':case 'w':if (m_newX > 0 && m_MAP[m_newX - 1][m_newY] != M_WALL) {m_newX = m_newX - 1;m_MAP[m_newX + 1][m_newY] = 2;}break;case 'S':case 's':if (m_newX < 49 && m_MAP[m_newX + 1][m_newY] != M_WALL) {m_newX = m_newX + 1;m_MAP[m_newX - 1][m_newY] = 2;}break;case 'A':case 'a':if (m_newY > 0 && m_MAP[m_newX][m_newY - 1] != M_WALL) {m_newY = m_newY - 1;m_MAP[m_newX][m_newY + 1] = 2;}break;case 'D':case 'd':if (m_newY < 49 && m_MAP[m_newX][m_newY + 1] != M_WALL) {m_newY = m_newY + 1;m_MAP[m_newX][m_newY - 1] = 2;}break;}//移动成功,发送移动后的数据if (x != m_newX || y != m_newY){NodeData nodeData;nodeData.massage = MassgeType::MOBILE;nodeData.massgeData = "";nodeData.New_X = m_newX;nodeData.New_Y = m_newY;//发送数据Client::GetInfrance()->SendData(&nodeData);}m_MAP[m_newX][m_newY] = 3;PrintfMap();IsSuccess();}}bool Game01::MapIsOk() //判断生成地图是否可用,不可用则完善地图通道,使其可通过{bool flag = false;int randVlaue = random(4);while (m_newX != m_endY && m_newY != m_endY) //未到达终点{randVlaue = random(4);switch (randVlaue % 4){case 0:break;case 1:break;case 2:break;case 3:break;}}return flag;}bool Game01::IsSuccess() // 是否到达终点{bool flag = false;if (m_newX == m_endX && m_newY == m_endY) // 到达终点,给服务器发送OK数据{SetPosittionData();flag = true;}return flag;}void Game01::GetPositionData(int* command) //获取服务器发送数据,并转换为下一步坐标{//int command[2] = {0}; //0为X,1为Y//调用客户端类的单例 获取到massage w a s dchar massge=' ';// srand((int)time(0)); // 产生随机种子 把0换成NULL也行int randVlaue = random(100000)%10;if (randVlaue == 0 || randVlaue == 1)massge = 'w';else if (randVlaue == 2 || randVlaue == 3 || randVlaue == 4)massge = 's';else if (randVlaue == 6 || randVlaue == 5)massge = 'a';else// (randVlaue == 3)massge = 'd';//if (randVlaue == 0 )// massge = 'w';//else if (randVlaue == 1 /*|| randVlaue == 4*/)// massge = 's';//else if (randVlaue ==2)// massge = 'a';//else// (randVlaue == 3)// massge = 'd';switch (massge){case 'W':case 'w':command[0] = m_newX;command[1] = m_newY - 1;break;case 'S':case 's':command[0] = m_newX;command[1] = m_newY + 1;break;case 'A':case 'a':command[0] = m_newX -1;command[1] = m_newY;break;case 'D':case 'd':command[0] = m_newX + 1;command[1] = m_newY;break;}}void Game01::SetPosittionData() // 给服务器发送下一步命令{//调用客户端类的单例NodeData data;data.massage = MassgeType::COMMAND;data.massgeData = "SUCCESS";Client::GetInfrance()->SendData(&data);}

Client#pragma once// 从 Windows 头文件中排除极少使用的信息#define WIN32_LEAN_AND_MEAN #define _WINSOCK_DEPRECATED_NO_WARNINGS#include<stdio.h>#include<string>#ifdef _WIN32#include<WinSock2.h>#include<Windows.h>#else#include<unistd.h>#include<arpa/inet.h>#include<string.h>#define SOCKET int#define SOCKET_ERROR -1#endif#pragma comment(lib,"ws2_32.lib")#include"Common.h"using namespace std;class Client{public:void Init();void Connect();void Close();void SendData(NodeData *data);NodeData* RecvData();MAPData* RecvDataMap();static Client* GetInfrance();static Client* m_client;private:Client() {}SOCKET sock;sockaddr_in sockadd;bool isClose = false;NodeData nodeData;MAPData mapData;};#include "Client.h"Client* Client::m_client = nullptr;void Client::Init(){if (!isClose){//启动windows socket #ifdef _WIN32WORD var = MAKEWORD(2, 2);WSADATA dar;WSAStartup(var, &dar);#endifsock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);sockadd.sin_family = AF_INET;sockadd.sin_port = htons(6666);#ifdef _WIN32sockadd.sin_addr.S_un.S_addr = inet_addr("127.0.0.1"); //转换IP地址为网络字节数据#elsesockadd.sin_addr.s_addr = inet_addr("192.168.126.128"); //192.168.128.1#endif}}Client* Client::GetInfrance(){if (m_client == nullptr){m_client = new Client();}return m_client;}void Client::Connect(){if (!isClose){//连接服务器if (SOCKET_ERROR == connect(sock, (const sockaddr*)&sockadd, sizeof(sockaddr_in))){printf("错误,连接服务器失败!\n");}else{printf("连接服务器成功!\n");}}}void Client::Close(){//关闭套接字//getchar();#ifdef _WIN32closesocket(sock);WSACleanup();#elseclose(sock);#endifisClose = true;}void Client::SendData(NodeData *data){if (!isClose){if (data != nullptr){send(sock, (char*)data, sizeof(NodeData), 0);}}}NodeData* Client::RecvData(){if (!isClose){memset(&nodeData,0,sizeof(NodeData));//接收发送数据if (recv(sock, (char*)&nodeData, sizeof(NodeData), 0) > 0){printf("服务端发送的数据,IP:%s\n", nodeData.massgeData.c_str());return &nodeData;}}return nullptr;}MAPData* Client::RecvDataMap(){if (!isClose){memset(&mapData, 0, sizeof(MAPData));//接收发送数据if (recv(sock, (char*)&mapData, sizeof(MAPData), 0) > 0){printf("服务端发送的地图数据");return &mapData;}}return nullptr;}

Common.h#pragma once#include<string>#define random(x) rand()%(x)#define MAXDATA 100#define MAP_VALUE 50#define M_WEIDHT 21//row#define M_HIGNTH 21#define M_down 1#define M_right 2#define M_left 4#define M_up 8#define M_WALL -1#define M_NOTHING 2enum MassgeType{COMMAND=0, //命令MAPDATA,//初始化迷宫数据INITIALIZEMAZE, //初始化迷宫,获取第一个登陆客户的迷宫DIRECTION, //方向MOBILE, //移动成功};typedef struct NodeData{MassgeType massage = COMMAND; //消息类型std::string massgeData; //消息数据int New_X;int New_Y;};typedef struct MAPData{MassgeType massage = INITIALIZEMAZE; //消息类型int Map[MAXDATA][MAXDATA];};struct block {int row, column, direction;block(int _row, int _column, int _direction) {row = _row;column = _column;direction = _direction;}};struct point {int x;int y;};

main.c#include<stdio.h>#include<iostream>#include <thread>#include<string>#include"Game01.h"#include"Common.h"#include"Client.h"using namespace std;//过去用户命令void getCommand(Game01 *game){string str;NodeData nodeData = {};while (1){str.clear();cin >> str;//压力测试代码//static long time_stamp = GetCurrentTime();//getCurrentTime为上面介绍的函数;//int dis = GetCurrentTime() - time_stamp;//if (dis >= 80) {//time_stamp = GetCurrentTime();//srand((int)time(0)); // 产生随机种子 把0换成NULL也行//int randVlaue = random(100000) % 10;//if (randVlaue == 0 || randVlaue == 1)//str.append("w");//else if (randVlaue == 2 || randVlaue == 3 || randVlaue == 4)//str.append("s");//else if (randVlaue == 6 || randVlaue == 5)//str.append("a");//else// (randVlaue == 3)//str.append("d");//}if (str.size() == 1){switch (str[0]){case 'w':case 's':case 'a':case 'd':case 'W':case 'S':case 'A':case 'D':nodeData.massage = MassgeType::DIRECTION;nodeData.massgeData = str;nodeData.New_X = game->getNewX();nodeData.New_Y = game->getNewY();//发送数据Client::GetInfrance()->SendData(&nodeData);break;case 'q'://预留退出接口break;default:break;}}}}//绘制用户命令void SetCommand(Game01 *game){while (1){NodeData *nodedata = Client::GetInfrance()->RecvData();if (nodedata != nullptr){//有服务器发送的数据game->refreshMap(nodedata);}}}int main(){Game01 game;Client::GetInfrance()->Init(); //初始化客户单Client::GetInfrance()->Connect(); //链接服务器game.refreshMap(Client::GetInfrance()->RecvDataMap()); //接受服务器发送的地图数据game.refreshMap(Client::GetInfrance()->RecvData()); //接受服务器发送的初始化位置数据game.init(); //初始化显示地图thread first(getCommand,&game);thread scend(SetCommand,&game);first.join();scend.join();Client::GetInfrance()->Close();return 0;}

服务器:

Common.h#include<vector>#define random(x) rand()%(x)#define MAXDATA 100#define MAP_VALUE 50#define M_WEIDHT 21//row#define M_HIGNTH 21#define M_down 1#define M_right 2#define M_left 4#define M_up 8#define M_WALL -1#define M_NOTHING 2enum MassgeType{COMMAND = 0, //命令MAPDATA,//初始化迷宫数据INITIALIZEMAZE, //初始化迷宫,获取第一个登陆客户的迷宫DIRECTION, //方向MOBILE, //移动成功};typedef struct MAPData{MassgeType massage = INITIALIZEMAZE; //消息类型int Map[MAXDATA][MAXDATA];};typedef struct NodeData{MassgeType massage = COMMAND; //消息类型std::string massgeData; //消息数据int New_X;int New_Y;}; struct block {int row, column, direction;block(int _row, int _column, int _direction) {row = _row;column = _column;direction = _direction;}};struct point {int x;int y;};int m_MAP[MAXDATA][MAXDATA];std::vector<block> myblock;int x_num = 1, y_num = 1;//矿工位置void GenerateAMap();void FindBlock();void init() {//将地图全部置为墙memset(m_MAP, M_WALL, sizeof(m_MAP));GenerateAMap();}void GenerateAMap(){srand((unsigned)time(NULL));//随机数种子FindBlock();//第一步压入两堵墙(起点右边和起点下面)进入循环while (myblock.size()) {int BlockSize = myblock.size();//随机选择一堵墙(生成0 ~ BlockSize-1之间的随机数,同时也是vector里墙的下标)int randnum = rand() % BlockSize;block SelectBlock = myblock[randnum];x_num = SelectBlock.row;//矿工来到我们“选择的墙”这里y_num = SelectBlock.column;//根据当前选择的墙的方向进行后续操作//此时,起始点 选择的墙 目标块 三块区域在同一直线上//我们让矿工从“选择的墙”继续前进到“目标块”//矿工有穿墙能力 :)switch (SelectBlock.direction) {case M_down: {x_num++;break;}case M_right: {y_num++;break;}case M_left: {y_num--;break;}case M_up: {x_num--;break;}}//目标块如果是墙if (m_MAP[x_num][y_num] == M_WALL) {//打通墙和目标块m_MAP[SelectBlock.row][SelectBlock.column] = m_MAP[x_num][y_num] = M_NOTHING;//再次找出与矿工当前位置相邻的墙FindBlock();}else {//如果不是呢?说明我们的矿工挖到了一个空旷的通路上面 休息一下就好了//relax}//删除这堵墙(把用不了的墙删了,对于那些已经施工过了不必再施工了,同时也是确保我们能跳出循环)myblock.erase(myblock.begin() + randnum);}}void FindBlock() {//找出与当前位置相邻的墙if (x_num + 1 <= M_WEIDHT && m_MAP[x_num + 1][y_num] == M_WALL) {//downmyblock.push_back(block(x_num + 1, y_num, M_down));}if (y_num + 1 <= M_HIGNTH && m_MAP[x_num][y_num + 1] == M_WALL) {//rightmyblock.push_back(block(x_num, y_num + 1, M_right));}if (x_num - 1 >= 1 && m_MAP[x_num - 1][y_num] == M_WALL) {//upmyblock.push_back(block(x_num - 1, y_num, M_up));}if (y_num - 1 >= 1 && m_MAP[x_num][y_num - 1] == M_WALL) {//leftmyblock.push_back(block(x_num, y_num - 1, M_left));}}

Service.cpp#include<stdio.h>#include<stdlib.h>#include<time.h>#ifdef _WIN32#define WIN32_LEAN_AND_MEAN#define _WINSOCK_DEPRECATED_NO_WARNINGS#define _CRT_SECURE_NO_WARNINGS#include<Windows.h>#include<WinSock2.h>#pragma comment(lib,"ws2_32.lib")#else#include<unistd.h>#include<arpa/inet.h>#include<string.h>#define SOCKET int#define SOCKET_ERROR -1#define INVALID_SOCKET (SOCKET)(~0)#endif#include<vector>#include<map>#include<string>#include"Common.h"using namespace std;std::vector<SOCKET> g_socket; //总的连接客户端//std::vector<SOCKET> g_socket_Client; //发送数据的客户端std::map<std::string, int> MessageList;int g_New_X = 0, g_New_Y = 1; //客户端当前的XY坐标int MessageData(SOCKET socket){static long time_stamp = GetCurrentTime();//getCurrentTime为上面介绍的函数;static int count1, count2, count3, count4 = 0;//static int new_X, new_Y = 0; //第一个客户端当前的XY坐标//==========================================================//要执行的代码//缓冲区char szRecv[1024] = { 0 };int nLen = recv(socket, szRecv, sizeof(NodeData), 0);NodeData *data = (NodeData*)szRecv;if (nLen <= 0){printf("客户端已退出\n");return -1;}if (data->massage == MassgeType::MOBILE) //移动成功更新最新坐标数据{g_New_X = data->New_X;g_New_Y = data->New_Y;}//if (g_socket_Client.end() == find(g_socket_Client.begin(), g_socket_Client.end(), socket)) //当前集合中不存在时,加入//{//g_socket_Client.push_back(socket);//}if (data->massage == DIRECTION){//消息发送接受处理std::string sss = data->massgeData;switch (sss[0]){case 'W':case 'w':MessageList.insert(pair<std::string, int>(sss, count1++));break;case 'S':case 's':MessageList.insert(pair<std::string, int>(sss, count2++));break;case 'A':case 'a':MessageList.insert(pair<std::string, int>(sss, count3++));break;case 'D':case 'd':MessageList.insert(pair<std::string, int>(sss, count4++));break;}//printf("客户端发送的数据,IP:%d , Data:%s, X:%d, Y:%d\n", socket, data->massgeData.c_str(), data->New_X,data->New_Y);}else if (data->massage == COMMAND && data->massgeData=="SUCCESS"){NodeData recvData;recvData.massage = COMMAND;recvData.massgeData = "OK";//recvData.New_X = new_X;//recvData.New_Y = new_Y;for (int i = 0; i < g_socket.size(); i++){send(g_socket[i], (char*)&recvData, sizeof(NodeData), 0);}printf("服务端发送的数据,IP:%d , Data:%s\n", socket, recvData.massgeData.c_str());return 1;}//==========================================================//计算睡眠时间(毫秒),保证每隔500ms循环一次,发送一次客户端需求最多的命令 是客户端实行int dis = GetCurrentTime() - time_stamp;if (dis >= 500 && MessageList.size() > 0) {//求四个方向最多的数 即为下一步方向NodeData recvData;recvData.massage = DIRECTION;recvData.New_X = 0;recvData.New_Y = 0;int num = max(max(max(count1, count2), count3), count4);if (num == count1){recvData.massgeData = "W";}else if (num == count2){recvData.massgeData = "S";}else if (num == count3){recvData.massgeData = "A";}else if (num == count4){recvData.massgeData = "D";}//if (g_socket.size() >= 10) //压测代码//{for (int i = 0; i < g_socket.size(); i++){send(g_socket[i], (char*)&recvData, sizeof(NodeData), 0);printf("服务端发出的数据,IP:%d , Data:%s\n", g_socket[i], recvData.massgeData.c_str());}//}count1 = 0;count2 = 0;count3 = 0;count4 = 0;MessageList.clear();time_stamp = GetCurrentTime();//getCurrentTime为上面介绍的函数;}return 1;}int main(){#ifdef _WIN32//启动windows socket WORD var = MAKEWORD(2, 2);WSADATA dar;WSAStartup(var, &dar);#endifSOCKET sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);sockaddr_in sockadd;sockadd.sin_family = AF_INET;sockadd.sin_port = htons(6666);SOCKET maxsock = sock;#ifdef _WIN32sockadd.sin_addr.S_un.S_addr = INADDR_ANY;//inet_addr("127.0.0.1"); 转换IP地址为网络字节数据#elsesockadd.sin_addr.s_addr = INADDR_ANY;#endif//绑定socketif (SOCKET_ERROR == bind(sock, (sockaddr*)&sockadd, sizeof(sockaddr_in))){printf("错误,绑定端口失败!\n");}else{printf("绑定端口成功!\n");}//开启监听if (SOCKET_ERROR == listen(sock, 10)){printf("错误,监听端口失败!\n");}else{printf("监听端口成功!\n");}while (true){//开启select 等待消息fd_set dataRead;fd_set dataWrite;fd_set dataError;timeval t_val = { 1,0 };//初始化FD_ZERO(&dataRead);FD_ZERO(&dataWrite);FD_ZERO(&dataError);//绑定到sockFD_SET(sock, &dataRead);FD_SET(sock, &dataWrite);FD_SET(sock, &dataError);//将socket集合中的socket添加到可读集合中for (int i = 0; i < (int)g_socket.size(); i++){FD_SET(g_socket[i], &dataRead);if (maxsock < g_socket[i])maxsock = g_socket[i];}int ret = select(maxsock + 1, &dataRead, &dataWrite, &dataError, &t_val);if (ret < 0){//有错误printf("错误,select出错...\n");// int nErr = WSAGetLastError();//printf("select: %d, %s\n", nErr, strerror(errno));//break;}//判断sock是否可读,有则,游客户端接入if (FD_ISSET(sock, &dataRead)){FD_CLR(sock, &dataRead);//accept 等待接收客户端连接sockaddr_in sockadd_Client = {};int clientLen = sizeof(sockaddr_in);//接收客户端信息的socketSOCKET _cSocket = INVALID_SOCKET;#ifdef _WIN32_cSocket = accept(sock, (sockaddr*)&sockadd_Client, &clientLen);#else_cSocket = accept(sock, (sockaddr*)&sockadd_Client, (socklen_t*)&clientLen);#endifif (INVALID_SOCKET == _cSocket){printf("错误,接收到无效客户端socket...\n");}printf("新客户段接入,socketID:%d,IP:%s \n", (int)_cSocket, inet_ntoa(sockadd_Client.sin_addr));char buff[128] = { 0 };strcpy(buff, inet_ntoa(sockadd_Client.sin_addr));for (int i = 0; i < (int)g_socket.size(); i++){send(g_socket[i], buff, 128, 0);}if (g_socket.size() == 0){g_New_X = 0;g_New_Y = 1;init(); //第一次有客户段链接,生成地图}//有新客户端上线,同步地图MAPData data;data.massage = INITIALIZEMAZE;memcpy(data.Map, m_MAP,sizeof(m_MAP));send(_cSocket, (char*)&data, sizeof(MAPData), 0);//有新客户端上线,同步位置NodeData data1;data1.massage = MAPDATA;data1.massgeData = "";data1.New_X = g_New_X;data1.New_Y = g_New_Y;send(_cSocket, (char*)&data1, sizeof(NodeData), 0);printf("当前位置 X:%d,Y:%d",g_New_X,g_New_Y);g_socket.push_back(_cSocket);}//消息处理for (int i = 0; i < (int)dataRead.fd_count; i++){if (-1 == MessageData(dataRead.fd_array[i])) //客户端无消息{auto iter = find(g_socket.begin(), g_socket.end(), dataRead.fd_array[i]);if (iter != g_socket.end()) //但是sockrt在连接列表里面 则移除{g_socket.erase(iter);}}}// printf("未处理网络请求\n");}getchar();#ifdef _WIN32//关闭套接字closesocket(sock);//接收发送数据WSACleanup();#elseclose(sock);#endifreturn 0;}

如果觉得《C++实现简易(多人弹幕控制主播游戏人物类型 CMD_迷宫小游戏)(二)》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。