⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gobangsrv.cpp

📁 一个Linux下的五子棋对战游戏
💻 CPP
字号:
#include "gobangSrv.h"#include "client.h"using namespace std;void sg_hd(int signum);vector<client> clivec;int maxfd;fd_set rset, wset;pair<int, int> pos;char chatBuff[MAX_LEN * 20];char flagInfo;char nextTurn;int x, y;char chessBoard[15][15];int newclient(int listenfd);char recv(fd_set& rs);int send(char* sendbuff, fd_set &ws);int NewGame();int SendFlagInfo();bool SendErroInfo(char wrongType, char sendDestine);bool PositionRight(void);bool SendPosInfo(char sendDestine);int checkLength(int x, int y, int direction);bool CheckVicCon();bool SendVicInfo();int main(int argc, char* argv[]){	int listenfd;	struct sockaddr_in servaddr;	sigset_t block_mask, zero_mask;	struct sigaction sg_act, old_sa;		if(argc < 2)	{		cout << "usage: crsrv <port>\n";		exit(0);	}			bzero(&sg_act, sizeof(struct sigaction));	bzero(&old_sa, sizeof(struct sigaction)); 	sigemptyset(&block_mask);	sigemptyset(&zero_mask);	sg_act.sa_mask = block_mask;	sg_act.sa_flags = 0;	sg_act.sa_handler = sg_hd;	if(sigaction(SIGCHLD, &sg_act, NULL) == -1)	{		perror("sigaction");		exit(1);		}		if((listenfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)	{		perror("socket");		exit(1);	}		bzero(&servaddr, sizeof(servaddr));	servaddr.sin_family = AF_INET;	servaddr.sin_addr.s_addr = htonl(INADDR_ANY);	servaddr.sin_port = htons(atoi(argv[1]));	if(bind(listenfd, (struct sockaddr*)&servaddr, sizeof(servaddr)) == -1)	{		perror("bind");		exit(1);	}		if(listen(listenfd, BACKLOG) ==-1)	{		perror("listen");		exit(1);	}		for( ; ; )	{		maxfd = listenfd + 1;		newclient(listenfd);		if(clivec.size() >= 2)		{			pid_t pid;			pid = fork();			cout << "fork\n";			if(pid < 0)			{				perror("fork");			}			else if (pid ==0)			{				close(listenfd);				NewGame();			}			else if (pid > 0)			{								close(clivec[0].clifd);				close(clivec[1].clifd);				clivec.clear();			}		}	}	return 0;}void sg_hd(int signum){	int status;	if(signum == SIGCHLD)	{		while(waitpid(-1, &status, WNOHANG) > 0);		cout << "Child exit\n";		return;	}	if(signum == SIGALRM)	{		cout << "Child " << getpid() << " get time alarmed\n";		exit(0);	}}int newclient(int listenfd){	int connfd;	struct sockaddr_in cliaddr;	socklen_t clilen;	clilen = sizeof(cliaddr);	connfd = accept(listenfd, (struct sockaddr*)&cliaddr, &clilen);	if(connfd == -1)	{		if(errno == EINTR)		{			return -1;		}		else if(errno == EWOULDBLOCK)		{			return -2;		}		else		{			perror("accept");			return -3;		}	}	else	{		client newclnt;		newclnt.clifd = connfd;		cout << "new client\n";		clivec.push_back(newclnt);		return 0;	}}char recv(fd_set& rs){	vector<client>::iterator iter;	int n;	char buff[MAX_LEN];	for(iter = clivec.begin(); iter !=clivec.end(); iter++)	{			if(FD_ISSET(iter->clifd, &rs))		{			bzero(buff, MAX_LEN);			if((n = iter->recv(buff, MAX_LEN)) == -3)			{				cout << iter->name << " recv wrong\n";				continue;			}			else if(n == 0)//client leave the chat room			{				snprintf(buff, MAX_LEN, "%s leave the serve\n", iter->name);				FD_CLR(iter->clifd, &wset);				FD_CLR(iter->clifd, &rset);				close(iter->clifd);				cout << buff;				clivec.erase(iter);				strncat(chatBuff, buff, MAX_LEN * 20);				return LEAVE_INFO;			}			else if(n > 0)			{				buff[n] = '\0';				switch(buff[0])				{				case NAME_INFO:					return NAME_INFO;				case POS_INFO:					cout << "recv flag "<< (unsigned)nextTurn << '\t' << (unsigned)iter->flagStatus << '\n';					if(iter->flagStatus == nextTurn)					{						pos.first = buff[1];						pos.second = buff[2];						cout << "pos:" << pos.first << '\t' << pos.second << '\n';						x = pos.first;						y = pos.second;						return POS_INFO;					}					else						return WRONG_SIDE;				case CHAT_INFO:					strncat(chatBuff, iter->recvhead, MAX_LEN * 20);					strncat(chatBuff, buff + 1, MAX_LEN * 20); 					break;				case FLAG_INFO:					flagInfo = buff[1];					return FLAG_INFO;				default:					return WRONG_INFO;				}			}		}	}	return CHAT_INFO;}int sendChatInfo(fd_set& ws){	vector<client>::iterator iter;	for(iter = clivec.begin(); iter != clivec.end(); iter++)	{		if(FD_ISSET(iter->clifd, &ws))		{			if(iter->send(chatBuff, MAX_LEN) == -3)			{				cout << iter->name << " send wrong\n";				return -1;			}		}	}	return 0;}int NewGame(){	client black, white;	pair<int, int> pos;//pos[0] = x; pos[2] = y		char recvResult;		FD_ZERO(&rset);	FD_ZERO(&wset);		vector<client>::iterator iter;	for(iter = clivec.begin(); iter !=clivec.end(); iter++)	{		iter->getname();		iter->nonblock();		FD_SET(iter->clifd, &rset);		FD_SET(iter->clifd, &wset);		if(iter->clifd + 1 > maxfd)				maxfd = iter->clifd + 1;		cout << "game:" << getpid() << "\tuser:"<< iter->name << '\n';	}		SendFlagInfo();	//cout << (unsigned)clivec[0].flagStatus << '\t' << (unsigned)clivec[1].flagStatus << '\n';		nextTurn = BLACK;	for(int i = 0; i < 15; i++)	{		for(int j =0; j< 15; j++)		{			chessBoard[i][j] = CHESSBOARD_EMPYT;		}	}	fd_set rs, ws;	for( ; ; )	{		rs = rset;		bzero(chatBuff, sizeof(chatBuff));		chatBuff[0] = CHAT_INFO;		//cout << "selecting maxfd:" << maxfd << '\n';		if(select(maxfd, &rs, NULL, NULL, NULL) == -1)		{			if(errno == EINTR)			{				continue;			}			else			{				perror("select");				exit(1);			}		}				recvResult = recv(rs);						if(recvResult == CHAT_INFO)		{			if(strlen(chatBuff) > 0)			{				ws = wset;				if(select(maxfd, NULL, &ws, NULL, NULL) == -1)				{					if(errno == EINTR)					{						continue;					}					else					{						perror("select");						exit(1);					}				}				sendChatInfo(ws);			}		}		else if(recvResult == POS_INFO)		{			if(PositionRight())			{				//cout << "\tSet " << x << '\t' << y << " to " << (unsigned)nextTurn << '\n';				chessBoard[x][y] = nextTurn;				if(!CheckVicCon())				{					if(nextTurn == BLACK)						nextTurn = WHITE;					else if(nextTurn == WHITE)						nextTurn = BLACK;					SendPosInfo(nextTurn);				}				else				{					SendVicInfo();				}			}			else			{				SendErroInfo(WRONG_POSITION, nextTurn);			}		}		else if(recvResult == LEAVE_INFO && clivec.size() < 2)		{			vector<client>::iterator iter;			for(iter = clivec.begin(); iter !=clivec.end(); iter++)			{				FD_CLR(iter->clifd, &wset);				FD_CLR(iter->clifd, &rset);				close(iter->clifd);				clivec.erase(iter);			}			exit(0);		}	}	}int SendFlagInfo(){	srand(time(NULL));	int gambleResult = rand() % 2;	char whiteName[MAXCLNTNAME], blackName[MAXCLNTNAME];		if(gambleResult == 0)	{		clivec[0].flagStatus = BLACK;//black		clivec[1].flagStatus = WHITE;//write		strncpy(whiteName, clivec[1].name, MAXCLNTNAME);		strncpy(blackName, clivec[0].name, MAXCLNTNAME);	}	else	{		clivec[0].flagStatus = WHITE;		clivec[1].flagStatus = BLACK;		strncpy(whiteName, clivec[0].name, MAXCLNTNAME);		strncpy(blackName, clivec[1].name, MAXCLNTNAME);	}		char buff[MAX_LEN];	//cout << "name:\t" << whiteName << "\t" << blackName << '\n';	vector<client>::iterator iter;	for(iter = clivec.begin(); iter !=clivec.end(); iter++)	{		bzero(buff, MAX_LEN);		buff[0] = FLAG_INFO;		buff[1] = iter->flagStatus;		if(iter->flagStatus == WHITE)		{			strncat(buff, blackName, MAX_LEN);		}		else if(iter->flagStatus == BLACK)		{			strncat(buff, whiteName, MAX_LEN);		}		if(iter->send(buff, strlen(buff)) == -3)		{			perror("Send flag");			return 0;		}	}	return 1;}bool SendErroInfo(char wrongType, char sendDestine){	char buff[2];	buff[0] = WRONG_INFO;	buff[1] = wrongType;	vector<client>::iterator iter;	for(iter = clivec.begin(); iter !=clivec.end(); iter++)	{		if(sendDestine == ALL)		{			if(iter->send(buff, 2) == -3)			{				perror("Send error Info");				return false;			}		}		else if(iter->flagStatus == sendDestine)		{			if(iter->send(buff, 2) == -3)			{				perror("Send error Info");				return false;			}		}	}	return true;}bool PositionRight(){	return chessBoard[x][y] ==  CHESSBOARD_EMPYT;}bool SendPosInfo(char sendDestine){	char buff[3];	buff[0] = POS_INFO;	buff[1] = (char)pos.first;	buff[2] = (char)pos.second;	vector<client>::iterator iter;	for(iter = clivec.begin(); iter !=clivec.end(); iter++)	{		//cout << "send flag "<< (unsigned)sendDestine << '\t' << (unsigned)iter->flagStatus << '\n';		if(iter->flagStatus == sendDestine)		{						if(iter->send(buff, 3) == -3)			{				perror("Send error Info");				return false;			}			//cout << "Pos send to " << (unsigned)sendDestine << '\t' << pos.first << '\t' << pos.second << '\n';		}	}	return true;}bool CheckVicCon(){	int length[8];	for(int direction = 0; direction < 8; direction ++)	{		length[direction] = checkLength(pos.first, pos.second, direction);		//cout << "length:\t";		//for(int j = 0; j <= direction; j++)		//{		//	cout << length[direction] <<'\t';		//}		//cout << '\n';		if(direction >= 4 && (length[direction] + length[direction - 4]) > 5)			return true;	}	return false;}int checkLength(int x, int y, int direction){	int length = 1;	int nextX, nextY;	nextX = x;	nextY = y;	for(int i = 0; i < 15 ; i++)	{		switch(direction)		{		case 0:			nextX = nextX - 1;			nextY = nextY - 1;			break;		case 1:			nextX = nextX;			nextY = nextY - 1;			break;		case 2:			nextX = nextX + 1;			nextY = nextY - 1;			break;		case 3:			nextX = nextX + 1;			nextY = nextY;			break;		case 4:			nextX = nextX + 1;			nextY = nextY + 1;			break;		case 5:			nextX = nextX;			nextY = nextY + 1;			break;		case 6:			nextX = nextX - 1;			nextY = nextY + 1;			break;		case 7:			nextX = nextX - 1;			nextY = nextY;			break;		}		//cout << "Length extend pos x: "<< nextX << " y: " << nextY << '\n';		//cout << "Chess board status:" << (unsigned)chessBoard[nextX][nextY] << " Next Turn " << (unsigned)nextTurn << '\n';		if(nextX >= 15 || nextX < 0 || nextY < 0 || nextY >= 15)			break;		if(chessBoard[nextX][nextY] == nextTurn)		{			length++;		}		else 			break;	}	return length;}bool SendVicInfo(){	char buff[4];	buff[0] = VIC_INFO;	buff[1] = nextTurn;	buff[2] = (unsigned)pos.first;	buff[3] = (unsigned)pos.second;	vector<client>::iterator iter;	for(iter = clivec.begin(); iter !=clivec.end(); iter++)	{		//cout << "Victory " << (int)nextTurn << "\tSend to " << (unsigned)iter->flagStatus << '\n';		if(iter->send(buff, 4) == -3)		{			perror("Send error Info");			return false;		}	}	return true;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -