diff --git a/Makefile b/Makefile index 2de01ca..d94ac21 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,8 @@ -search_tree:search_tree.c +.PHONY:all +all:server client +server: game.c server.c gcc -o $@ -g $^ -.PHONY: - clean +client: game.c client.c +.PHONY:clean clean: - rm -f search_tree - + rm -f server client diff --git a/client.c b/client.c index 70a4ec6..368cd88 100644 --- a/client.c +++ b/client.c @@ -1,59 +1,110 @@ -#include -#include -#include -#include +#include "game.h" #include +#include +#include #include -#include #include -void SocketCommon(int sock, struct sockaddr_in* server) +#include + +void Menu() { - char buf[1024]; - struct sockaddr_in peer; - while(1) - { - socklen_t len = sizeof(peer); - printf("Please Enter# \n"); - fflush(stdout); - ssize_t s = read(0,buf,sizeof(buf)-1); - if(s > 0) - { - buf[s-1] = 0; - sendto(sock,buf,strlen(buf),0,(struct sockaddr*)server,sizeof(*server)); - ssize_t _s = recvfrom(sock,buf,sizeof(buf)-1,0,(struct sockaddr*)&peer,&len); - if(_s > 0) - { - buf[_s] = 0; - printf("server echo# %s\n",buf); - } + printf("==================================\n"); + printf("|| 1.开始游戏 0.退出游戏 ||\n"); + printf("==================================\n"); +} +void Game(int sock) +{ + Point point_server,point_client; + char board[ROWS][COLS]; + InitBoard(board,ROWS,COLS); + PrintBoard(board,ROWS,COLS); + ssize_t s; + int x,y; + while(1){ + printf("请下子(输入坐标)> "); + scanf("%d%d",&x,&y); + point_client.row = x-1; + point_client.col = y-1; + ClientMove(board,&point_client); + PrintBoard(board,ROWS,COLS); + write(sock,(void*)&point_client,sizeof(point_client)); + if(GameState(board,&point_client) == 'X') + { + printf("You win!\n"); + break; + } + else if(GameState(board,&point_client) == 'p') + { + printf("平局!\n"); + break; + } + s = read(sock,(void*)&point_server,sizeof(point_server)); + if(s == 0) + { + printf("Server quit\n"); + return; + } + ServerMove(board,&point_server); + PrintBoard(board,ROWS,COLS); + if(GameState(board,&point_server) == 'O') + { + printf("Server win!\n"); + break; + } + else if(GameState(board,&point_server) == 'p') + { + printf("平局!\n"); + break; } } } -int main(int argc,char *argv[]) +int main(int argc, char* argv[]) { - if(argc < 3) + if(argc != 3) { - perror("argc"); + printf("Usage: ./server [ip] [port]\n"); exit(1); } - //创建 socket 文件描述符 - //AF_INET ipv4地址类型 - //SOCK_DGRAM udp类型 - //0 默认使用SOCK_DGRAM类型 - int sock = socket(AF_INET,SOCK_DGRAM,0); + + int sock = socket(AF_INET,SOCK_STREAM,0); if(sock < 0) { perror("socket"); - exit(2); + exit(1); } - struct sockaddr_in server; - server.sin_family = AF_INET;//ipv4地址类型 - server.sin_port = htons(atoi(argv[2]));//端口号 - server.sin_addr.s_addr = inet_addr(argv[1]);//ipv4地址转换 因为输入的是点分十进制 - + struct sockaddr_in client; + client.sin_family = AF_INET; + client.sin_addr.s_addr = inet_addr(argv[1]); + client.sin_port = htons(atoi(argv[2])); + int ret = connect(sock,(const struct sockaddr*)&client,sizeof(client)); + if(ret < 0) + { + perror("connect"); + exit(2); + } + Menu(); + int state; + while(1) + { + printf("请做出你的选择> "); + scanf("%d",&state); + if(state == 1) + { + Game(sock); + }else if(state == 0) + { + break; + } + else + { + printf("选择错误\n"); + Menu(); + sleep(2); + } + } - SocketCommon(sock,&server); + close(sock); return 0; } diff --git a/game.c b/game.c new file mode 100644 index 0000000..a4929f7 --- /dev/null +++ b/game.c @@ -0,0 +1,308 @@ +#include "game.h" +#include +#include +#include +#include +#include + +//初始化棋盘 +void InitBoard(char board[ROWS][COLS],int row, int col) +{ + memset(board,' ',row*col*sizeof(char)); +} +//打印棋盘 +void PrintBoard(char board[ROWS][COLS],int row,int col) +{ + int i = 0; + printf(" 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10\n"); + for(; i < row;i++) + { + printf("%2d ",i+1); + int j = 0; + for(; j < col;j++) + { + if( j == col-1 ) + { + printf(" %c \n",board[i][j]); + if(i != row-1) + printf(" ---|---|---|---|---|---|---|---|---|---\n"); + break; + } + printf(" %c ",board[i][j]); + printf("|"); + } + + } +} + +//判断棋盘是否满了 +int IsFall(char board[ROWS][COLS]) +{ + size_t i = 0; + for(; i < ROWS;i++) + { + size_t j = 0; + for(; j < COLS; j++) + { + if(board[i][j] == ' ') + return 0; + } + } + return 1; +} +//移动 +void CommonMove(char board[ROWS][COLS],Point* point,char ch) +{ + if(point == NULL) + { + return; + } + int x = point->row; + int y = point->col; + //如果棋盘满了的话就退出循环,也就是不能再下子了 + while(1) + { + if(x >= 0 && x < ROWS && y >= 0 && y < COLS){ + if(board[x][y] == ' ') + { + board[x][y] = ch; + point->row = x; + point->col = y; + break; + } + else + { + printf("坐标输入有误,请重新输入坐标: "); + scanf("%d%d",&x,&y); + x--; + y--; + } + } + else{ + printf("坐标输入有误,请重新输入坐标: "); + scanf("%d%d",&x,&y); + x--; + y--; + } + } +} +//客户端移动 +void ClientMove(char board[ROWS][COLS],Point* point) +{ + CommonMove(board,point,'X'); +} + +//服务器移动 +void ServerMove(char board[ROWS][COLS],Point* point) +{ + CommonMove(board,point,'O'); +} +//列齐 +int ColState(char board[ROWS][COLS],Point* point) +{ + int x = point->row; + int y = point->col; + int count = 1; + while(x-1 >= 0) + { + if(board[x][y] != board[x-1][y]) + break; + count++; + if(count == 5) + { + //如果往上遍历已经够了五个,说明已经赢了,直接返回 + return count; + } + x--; + } + //到这里说明当前点往上走是不满足条件的 + //但是已经走到了最上面的点,所以从临界点往相反方向找 + //必须要找到五个连续的才算满足条件 + count = 1;//count 重新被设定为1 + while(x+1 <= ROWS) + { + if(board[x][y] == board[x+1][y]) + { + count++; + if(count == 5) + { + return count; + } + x++; + } + else + { + //n 代表当前状态未满足赢的条件 + return 0; + } + } + return 0; +} +//行齐 +int RowState(char board[ROWS][COLS],Point* point) +{ + int x = point->row; + int y = point->col; + int count = 1; + while(y-1 >= 0) + { + if(board[x][y] != board[x][y-1]) + break; + count++; + if(count == 5) + { + //如果往左遍历已经够了五个,说明已经赢了,直接返回 + return count; + } + y--; + } + //到这里说明当前点往左走是不满足条件的 + //但是已经走到了最左面的点,所以从临界点往相反方向找 + //必须要找到五个连续的才算满足条件 + count = 1;//count 重新被设定为1 + while(y+1 <= COLS) + { + if(board[x][y] == board[x][y+1]) + { + count++; + if(count == 5) + { + return count; + } + y++; + } + else + { + //n 代表当前状态未满足赢的条件 + return 0; + } + } + return 0; +} +//左上到右下的对角线 +int UpLeftState(char board[ROWS][COLS],Point* point) +{ + int x = point->row; + int y = point->col; + int count = 1; + while(x-1 >= 0 && y-1 >= 0 ) + { + if(board[x][y] != board[x-1][y-1]) + break; + count++; + if(count == 5) + { + //如果往左上遍历已经够了五个,说明已经赢了,直接返回 + return count; + } + x--; + y--; + } + //到这里说明当前点往左上走是不满足条件的 + //但是已经走到了最左上的点,所以从临界点往相反方向找 + //必须要找到五个连续的才算满足条件 + count = 1;//count 重新被设定为1 + while(x+1 <= ROWS && y+1 <= COLS) + { + if(board[x][y] == board[x+1][y+1]) + { + count++; + if(count == 5) + { + return count; + } + x++; + y++; + } + else + { + //n 代表当前状态未满足赢的条件 + return 0; + } + } + return 0; +} +//右上到左下的对角线 +int UpRightState(char board[ROWS][COLS], Point* point) +{ + int x = point->row; + int y = point->col; + int count = 1; + while(x-1 >= 0 && y+1 <= COLS) + { + if(board[x][y] != board[x-1][y+1]) + break; + count++; + if(count == 5) + { + //如果往右上遍历已经够了五个,说明已经赢了,直接返回 + return count; + } + x--; + y++; + } + //到这里说明当前点往右上走是不满足条件的 + //但是已经走到了最右上面的点,所以从临界点往相反方向找 + //必须要找到五个连续的才算满足条件 + count = 1;//count 重新被设定为1 + while(x+1 <= ROWS && y-1 <=COLS) + { + if(board[x][y] == board[x+1][y-1]) + { + count++; + if(count == 5) + { + return count; + } + x++; + y--; + } + else + { + //n 代表当前状态未满足赢的条件 + return 0; + } + } + return 0; +} +//返回游戏进行状态 +char GameState(char board[ROWS][COLS],Point* point) +{ + if(point == NULL) + { + return 'e'; + } + //判断当前点所在列是否是连续五个子儿 + if(ColState(board,point) == 5) + { + return board[point->row][point->col]; + } + //判断当前点所在行是否是连续五个子儿 + else if(RowState(board,point) == 5) + { + return board[point->row][point->col]; + } + //判断当前点所在左上与右下的对角线是否满足条件 + else if(UpLeftState(board,point) == 5) + { + return board[point->row][point->col]; + } + //判断当前点所在左上与右下的对角线是否满足条件 + else if(UpRightState(board,point) == 5) + { + return board[point->row][point->col]; + } + else if(IsFall(board)) + { + //平局 + return 'p'; + } + //当前没有输赢,继续游戏 + return 'g'; +} + +//////////////////////////////////////////// +////////TEST PART +/////////////////////////////////////////// + + diff --git a/game.h b/game.h new file mode 100644 index 0000000..1ab0e7e --- /dev/null +++ b/game.h @@ -0,0 +1,35 @@ +#pragma once +#include +#include +#include +#include + +#define ROWS 10 +#define COLS 10 + + +typedef struct Point{ + int row; + int col; +}Point; + +//初始化棋盘 +void InitBoard(char board[ROWS][COLS],int row, int col); + +//打印棋盘 +void PrintBoard(char board[ROWS][COLS], int row, int col); + +//共同移动 +void CommonMove(char board[ROWS][COLS],Point* point,char ch); + +//客户端移动 +void ClientMove(char board[ROWS][COLS],Point* point); + +//服务器移动 +void ServerMove(char board[ROWS][COLS],Point* point); + + +//判断输赢 +char GameState(char board[ROWS][COLS],Point* point); + + diff --git a/server.c b/server.c index bb1d3f7..29fcd92 100644 --- a/server.c +++ b/server.c @@ -1,57 +1,97 @@ -#include -#include -#include -#include +#include "game.h" #include +#include +#include #include -#include -void SocketCommon(int sock) -{ - char buf[1024]; - struct sockaddr_in client; - while(1) - { - socklen_t len = sizeof(client); - ssize_t s = recvfrom(sock,buf,sizeof(buf)-1,0,(struct sockaddr*)&client,&len); - if(s > 0) - { - buf[s] = 0; - printf("[%s:%d]:%s\n",inet_ntoa(client.sin_addr),ntohs(client.sin_port),buf); - fflush(stdout); - sendto(sock,buf,strlen(buf),0,(struct sockaddr*)&client,sizeof(client)); - } - } -} +#include +#include -int main(int argc,char *argv[]) +int main(int argc, char* argv[]) { - if(argc < 3) + if(argc != 3) { - perror("argc"); + printf("Usage: ./server [ip] [port]\n"); exit(1); } - //创建 socket 文件描述符 - //AF_INET ipv4地址类型 - //SOCK_DGRAM udp类型 - //0 默认使用SOCK_DGRAM类型 - int sock = socket(AF_INET,SOCK_DGRAM,0); + + int sock = socket(AF_INET,SOCK_STREAM,0); if(sock < 0) { perror("socket"); - exit(2); + exit(1); } - struct sockaddr_in local; - local.sin_family = AF_INET;//ipv4地址类型 - local.sin_port = htons(atoi(argv[2]));//端口号 - local.sin_addr.s_addr = inet_addr(argv[1]);//ipv4地址转换 因为输入的是点分十进制 + struct sockaddr_in server; + server.sin_family = AF_INET; + server.sin_addr.s_addr = inet_addr(argv[1]); + server.sin_port = htons(atoi(argv[2])); - if(bind(sock,(const struct sockaddr*)&local,sizeof(local)) < 0) + int ret = bind(sock,(const struct sockaddr*)&server,sizeof(server)); + if(ret < 0) { perror("bind"); + exit(2); + } + ret = listen(sock,5); + if(ret < 0) + { + perror("listen"); exit(3); } - SocketCommon(sock); + for(;;) + { + struct sockaddr_in client; + socklen_t len; + int client_sock = accept(sock,(struct sockaddr*)&client,&len); + if(client_sock < 0) + { + continue; + } + ssize_t s; + Point point_server,point_client; + char board[ROWS][COLS]; + InitBoard(board,ROWS,COLS); + int x,y; + while(1){ + s = read(client_sock,(void*)&point_client,sizeof(point_client)); + if(s == 0) + { + printf("Client quit...\n"); + close(client_sock); + } + ClientMove(board,&point_client); + PrintBoard(board,ROWS,COLS); + if(GameState(board,&point_client) == 'X') + { + printf("Client win!\n"); + break; + } + else if(GameState(board,&point_client) == 'p') + { + printf("平局!\n"); + break; + } + printf("请下子(输入坐标)> "); + scanf("%d%d",&x,&y); + point_server.row = x-1; + point_server.col = y-1; + ServerMove(board,&point_server); + PrintBoard(board,ROWS,COLS); + write(client_sock,(void*)&point_server,sizeof(point_server)); + if(GameState(board,&point_client) == 'O') + { + printf("You win!\n"); + break; + } + else if(GameState(board,&point_client) == 'p') + { + printf("平局!\n"); + break; + } + + }//游戏下完了 + } + close(sock); return 0; }