//server
#include<iostream>
using namespace std;
#include<Winsock2.h>
#include<stdlib.h>
#include<time.h>
#include<vector>
#include<string>
#include<Windows.h>
#define _LISTEN_SUM_ 5
#define _IP_ "127.0.0.1"
#define _PORT_ 8080
#pragma comment(lib,"Ws2_32.lib")
#define _CRT_SECURE_NO_WARNINGS
#define _SIZE_ 256
vector<string> user_ip(_SIZE_);
int scos[_SIZE_];//对应相应用户IP的游戏次数
int user_index = 0;
char result[20];//存储游戏结果,排名
int startup(char*ip, int port)
{
	int sock = socket(AF_INET, SOCK_STREAM, 0);//创建套接字
	if (sock < 0)
	{
		printf("sock");
		exit(1);
	}
	struct sockaddr_in local;
	local.sin_family = AF_INET;
	local.sin_port = htons(_PORT_);
	local.sin_addr.s_addr = inet_addr(_IP_);
	if (bind(sock, (struct sockaddr*)&local, sizeof(local))<0)//绑定端口号
	if (sock < 0)
	{
		printf("bind");
		exit(2);
	}
	if (listen(sock, _LISTEN_SUM_) < 0)//设置监听状态
	{
		printf("listen");
		exit(3);
	}
	return sock;

}

void menu(int new_sock)//向用户打印游戏菜单
{
	char buf[1024] = "--------------------------\n1:start play\n2:restart play\n0:quit play\n--------------------------\n";
	send(new_sock, buf, sizeof(buf)-1, 0);
}
int main()
{
	WSADATA wsadata;
	WSAStartup(0x0202, &wsadata);             //初始化winsock
	int sock = startup(_IP_, _PORT_);//获取服务器套接字
	struct sockaddr_in client;
	int len = sizeof(client);
	while (1)
	{
		int new_sock = accept(sock, (struct sockaddr*)&client, &len);//接收用户连接
		user_ip[user_index] = inet_ntoa(client.sin_addr);//存储用户IP
		scos[user_index] = 0;//初始化用户游戏次数
		if (new_sock < 0)
		{
			printf("new_sock");
			continue;
		}
		//cout << "receive sock" << new_sock << endl;
		while (1)
		{
			menu(new_sock);       //给客户端发送游戏指示
			//	play(new_sock);
			char buf[1024];
			buf[0] = '\0';
			srand(unsigned int(time(NULL)));
			int num = rand() % 100;    //产生随机数
			int ret = 0;
			char msg[1024];
			recv(new_sock, buf, sizeof(buf)-1, 0);//接收客户端用户选择:开始游戏还是退出
			ret = atoi(buf);//判断用户输入
			switch (ret)
			{
			case 2:
				strcpy(msg, "your restart play");//重新开始游戏
				send(new_sock, msg, sizeof(msg)-1, 0);
				continue;
			case 0:
				strcpy(msg, "your are quit");//退出游戏
				send(new_sock, msg, sizeof(msg)-1, 0);
				return 0;
			case 1:
				strcpy(msg, "your are start");//开始游戏
				send(new_sock, msg, sizeof(msg)-1, 0);
			}
			while (1)
			{
				memset(buf, '\0', sizeof(buf));
				memset(msg, '\0', sizeof(msg));
				recv(new_sock, buf, sizeof(buf)-1, 0);//接收用户输入数值
				//cout << buf << endl;
				ret = atoi(buf);//转化为数字进行比较
				if (ret > num)//用户输入数字较大
				{
					strcpy(msg, "your input is biger");
					send(new_sock, msg, sizeof(msg)-1, 0);//向用户发送游戏结果:输入数较大
					scos[user_index]++;//游戏次数加1
				}
				else if (ret < num)//用户输入数字较小
				{
					strcpy(msg, "your input is smaller");
					send(new_sock, msg, sizeof(msg)-1, 0);//向用户发送游戏结果:输入数较小
					scos[user_index]++;//游戏次数加1
				}
				else//用户猜对了
				{
					strcpy(msg, "you are right");
					int tmp[_SIZE_] ;
					//在另一个数组进行排序,不更改原纪录数组
					for (int i = 0; i <= user_index; ++i)//排序所有用户游戏次数,得到排名
					{
						tmp[i] = scos[i];
					}
					int flag = 0;
					//冒泡排序得到排行榜
					for (int i = 0; i <= user_index - 1; ++i)
					{
						flag = 0;
						for (int j = 0; j <= user_index - i - 1; ++j)
						{
							if (tmp[j]>tmp[j + 1])
							{
								swap(tmp[j], tmp[j + 1]);
								flag = 1;
							}

							if (flag == 0)//冒泡排序优化:如果已经有序,直接退出循环
								break;
						}
					}
					int top = 0;//存储排名
					for (int i = 0; i <= user_index; ++i)
					{
						if (tmp[i] == scos[user_index])
						{
							//排名从一开始
							top = i + 1;
							break;
						}
					}
					//cout << scos[user_index] << " " << top;
					sprintf(result, "you IP is %s,you play %c counts,is top %c", user_ip[user_index].c_str(),scos[user_index]+'0',top+'0');//向客户输出猜测次数,并返回排名
					strcat(msg,result);
					send(new_sock, msg, sizeof(msg)-1, 0);//向用户发送游戏结果
					scos[user_index] = 0;//重置猜测次数为0
					break;
				}
			}
		}
	}
	return 0;
}
//client
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
#include<Winsock2.h>
#include<stdlib.h>
#define _IP_ "127.0.0.1"
#define _PORT_ 8080
#pragma comment(lib,"Ws2_32.lib")
int main()
{
	WSADATA wsadata;
	WSAStartup(0x0202, &wsadata);                //初始化winsock
	int sock = socket(AF_INET, SOCK_STREAM, 0);//客户端产生套接字,不需绑定
	if (sock < 0)
	{
		printf("sock");
		exit(1);
	}
	struct sockaddr_in remote;
	remote.sin_family = AF_INET;
	remote.sin_port = htons(_PORT_);
	remote.sin_addr.s_addr = inet_addr(_IP_);
	int ret = connect(sock, (struct sockaddr*)&remote, sizeof(remote));//连接服务器
	//gets(buf);
	while (1)
	{
		//play(sock);
		char buf[1024];
		buf[0] = '\0';
		recv(sock, buf, sizeof(buf)-1, 0);//接收服务器端游戏说明
		cout << buf << endl;//打印游戏指示
		gets(buf);//接收用户选择
		send(sock, buf, sizeof(buf)-1, 0);//发送选择
		recv(sock, buf, sizeof(buf)-1, 0);//接收反馈信息
		if (strcmp(buf, "your restart play") == 0)//根据反馈信息得到用户接下来动作
			continue;//重新开始游戏
		else if (strcmp(buf, "your are quit") == 0)
			return 0;//退出游戏
		else if (strcmp(buf, "your are start") == 0)//开始游戏
		{
			cout << "start play" << endl;
			cout << "please input num in 0~99" << endl;
		}
		while (1)
		{
			printf("please input num:");
		
			gets(buf);//输入数值
			send(sock, buf, sizeof(buf)-1, 0);//想服务器发送用户数值
			//memset(buf, '\0', sizeof(buf));
			recv(sock, buf, sizeof(buf)-1, 0);//接收用户反馈信息
			cout << buf << endl;
			if (strncmp(buf, "you are right", strlen("you are right")) == 0)//猜对退出
			{

				cout << "you win" << endl;
				break;
			}
			memset(buf, '\0', sizeof(buf));//重置buf
		}
	}
}

wKioL1eB4ULBbRatAADrS1cMXLU758.jpg