📄 fives.c
字号:
//gcc fives.c -o fives#include <fcntl.h>#include <netinet/in.h>#include <unistd.h>#include <stdio.h>#include <string.h>#include <stdlib.h>#include <sys/socket.h>#include <sys/select.h>#include <sys/types.h>/////////////////////////////////////#define MAXLEN 1024#define PROTOCOLLEN 24 //协议数据包固定常度(待所有协议确定长度后选定一个最长的,目前最长数据包是24)#define BACKLOG 3#define PORT 55555 //五子棋游戏服务器程序端口#define ROWCOL 20 //棋盘行列数量,每个棋子所占空格空间,屏幕宽度,屏幕高度-这四个常量定义有关系 //棋子放在横竖线的焦点上#define USER1 0 //用户1编号#define USER2 1 //用户2编号#define USER_NAME_LEN 5 //用户名字符串长度#define QIPAN_NULL 'N' //棋盘空位#define QIZI_SIZE 20 //每个棋子所占空格空间#define COLOR_BG 255,255,128 //棋盘背景颜色-黄色#define COLOR_LINE 0,0,0 //棋盘划线颜色-黑色#define COLOR_USER1 255,0,0 //用户1棋子颜色-红色#define COLOR_USER2 0,0,255 //用户2棋子颜色-蓝色#define SCREEN_W 420 //屏幕宽度#define SCREEN_H 420 //屏幕高度#define OFFSET_X QIZI_SIZE //棋盘划线偏移量x#define OFFSET_Y QIZI_SIZE //棋盘划线偏移量y#define TITLE_LEN 128 //标题缓冲区长度//服务器端协议编号处理函数定义#define REGIST_USER_NAME 1001 //注册用户姓名p_1001#define SET_QIZI_POSITION 1002 //设置棋子位置p_1002#define GAME_CONTINUE 1003 //继续新一轮游戏p_1003#define NOTE_SERVER_START 1004 //通知服务器游戏可以开始了p_1004//客户端协议编号处理函数定义#define NOTE_USER_OVERFLOW 2001 //提示用户已满u_2001#define NOTE_USER_GAMESTART 2002 //提示用户游戏开始u_2002#define NOTE_USER_WAITFOROTHER 2003 //通知用户连接成功,等待另一个用户连接u_2003#define NOTE_USER_ANOTHEREXIT 2004 //一个用户退出游戏,重设游戏变量,通知另一个用户等待新用户u_2004#define NOTE_USER_RESULT 2005 //通知两个用户本回合棋盘落子情况和获胜情况 //若游戏结束,等待用户确认重新开始u_2005#define NOTE_USER_START 2006 //通知用户游戏可以开始了u_2006//游戏状态定义#define GAME_READY 0#define GAME_RUN 1#define GAME_OVER 2///////////////////////////////////////系统变量定义int qipan[ROWCOL][ROWCOL], currentuser; //棋盘,本回合落子用户int user_fd[2], user_flag[2]; //用户连接号,用户同步等待标志char user_name[2][USER_NAME_LEN]; //用户名字int game_state; //游戏状态int *protocol_num; //协议编号指针char *protocol_context; //协议内容指针int fd_max, fd_listen, fd_conn, selectn, len; //以下是处理用户连接发送命令用的系统变量fd_set set_temp, set_all;char receive_buf[MAXLEN], *temp;char send_buf[MAXLEN];struct sockaddr_in addr_c, addr_s;struct timeval timeout;/////////////////////////////////////////////////系统函数////////////////////////////////////////////////////////处理不同命令请求的代理程序//客户端每增加新的处理请求都需要在双方程序开始增加一个1000开始的协议编号的定义,并在此增加该协议的处理函数void s_delegate(int user, char *buf){ protocol_num=(int *)buf; switch (*protocol_num) { case REGIST_USER_NAME : {//注册用户姓名p_1001 p_1001(user, buf); break; } case SET_QIZI_POSITION : {//设置棋子位置p_1002 p_1002(user, buf); break; } case GAME_CONTINUE : {//继续新一轮游戏p_1003 p_1003(user, buf); break; } case NOTE_SERVER_START: {//通知服务器游戏可以开始了p_1004 p_1004(user, buf); break; } default : { break;} }}///////////////////////////////////////初始化游戏s_init(){ memset(qipan, QIPAN_NULL, sizeof(int)*ROWCOL*ROWCOL);//棋盘置空 user_flag[USER1]=0;//用户继续游戏的同步标志 user_flag[USER2]=0; game_state=GAME_READY;//游戏状态}///////////////////////////////////////////////////游戏处理函数///////////////////////////////////////////////////判断游戏输赢平int g_result(){ //分析棋盘布局,判断游戏输赢平的结果qipan[ROWCOL][ROWCOL] //若有输赢,返回获胜用户的编号(0,1),若平局返回2,未决出胜负平结果返回-1 int result, row, col; //默认是平局,平局返回2;如果棋盘还有空白说明肯定未决出胜负,未决出胜负返回-1 result=2; for(row=0; row<=ROWCOL; row++){ for(col=0; col<=ROWCOL; col++){ if(!(qipan[row][col]==USER1) && !(qipan[row][col]==USER2)){ result=-1; break; } } if(result==-1) break; } //判断双方是否有已经连接成功5个棋子的情况决定是否有胜出者 //横向判断 for(row=0; row<ROWCOL; row++){ for(col=0; col<ROWCOL - 5 + 1; col++){ if((qipan[row][col]==USER1) && (qipan[row][col+1]==USER1) && (qipan[row][col+2]==USER1) \ && (qipan[row][col+3]==USER1) && (qipan[row][col+4]==USER1)) {result=USER1; return result;}//USER1胜出 if((qipan[row][col]==USER2) && (qipan[row][col+1]==USER2) && (qipan[row][col+2]==USER2) \ && (qipan[row][col+3]==USER2) && (qipan[row][col+4]==USER2)) {result=USER2; return result;}//USER2胜出 } } //纵向判断 for(row=0; row<ROWCOL - 5 + 1; row++){ for(col=0; col<ROWCOL; col++){ if((qipan[row][col]==USER1) && (qipan[row+1][col]==USER1) && (qipan[row+2][col]==USER1) \ && (qipan[row+3][col]==USER1) && (qipan[row+4][col]==USER1)) {result=USER1; return result;}//USER1胜出 if((qipan[row][col]==USER2) && (qipan[row+1][col]==USER2) && (qipan[row+2][col]==USER2) \ && (qipan[row+3][col]==USER2) && (qipan[row+4][col]==USER2)) {result=USER2; return result;}//USER2胜出 } } //撇向判断 for(row=0; row<ROWCOL - 5 + 1; row++){ for(col=0 + 5 - 1; col<ROWCOL; col++){ if((qipan[row][col]==USER1) && (qipan[row+1][col-1]==USER1) && (qipan[row+2][col-2]==USER1) \ && (qipan[row+3][col-3]==USER1) && (qipan[row+4][col-4]==USER1)) {result=USER1; return result;}//USER1胜出 if((qipan[row][col]==USER2) && (qipan[row+1][col-1]==USER2) && (qipan[row+2][col-2]==USER2) \ && (qipan[row+3][col-3]==USER2) && (qipan[row+4][col-4]==USER2)) {result=USER2; return result;}//USER2胜出 } } //那向判断 for(row=0; row<ROWCOL - 5 + 1; row++){ for(col=0; col<ROWCOL - 5 + 1; col++){ if((qipan[row][col]==USER1) && (qipan[row+1][col+1]==USER1) && (qipan[row+2][col+2]==USER1) \ && (qipan[row+3][col+3]==USER1) && (qipan[row+4][col+4]==USER1)) {result=USER1; return result;}//USER1胜出 if((qipan[row][col]==USER2) && (qipan[row+1][col+1]==USER2) && (qipan[row+2][col+2]==USER2) \ && (qipan[row+3][col+3]==USER2) && (qipan[row+4][col+4]==USER2)) {result=USER2; return result;}//USER2胜出 } } //双方都没有获胜的,返回开始默认的平局或者未决出胜负关系 return result;}///////////////////////////////////////////////////用户处理函数///////////////////////////////////////////////////提示用户已满,不能在连接到游戏服务器u_2001(int user_fd){//本函数发送实际有用数据长度是:sizeof(int)=4 protocol_num=(int *)send_buf; *protocol_num=NOTE_USER_OVERFLOW;//协议号码sizeof(int) write(user_fd, send_buf, PROTOCOLLEN); fsync(user_fd); close(user_fd);}//通知用户游戏开始u_2002(int user){//本函数发送数据长度是:sizeof(int)+sizeof(int)+sizeof(int)+USER_NAME_LEN=22 protocol_num=(int *)send_buf; *protocol_num=NOTE_USER_GAMESTART;//协议号码sizeof(int) protocol_num=protocol_num+1; *protocol_num=user;//分配一个用户编号sizeof(int) protocol_num=protocol_num+1; *protocol_num=currentuser;//本回合落子的用户编号sizeof(int) protocol_num=protocol_num+1; protocol_context=(char *)protocol_num; if(user==USER1) bcopy(user_name[USER2], protocol_context, USER_NAME_LEN);//对方姓名USER_NAME_LEN else bcopy(user_name[USER1], protocol_context, USER_NAME_LEN); write(user_fd[user], send_buf, PROTOCOLLEN); fsync(user_fd[user]);}//通知用户连接成功,等待另一个用户连接u_2003(int user){//本函数发送数据长度是:sizeof(int)=4 protocol_num=(int *)send_buf; *protocol_num=NOTE_USER_WAITFOROTHER;//协议号码sizeof(int) write(user_fd[user], send_buf, PROTOCOLLEN); fsync(user_fd[user]);}//一个用户退出游戏,重新设置用户和游戏变量,通知另一个用户等待新的用户到来u_2004(int user){//本函数发送数据长度是:sizeof(int)=4 protocol_num=(int *)send_buf; *protocol_num=NOTE_USER_ANOTHEREXIT;//协议号码sizeof(int)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -