C语言大作业——匹配系统

c语言大作业,匹配系统,开了三个线程,c89,需要支持pthread.h库。

文件1 color.h

#include <windows.h>
const WORD FORE_BLUE   = FOREGROUND_BLUE;           //蓝色文本属性  
const WORD FORE_GREEN  = FOREGROUND_GREEN;          //绿色文本属性
const WORD FORE_RED    = FOREGROUND_RED;            //红色文本属性  
const WORD FORE_YELLOW = 6; //(FORE_RED | FORE_GREEN);     //黄色文本属性   //c89标准不允许 (FORE_RED | FORE_GREEN)操作,所以直接给出值了,但是可移植性降低了。 
const WORD FORE_GRAY   = FOREGROUND_INTENSITY;      //灰色文本属性                  //如果是c99标准请去掉数字换成后面的表达式 
const WORD BACK_BLUE   = BACKGROUND_BLUE;           //蓝色背景属性  
const WORD BACK_GREEN  = BACKGROUND_GREEN;          //绿色背景属性  
const WORD BACK_RED    = BACKGROUND_RED;            //绿色背景属性  
const WORD BACK_PURPLE = 80; //(BACK_BLUE | BACK_RED);      //紫色背景属性  
const WORD BACK_CYAN   = 48;//(BACK_BLUE | BACK_GREEN);    //青色背景属性  
const WORD BACK_YELLOW = 96;//(BACK_RED | BACK_GREEN);     //黄色背景属性  
const WORD BACK_GRAY   = BACKGROUND_INTENSITY;      //灰色背景属性
// 以下为windows改变窗口颜色调用 

#define get_yellow SetConsoleTextAttribute(handle_out, FORE_YELLOW) //黄色
#define get_red SetConsoleTextAttribute(handle_out, FOREGROUND_INTENSITY | FORE_RED)//红色
#define get_white SetConsoleTextAttribute(handle_out, FORE_GREEN | FORE_BLUE | FORE_RED) //将三原色混合不就是白色(原色嘛)哈哈哈。 
#define get_blue SetConsoleTextAttribute(handle_out, FORE_BLUE) //蓝色
#define get_green SetConsoleTextAttribute(handle_out, FORE_GREEN) //绿色
//暂时只用的上这么多颜色啦

void getcolor()
{
		HANDLE handle_out = GetStdHandle(STD_OUTPUT_HANDLE);    //获得标准输出设备句柄  
		CONSOLE_SCREEN_BUFFER_INFO csbi;                        //定义窗口缓冲区信息结构体  
		GetConsoleScreenBufferInfo(handle_out, &csbi);      //获得窗口缓冲区信息
}

文件2 match_data.h

#include<stdio.h>
#include<stdlib.h>
#include<pthread.h>
struct people
{
	int id;//用户id 
	char name[500];//用户名 
	int grade; //分数 
	int wait_time; //匹配等待时间 
};
struct gaming
{
	struct people a;
	struct people b;
	int average_score;
	int time_ing;
};

文件3 match_list.h


///存链表操作头文件
#include "sstring.h"
//#include "solve_error.h"
#include"menu.h"
extern int list_size;
typedef struct data_list //链表的结构,包含了match_data.h中的本程序基本数据(id名字和分数),以及一个指向下一个的指针。 
{
	struct people data;
	struct data_list *next;

} list_data;
struct data_list * list_inint(int n) //初始化一个链表(list_data类型),其中包含n个表,不过本程序不需要初始的n个表,只需要初始化。 
{
	list_data * head;
	list_data * tail;
	list_data * p;
	head = tail = p = NULL;
	list_size=n;
	while (n--)
	{
		p = (list_data *) malloc(sizeof(list_data));//给表分配空间 
		scanf("%d%s%d", &p->data.id, p->data.name, &p->data.grade);
		
		p->next = NULL;

		if (head == NULL)
		{
			head = p;
			tail = p;
		}
		else
		{
			tail->next = p;
			tail = p;
		}
	}
	return head;//返回头指针 
}
list_data * list_add(list_data *head,struct people a,int * kase)//向链表中插入一个数据(插入保证链表按照 “i d” 排好序)。 
{
	list_size++;
	list_data * p = (list_data *) malloc(sizeof(list_data));//给表分配空间 
	p->data=a;
	p->next=NULL;
	list_data * head1 = head; //创建新表头——用来遍历到刚好比id小的地方,然后放入此次数据。 
	if(head==NULL||head->data.id>a.id)
	{
	p->next=head;
	head=p;
	return head;
	}
	else
	{
		while(head1->next!=NULL && head1->next->data.id <= a.id)
		{
			head1=head1->next;
		}
		if(head1->data.id == a.id)//如果出现重id则出现错误输入。
		{
			free(p);//出错记得释放空间,防止出现漏洞。
			error(1);//输出错误信息。
			list_size--;
			*kase=1;
		}
		else//插入 
		{
			p->next = head1->next;
			head1->next = p;
		}
	}
	return head;
	//返回新的头指针。
}
list_data * list_remove(list_data *head,struct people a,int *kase)
{
	list_size--;
	if(head == NULL)
	{
		error(2);
		list_size++;
		*kase = 1;
		return head;
	}
	if(head->data.id == a.id)
	{
	list_data * temp = head;	
	head=head->next;
	free(temp);
	}
	else
	{
		list_data * head1 = head;
		while((head1->next != NULL) && (head1->next->data.id !=a.id) )//遍历到要删除的人 
		{
			head1=head1->next;
		}
		
		if(head1->next == NULL)//错误2,删除人物不存在。 
		{
			error(2);
			list_size++;
			*kase = 1;
		}
		else
		{
			list_data * temp = head1->next;
			
			head1->next=head1->next->next; //删除操作
			free(temp);//记得释放内存。 
		} 
	}
	return head;
}
int remove_now(list_data * a)//删除当前节点 
{
	if(a == NULL)
	return 0;
	
	if(a->next==NULL)
	{
		list_data * temp =a;
		a=NULL;
		free(temp);
		list_size--;
		return 1;
	}
	a->data=a->next->data;
	
	list_data * temp =a->next;
	
	a->next=a->next->next;
	
	free(temp);
	
	list_size--;
	
	return 1;
	
}
int list_print(list_data * head)
{
	HANDLE handle_out = GetStdHandle(STD_OUTPUT_HANDLE);    //获得标准输出设备句柄  
	CONSOLE_SCREEN_BUFFER_INFO csbi;                        //定义窗口缓冲区信息结构体  
	GetConsoleScreenBufferInfo(handle_out, &csbi);      //获得窗口缓冲区信息
	list_data *p =head;
	if(p == NULL)
	{
		get_red;
		printf("there if no one in the match pool\n");
		get_white;
	}
	else
	{
		int i=1;
		get_yellow;
		while(p!=NULL)
		{
			printf("%3d:id=%2d,name=%s,grade=%5d  waiting for %d seconds\n",i,p->data.id,p->data.name,p->data.grade,p->data.wait_time);
			p = p->next;
			i++;
		}
		get_white;
		
	}
	return 1;
}

文件4 menu.h

#include<stdio.h>
//#include"color.h"
#include"solve_error.h"
int menu()//主菜单函数 
{
	HANDLE handle_out = GetStdHandle(STD_OUTPUT_HANDLE);    //获得标准输出设备句柄  
	CONSOLE_SCREEN_BUFFER_INFO csbi;                        //定义窗口缓冲区信息结构体  
	GetConsoleScreenBufferInfo(handle_out, &csbi);      //获得窗口缓冲区信息 
	printf("制作者:");
    get_yellow;
	printf("罗春阳\n\n");Sleep(1*20);
    get_white;                                              //这些东西都是调字体颜色的,可以忽略 
  	printf("主菜单\n");Sleep(1*20);
  	get_green;
	printf("                     注:可以输入'q'(加回车)来刷新页面,(命令不分大小写,可随意大小写)\n"); 
	
  	get_white;
  	printf("########################################################################################################\n");Sleep(1*20);
  	printf("##");
  	get_red;
  	printf("             功能1:加入或删除用户进入匹配池。                  功能2:查看匹配池或游戏池情况       ");Sleep(1*20);
  	get_white;
	printf("##\n"); 
  	printf("##               add/remove ‘id’ ‘username’ ‘grade’       fgamewait fgameing(-t)(-av) fpoolsize ##\n");Sleep(1*20);
  	printf("##");
  	get_red;
  	printf("             功能3:结束某个用户的游戏。                        功能4:查看各种历史                 ");Sleep(1*20);
  	get_white;
	printf("##\n");  
	printf("##               gameover ‘id’ or gameover ‘username’             system-history  history         ##\n");Sleep(1*20);
	printf("##");
	get_red;
	printf("             功能5:切换系统信息输出模式。                      功能6:查看帮助                     ");Sleep(1*20);
	get_white;
	printf("##\n");
	printf("##               system-change                                        help                            ##\n");Sleep(1*20); 
	printf("##                                              输入\"exit\"退出程序                                    ##\n");Sleep(1*20);
	printf("########################################################################################################\n\n");Sleep(1*20);
	printf("输入代码后回车即可执行相应请求\n"); Sleep(1*20);
	return 1; 
	
}

int match_exit()
{
	HANDLE handle_out = GetStdHandle(STD_OUTPUT_HANDLE);    //获得标准输出设备句柄  
	CONSOLE_SCREEN_BUFFER_INFO csbi;                        //定义窗口缓冲区信息结构体  
	GetConsoleScreenBufferInfo(handle_out, &csbi);      //获得窗口缓冲区信息 
	
	
	printf("             ■          ■     \n");Sleep(1*50);
	printf("   ■      ■■■■      ■     \n");Sleep(1*50);
	printf("     ■    ■    ■      ■     \n");Sleep(1*50);
	printf("     ■    ■■■■      ■     \n");Sleep(1*50);
	printf("           ■    ■■■■■■   \n");Sleep(1*50);
	printf(" ■■■    ■■■■      ■     \n");Sleep(1*50);
	printf("     ■    ■    ■      ■     \n");Sleep(1*50);
	printf("     ■    ■    ■■    ■     \n");Sleep(1*50);
	printf("     ■  ■■■■■  ■  ■     \n");Sleep(1*50);
	printf("     ■        ■■  ■  ■     \n");Sleep(1*50);
	printf("     ■■    ■  ■      ■     \n");Sleep(1*50);
	printf("     ■    ■    ■      ■     \n");Sleep(1*50);
	printf("         ■      ■      ■     \n");Sleep(1*50);
	printf("       ■    ■  ■  ■  ■     \n");Sleep(1*50);
	printf("               ■      ■       \n");Sleep(1*50);
	printf("                                \n\n");
	
	printf("             ■          ■     \n");Sleep(1*50);
	printf("   ■      ■■■■      ■     \n");Sleep(1*50);
	printf("     ■    ■    ■      ■     \n");Sleep(1*50);
	printf("     ■    ■■■■      ■     \n");Sleep(1*50);
	printf("           ■    ■■■■■■   \n");Sleep(1*50);
	printf(" ■■■    ■■■■      ■     \n");Sleep(1*50);
	printf("     ■    ■    ■      ■     \n");Sleep(1*50);
	printf("     ■    ■    ■■    ■     \n");Sleep(1*50);
	printf("     ■  ■■■■■  ■  ■     \n");Sleep(1*50);
	printf("     ■        ■■  ■  ■     \n");Sleep(1*50);
	printf("     ■■    ■  ■      ■     \n");Sleep(1*50);
	printf("     ■    ■    ■      ■     \n");Sleep(1*50);
	printf("         ■      ■      ■     \n");Sleep(1*50);
	printf("       ■    ■  ■  ■  ■     \n");Sleep(1*50);
	printf("               ■      ■       \n");Sleep(1*50);
	printf("                                \n\n");Sleep(1*50);
	///
	printf("        ■        ■            \n");Sleep(1*50);
	printf("        ■        ■            \n");Sleep(1*50);
	printf("      ■  ■■■■■■■■■■  \n");Sleep(1*50);
	printf("    ■            ■            \n");Sleep(1*50);
	printf("    ■■          ■            \n");Sleep(1*50);
	printf("  ■  ■  ■■■■■■■■■    \n");Sleep(1*50);
	printf("      ■  ■      ■      ■    \n");Sleep(1*50);
	printf("      ■  ■      ■      ■    \n");Sleep(1*50);
	printf("      ■  ■■■■■■■■■    \n");Sleep(1*50);
	printf("      ■    ■    ■            \n");Sleep(1*50);
	printf("      ■      ■■              \n");Sleep(1*50);
	printf("      ■        ■■            \n");Sleep(1*50);
	printf("      ■      ■    ■■        \n");Sleep(1*50);
	printf("      ■  ■■          ■■■  \n");Sleep(1*50);
	printf("      ■■                ■    \n");Sleep(1*50);
	printf("                                \n\n");
	
	printf("                                \n");Sleep(1*50);
	printf("      ■■■■■■■■■■■    \n");Sleep(1*50);
	printf("      ■        ■        ■    \n");Sleep(1*50);
	printf("      ■        ■        ■    \n");Sleep(1*50);
	printf("      ■        ■        ■    \n");Sleep(1*50);
	printf("      ■■■■■■■■■■■    \n");Sleep(1*50);
	printf("      ■        ■        ■    \n");Sleep(1*50);
	printf("      ■        ■        ■    \n");Sleep(1*50);
	printf("      ■        ■        ■    \n");Sleep(1*50);
	printf("      ■■■■■■■■■■■    \n");Sleep(1*50);
	printf("      ■        ■        ■    \n");Sleep(1*50);
	printf("      ■        ■        ■    \n");Sleep(1*50);
	printf("    ■          ■        ■    \n");Sleep(1*50);
	printf("    ■          ■    ■  ■    \n");Sleep(1*50);
	printf("  ■                    ■      \n");Sleep(1*50);
	printf("                                \n\n\n");
	get_red;
	printf("                  虽然程序已经结束,但是您的操作历史和系统历史以及游戏池仍然会存下来\n                  他们存在history.txt,system_history.txt和game.txt中\n");
	get_white;
	Sleep(1*1000);
	system("pause");
	exit(0);
	
}

int help()
{
	HANDLE handle_out = GetStdHandle(STD_OUTPUT_HANDLE);    //获得标准输出设备句柄  
	CONSOLE_SCREEN_BUFFER_INFO csbi;                        //定义窗口缓冲区信息结构体  
	GetConsoleScreenBufferInfo(handle_out, &csbi);      //获得窗口缓冲区信息 

	FILE * fp;
	fp = fopen("readme.txt","r");
	char kmp[2000];
	while(fscanf(fp,"%[^\n]%*c",kmp)==1)
	{
		if(!strcmp(kmp,"功能"))
		{
			get_red;
			puts(kmp);
			get_white;
		}
		else 
		puts(kmp);
	}
	puts("");
	return 0;
}
int enter()
{
	HANDLE handle_out = GetStdHandle(STD_OUTPUT_HANDLE);    //获得标准输出设备句柄  
	CONSOLE_SCREEN_BUFFER_INFO csbi;                        //定义窗口缓冲区信息结构体  
	GetConsoleScreenBufferInfo(handle_out, &csbi);      //获得窗口缓冲区信息 
	
	get_red;
	printf("按回车进入系统\n");
	get_white;
	if(!scanf("%*[^\n]%*c"))
	{
	getchar();
	}
	return 0;
}

文件5 solve_error.h

#include"color.h"
#include<stdio.h> 

void error(int n)//处理错误的函数 
{
	HANDLE handle_out = GetStdHandle(STD_OUTPUT_HANDLE);    //获得标准输出设备句柄  
	CONSOLE_SCREEN_BUFFER_INFO csbi;                        //定义窗口缓冲区信息结构体  
	GetConsoleScreenBufferInfo(handle_out, &csbi);      //获得窗口缓冲区信息
	if(n==1)
	{
	get_red;
	printf("\n error\n 错误代码:001 重id__请勿反复加入匹配!\n");
	get_white;
	}
	else if(n==2)
	{
	get_red;
	printf("\n error\n 错误代码:002 此id用户未进行匹配__请勿反复退出或开始游戏!\n");
	get_white;
	}
	else if(n==3)
	{
	get_red;
	printf("\n error\n 错误代码:003 输入格式错误__请按照上方格式输入!\n");
	get_white;
	}
	else if(n==4)
	{
	get_red;
	printf("\n error\n 错误代码:004 未找到此游戏用户__此用户未开始游戏,无法结束!\n");
	get_white;
	}
	else if(n==5)
	{
		get_red;
	    printf("\n error\n 错误代码:005 无法加入此用户__此用户已经开始游戏,无法再次匹配!\n");
	    get_white;
	}
	return;
}

文件6 sstring.h

//本程序需要用到的字符串处理函数
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include"match_data.h"

int search_kongge(char a[])//判断空格个数 
{
	int flag = 0;
	int ans = 0;
	int i;
	for (i = 0; a[i] != '\0'; i++)
	{
		if (a[i] == ' ' && flag > 0)
			ans++;
		else
		{
			flag++;
		}
	}
	return ans;
}
int fengge_one(char get[],char d[])//分割成一个空格的版本 
{
	sscanf(get,"%s",d);
	if(!strcmp(d,"gameover"))
	{
		sscanf(get,"%*s%s",d);
		return 0;
	}
	else
	{
		return 1;
	}
}
int fengge_three(char get[], char d[], struct people *a)//分割成三个空格的版本 
{
	sscanf(get, "%s%d%s%d", d, &a->id, a->name, &a->grade);
	return 1;
}
int string_sourch(char a[], int n)
{
	if (n == 1)
	{
		int i;
		for (i = 0; a[i] != '\0'; i++) //先转换大小写
		{
			if (a[i] >= 'A' && a[i] <= 'Z')
				a[i] = a[i] - 'A' + 'a';
		}
		if (!strcmp(a, "add"))
			return 1;
		else if (!strcmp(a, "remove"))
			return 2;
		else
			return 3;
	}
	else
	{
		int i;
		for (i = 0; a[i] != '\0'; i++) //先转换大小写
		{
			if (a[i] >= 'A' && a[i] <= 'Z')
				a[i] = a[i] - 'A' + 'a';
		}
		if (!strcmp(a, "fgamewait"))
			return 1;
		else if (!strcmp(a, "fgameing"))
			return 2;
		else if(!strcmp(a,"fpoolsize"))
		    return 4;
		else if(!strcmp(a,"q"))
		return 5;
		else if(!strcmp(a,"exit"))
		return 0;
		else if(!strcmp(a,"history"))
		return 6;
		else if(!strcmp(a,"system-history"))
		return 7;
		else if(!strcmp(a,"system-change"))
		return 8;
		else if(!strcmp(a,"help"))
		return 9;
		else if(!strcmp(a,"fgameing-t"))
		return 10;
		else if(!strcmp(a,"fgameing-av"))
		return 11;
		else
			return 3;
			
	}
}

文件7 game_pool.h

#include<stdio.h>
/*struct gaming
{
	struct people a;
	struct people b;
	int average_score;
	
};*/
//#include"color.h"
//#include "menu.h" 
//#include"match_data.h"
//#include"sstring.h"
#include"match_list.h"
int gameing_print(struct gaming a[],int size)//默认输出游戏进行时间 
{
	HANDLE handle_out = GetStdHandle(STD_OUTPUT_HANDLE);    //获得标准输出设备句柄  
	CONSOLE_SCREEN_BUFFER_INFO csbi;                        //定义窗口缓冲区信息结构体  
	GetConsoleScreenBufferInfo(handle_out, &csbi);      //获得窗口缓冲区信息
	int i;
	for(i=0;size>i;i++)
	{
		printf("%d:\n",i+1);
		get_red;
		printf("%s",a[i].a.name);
		get_white;
		printf("  vs  ");
		get_blue;
		printf("%s\n",a[i].b.name);
		get_white;
		printf("played:%d seconds\n\n",a[i].time_ing); 
	}
	if(size == 0)
	{
		get_red;
		printf("\nthere is no one in gameing\n");
		get_white;
	}
	puts("");
	return 0;
}

int gameing_print_a(struct gaming a[],int size)//输出游戏双方的平均分数 
{
	HANDLE handle_out = GetStdHandle(STD_OUTPUT_HANDLE);    //获得标准输出设备句柄  
	CONSOLE_SCREEN_BUFFER_INFO csbi;                        //定义窗口缓冲区信息结构体  
	GetConsoleScreenBufferInfo(handle_out, &csbi);      //获得窗口缓冲区信息
	int i;
	for(i=0;size>i;i++)
	{
		printf("%d:\n",i+1);
		get_red;
		printf("%s",a[i].a.name);
		get_white;
		printf("  vs  ");
		get_blue;
		printf("%s\n",a[i].b.name);
		get_white;
		printf("平均分数为:%d 分\n\n",a[i].average_score); 
	}
	if(size == 0)
	{
		get_red;
		printf("\nthere is no one in gameing\n");
		get_white;
	}
	puts("");
	return 0;
}

主c文件  用户动态匹配系统.c

int list_size=0;//当前链表长度 
//#include "match_list.h"
#include <pthread.h>
#include "game_pool.h"//保存 
//#include"color.h"
int system_history=0;//全局变量,用来改变系统问题是否输出到屏幕。0表示不输出。 
 
int id_card[10000000];//对id进行判重,防止重复id加入游戏。 
//int name_card[1000000]; //本来想写一个字符串哈希来对名字判重的,但是没写了,因为没什么意义,名字可以重复。 
pthread_mutex_t id_m;

struct mutex_match//定义了一个带锁的链表,方便多线程时的管理。//此为匹配池 匹配池为动态池,动态存储。 
{
	list_data * head ;
	pthread_mutex_t m;
	
}q;

struct mutex_game //这是游戏池。//游戏池将存在文件game.txt中。 
{
	struct gaming pool[2000];
	int cnt;
	pthread_mutex_t m;
}gameing;

struct gaming ttemp[2000];//用来处理游戏池的删除//做中介作用 
//
pthread_mutex_t file_game_m;//文件锁,防止多进程同时对文件进行增删查改。 

pthread_mutex_t file_history_m;//操作历史文件——锁。 

pthread_mutex_t file_history_system_m;//系统操作历史文件(例如match 1 and 2 succeed)。——锁。
 
int add_to_game(struct people a,struct people b)//加入正在进行中的游戏池。 
{
	pthread_mutex_lock(&gameing.m);
	gameing.pool[gameing.cnt].a=a;
	gameing.pool[gameing.cnt].b=b;
	gameing.pool[gameing.cnt].average_score=((a.grade+b.grade)>>1);
	gameing.cnt++;
	pthread_mutex_unlock(&gameing.m);
}
/*#############此 处 为 匹 配 线 程 开 始 #####################*/
int match_server(list_data * head)//匹配程序,遍历匹配,选取合法的用户匹配,每一次匹配提高每个用户的匹配(阈值)(时间越久越容易匹配到人(不过可能被虐菜))。 
{
	int a=0;
	list_data * i;
	for(i = head ; i!=NULL ; i = i->next)
	{
		i->data.wait_time++;
	}
	for(i = head ; i!=NULL ; i = i->next)//遍历进行匹配 
	{
		list_data * j;
		for(j = i->next ; j!=NULL ; j = j->next)
		{
			int t=abs(i->data.grade - j->data.grade);
			if((t <= (i->data.wait_time * 5))&&(t <= (j->data.wait_time * 5)))//符合要求则进入游戏池,并从匹配池删除 
			{
				add_to_game(i->data,j->data);
				
				pthread_mutex_lock(&id_m);//更新id 
				id_card[i->data.id]=1;
				id_card[j->data.id]=1;
				pthread_mutex_unlock(&id_m);
				
			    if(system_history)//存历史 
				{
					printf("match %d and %d succeed\n",i->data.id,j->data.id);
				}
				pthread_mutex_lock(&file_history_system_m);
				FILE *fp;
				fp =fopen("history_system.txt","a+");
				fprintf(fp,"match %d and %d succeed\n",i->data.id,j->data.id);
				fclose(fp);
				
				pthread_mutex_unlock(&file_history_system_m);
				
				if(j->next==NULL)
				{
					q.head=list_remove(q.head,j->data,&a);
				}
				else
				remove_now(j);
				if(i->next==NULL||i==head)
				{
					q.head=list_remove(q.head,i->data,&a);
				}
				else
				{
				remove_now(i);
				}
				
				return 0;
			}
		}
	}
	
	return 0;
}

void * solve_task(void *argc)//解决匹配问题 
{
	while(1)
	{
		
	while (list_size>0)//一秒匹配一次 
	{
		pthread_mutex_lock(&q.m);
		match_server(q.head);
		pthread_mutex_unlock(&q.m);
		Sleep(1000);
	}
	Sleep(1000);
	
	}
}
/*############# 此 处 为 匹 配 线 程 的 结 尾 #####################*/

//-----------------------------------------------------------------------------------------------------------------------------------------分割线 

/*############# 此 处 为 游 戏 线 程 的 开 始 #####################*/
int game_file_add()//每五秒刷新一次 游戏进行时文件 
{
	pthread_mutex_lock(&gameing.m);
	pthread_mutex_lock(&file_game_m);
	
	FILE *fp;
	fp = fopen("game.txt","w");
	
	int i;
	for(i=0;gameing.cnt>i;i++)
	{
		gameing.pool[i].time_ing+=5;//每次刷新游戏时间加5 
		fprintf(fp,"%d:\n",i+1);
		
		fprintf(fp,"    %d   %s   %d\n",gameing.pool[i].a.id,gameing.pool[i].a.name,gameing.pool[i].a.grade);
		
		fprintf(fp,"         vs                 gameing_time:%ds\n",gameing.pool[i].time_ing);
		
		fprintf(fp,"    %d   %s   %d\n\n",gameing.pool[i].b.id,gameing.pool[i].b.name,gameing.pool[i].b.grade);
		
	}
	fclose(fp);
	pthread_mutex_unlock(&gameing.m);
	pthread_mutex_unlock(&file_game_m);
	return 0;
}

int game_remove_name(char name[])//结束某个用户的游戏——用名称进行删除。 
{
	pthread_mutex_lock(&gameing.m);
	int temp_cnt=0; 
	int i;
	for(i = 0;gameing.cnt>i;i++)
	{
		if((!strcmp(name,gameing.pool[i].a.name)) || (!strcmp(name,gameing.pool[i].b.name)) )
		{
			pthread_mutex_lock(&id_m);
			id_card[gameing.pool[i].a.id]=0;
			id_card[gameing.pool[i].b.id]=0;
			pthread_mutex_unlock(&id_m);
			continue;
		}
		ttemp[temp_cnt++]=gameing.pool[i];
	}
	if(temp_cnt == gameing.cnt)
	{
		pthread_mutex_unlock(&gameing.m);
		
		if(system_history)//存历史 
		{
			printf("gameover '%s' false\n",name);
		}
		pthread_mutex_lock(&file_history_system_m);
		FILE *fp;
		fp =fopen("history_system.txt","a+");
		fprintf(fp,"gameover '%s' false\n",name);
		fclose(fp);
				
		pthread_mutex_unlock(&file_history_system_m);
		return 1;
	}
	else
	{
		for(i=0;temp_cnt>i;i++)//在前面定义过了 
		{
			gameing.pool[i]=ttemp[i];
		}
		gameing.cnt=temp_cnt;
	} 
	pthread_mutex_unlock(&gameing.m);
	
		if(system_history)//存历史
		{
			printf("gameover '%s' succeed\n",name);
		}
		pthread_mutex_lock(&file_history_system_m);
		FILE *fp;
		fp =fopen("history_system.txt","a+");
		fprintf(fp,"gameover '%s' succeed\n",name);
		fclose(fp);
		
		pthread_mutex_unlock(&file_history_system_m);//记得开锁。 
	return 0;
}


int game_remove_id(int id)//结束某个用户的游戏——用id进行删除。 
{
	pthread_mutex_lock(&gameing.m);
	int temp_cnt=0; 
	int i; 
	for(i = 0;gameing.cnt>i;i++)
	{
		if((id == gameing.pool[i].a.id) || (id == gameing.pool[i].b.id))
		{
			pthread_mutex_lock(&id_m);
			id_card[gameing.pool[i].a.id]=0;
			id_card[gameing.pool[i].b.id]=0;
			pthread_mutex_unlock(&id_m);
			continue;
		}
		ttemp[temp_cnt++]=gameing.pool[i];
	}
	if(temp_cnt == gameing.cnt)
	{
		pthread_mutex_unlock(&gameing.m);
		
		if(system_history)//存历史 
		{
			printf("gameover '%d' false\n",id);
		}
		pthread_mutex_lock(&file_history_system_m);
		FILE *fp;
		fp =fopen("history_system.txt","a+");
		fprintf(fp,"gameover '%d' false\n",id);
		fclose(fp);
				
		pthread_mutex_unlock(&file_history_system_m);
		return 1;
	}
	else
	{
		for(i=0;temp_cnt>i;i++)//前面定义过了 
		{
			gameing.pool[i]=ttemp[i];
		}
		gameing.cnt=temp_cnt;
	} 
	pthread_mutex_unlock(&gameing.m);
	
		if(system_history)//存历史
		{
			printf("gameover '%d' succeed\n",id);
		}
		pthread_mutex_lock(&file_history_system_m);
		FILE *fp;
		fp =fopen("history_system.txt","a+");
		fprintf(fp,"gameover '%d' succeed\n",id);
		fclose(fp);
		
		pthread_mutex_unlock(&file_history_system_m);//记得开锁。 
	return 0;
}

void *solve_gaming(void *argc)//解决游戏问题
{
	while(1)
	{
		while(gameing.cnt>0)
		{
			game_file_add();
			Sleep(5000);
		}
		Sleep(5000);
	}
} 
/*############# 此 处 为 游 戏 线 程 的 结 尾 #####################*/

/*############# 此 处 为 历 史 文 件 处 理 的 开 始 #####################*/

int print_history()输出history.txt文件。 
{
	pthread_mutex_lock(&file_history_m);
	FILE * fp;
	int i=1;
	fp = fopen("history.txt","r");
	char kmp[200];
	while(fscanf(fp,"%[^\n]%*c",kmp)==1)
	{
		printf("%d:",i);
		puts(kmp);
		i++;
	}
	puts("");
	pthread_mutex_unlock(&file_history_m);
	
	return 0;
}

int print_system_history()///输出系统信息___history_system.txt文件 
{
	pthread_mutex_lock(&file_history_system_m);
	FILE * fp;
	int i=1;
	fp = fopen("history_system.txt","r");
	char kmp[200];
	while(fscanf(fp,"%[^\n]%*c",kmp)==1)
	{
		printf("%d:",i);
		puts(kmp);
		i++;
	}
	puts("");
	pthread_mutex_unlock(&file_history_system_m);
	
	return 0;
}
/*############# 此 处 为 历 史 文 件 处 理 的 结 尾 #####################*/


/*############# 此 处 为 解 决 游 戏 池 排 序 输 出 的 问 题 开 始 #####################*/
int cmp_time(const void *p1,const void *p2)//时间排序函数 
{
	const struct gaming *a1 = (const struct gaming *)p1;
	const struct gaming *a2 = (const struct gaming *)p2;
	return a1->time_ing > a2->time_ing;
	
} 
int cmp_average(const void *p1,const void *p2)//平均分数排序函数 
{
	const struct gaming *a1 = (const struct gaming *)p1;
	const struct gaming *a2 = (const struct gaming *)p2;
	return a1->average_score > a2->average_score;
	
}

int gameing_print_time(struct gaming a[],int n)//按时间排序后输出函数 
{
	qsort(a,n,sizeof(struct gaming),cmp_time);
	gameing_print(a,n);
	return 0;
	
}
int gameing_print_average(struct gaming a[],int n) //按平均成绩排序后输出函数。
{
	qsort(a,n,sizeof(struct gaming),cmp_average); 
	gameing_print_a(a,n);
	
	return 0;
} 
/*############# 此 处 为 解 决 游 戏 池 排 序 输 出 的 问 题 结 尾 #####################*/

int main(void)//主函数开始处、、、、、、、、 
{
	
	//先输出教程
	help();//定义在menu.h 
	
	enter();//阻断函数。。给用户看说明的时间//定义在menu.h
	 
	system("cls"); 
	
	
	//正式进入系统 
	
	
	FILE *file_to_zero;//初始化各个文件防止上一次运行残留。 
	file_to_zero = fopen("history.txt","w");
	fclose(file_to_zero);
	
	file_to_zero = fopen("history_system.txt","w");
	fclose(file_to_zero);//初始化 history文件。
	
	file_to_zero = fopen("game.txt","w");
	fclose(file_to_zero);
	
	menu(); //输出菜单。
	 
	char get[700]; //读取整行输入 
	char doing[200];//存临时操作名称 
	struct people a;//存临时用户。 
	
	gameing.cnt=0;
	
	q.head=list_inint(0);//初始化链表
	
	pthread_t th1_match;//定义第一个线程 //用于匹配 
	pthread_t th2_game;//定义第二个线程// 用于进行游戏池更新。
	 
	pthread_create(&th1_match,NULL,solve_task,NULL);//创建第一个线程 (匹配线程,每一秒匹配一次) 
	pthread_create(&th2_game,NULL,solve_gaming,NULL);//创建第二个线程(游戏线程,处理游戏进行时的条件改变__五秒刷新一次) 
	
	while(1==1)//反复循环读取用户输入
	{
		if(!scanf("%[^\n]%*c",get))//输入操作 
		{
		getchar();
		continue;
		}
		
		pthread_mutex_lock(&file_history_m);   //存操作历史。 
		FILE *history_file_hand;
		history_file_hand = fopen("history.txt","a+");
		fprintf(history_file_hand,"%s\n",get);
		fclose(history_file_hand);
		pthread_mutex_unlock(&file_history_m);
		/
		 
		int kongge=search_kongge(get);//输入按空格分为0,1,3空格形式命令 
		if(kongge != 3 && kongge != 0 && kongge !=1)//都不是则error 
		error(3);
		else if(kongge == 3)//三空格命令 
		{
			fengge_three(get,doing,&a);//三空格的字符串 分割出来。 
			int temp=0;
			temp=string_sourch(doing,1);//以一号方式执行函数  //为添加和删除匹配(方式 ) 
			if(temp==3)
			error(3);
			else if(temp == 1)//添加用户 
			{
				int p=0;
				pthread_mutex_lock(&q.m);//把链表上锁,防止同时修改。 
				pthread_mutex_lock(&id_m);//id也要上锁。 
				if(id_card[a.id])
				{
					p=1;
				    error(5);
				}
				else
				q.head = list_add(q.head,a,&p);
				pthread_mutex_unlock(&q.m);//释放 
				pthread_mutex_unlock(&id_m);
				
				if(!p)  //处理系统信息,判断添加成功与否 
				{
					pthread_mutex_lock(&id_m);//更新id 
					id_card[a.id]=1;
					pthread_mutex_unlock(&id_m);
					
					if(system_history)
					{
						printf("add %d succeed\n",a.id);
					}
					pthread_mutex_lock(&file_history_system_m);
					FILE *fp;
					fp =fopen("history_system.txt","a+");
					fprintf(fp,"add %d succeed\n",a.id);
					fclose(fp);
					
					pthread_mutex_unlock(&file_history_system_m);
				}
				else
				{
					if(system_history)
					{
						printf("add %d false\n",a.id);
					}
					pthread_mutex_lock(&file_history_system_m);
					FILE *fp;
					fp =fopen("history_system.txt","a+");
					fprintf(fp,"add %d false\n",a.id);
					fclose(fp);
					
					pthread_mutex_unlock(&file_history_system_m);
				}
				///
				
			}
			else if(temp == 2)//同上,删除用户 
			{
				int p=0;
				pthread_mutex_lock(&q.m);//把链表上锁,防止同时修改。 
				q.head = list_remove(q.head,a,&p);
				pthread_mutex_unlock(&q.m);
				
				if(!p)//处理系统信息,判断删除成功与否  
				{
					if(system_history)
					{
						printf("remove %d succeed\n",a.id);
					}
					pthread_mutex_lock(&file_history_system_m);
					FILE *fp;
					fp =fopen("history_system.txt","a+");
					fprintf(fp,"remove %d succeed\n",a.id);
					fclose(fp);
					
					pthread_mutex_unlock(&file_history_system_m);
				}
				else
				{
					if(system_history)
					{
						printf("remove %d false\n",a.id);
					}
					pthread_mutex_lock(&file_history_system_m);
					FILE *fp;
					fp =fopen("history_system.txt","a+");
					fprintf(fp,"remove %d false\n",a.id);
					fclose(fp);
					
					pthread_mutex_unlock(&file_history_system_m);
				}
				/// 
			}
		}
		else if(kongge == 1)//一空格命令 
		{
			if(fengge_one(get,doing))//先分割 
			{
				error(3);
				continue;
			}
			if(doing[0]>='0'&&doing[0]<='9')//判断数字id还是名字 
			{
				int id=0;
				int i;
				for(i=0;doing[i]!='\0';i++)
				{
					id=id*10 +(doing[i]-'0');
				}
				if(game_remove_id(id))
				{
					error(4);
				}
			}
			else 
			if(game_remove_name(doing))
			{
				error(4);
			}
			
			
		}
		else if(kongge == 0)//零空格命令 
		{
			int temp=string_sourch(get,2);//以二号方式执行。//是某些单条命令 
			if(temp ==0)//exit 
			{
				pthread_mutex_lock(&file_game_m);
				pthread_mutex_lock(&file_history_m);
				pthread_mutex_lock(&file_history_system_m);
				match_exit();
				pthread_mutex_unlock(&file_game_m);
				pthread_mutex_unlock(&file_history_m);
				pthread_mutex_unlock(&file_history_system_m);
				
			}
			else if(temp==3)//没这个命令 
			error(3);
			else if(temp == 1)//fgamewait 
			{
				pthread_mutex_lock(&q.m);//把链表上锁,防止同时修改。 
				list_print(q.head);
				pthread_mutex_unlock(&q.m);//释放 
				
			}
			else if(temp == 2)//fgameing
			{
				pthread_mutex_lock(&gameing.m);
				gameing_print(gameing.pool,gameing.cnt);
				pthread_mutex_unlock(&gameing.m);
				
			}
			else if(temp == 4)//fpoolsize
			{
				HANDLE handle_out = GetStdHandle(STD_OUTPUT_HANDLE);    //获得标准输出设备句柄  
				CONSOLE_SCREEN_BUFFER_INFO csbi;                        //定义窗口缓冲区信息结构体  
				GetConsoleScreenBufferInfo(handle_out, &csbi);      //获得窗口缓冲区信息			
				
				printf("now the pool size is: ");
				get_red;
				printf("%d\n",list_size);
				get_white;
				
			}
			else if(temp == 5)//q//刷新 
			{
				system("cls");
				menu();
			}
			else if(temp == 6)//history 
			{
				print_history();
			}
			else if(temp == 7)//system-history 
			{
				print_system_history();
			}
			else if(temp == 8)//system-change
			{
				system_history ^=1;
				if(system_history == 1)
				printf("change to system_out (此模式下将及时的输出所有系统信息)\n");
				else
				{
					printf("change to system_in(关闭系统信息输出)\n");
				}
			}
			else if(temp == 9)//help
			{
				help();//直接输出帮助____定义在menu.h中。 
			}
			else if(temp == 10)//fgameing-t//按时间排序从小到大输出。
			{
				pthread_mutex_lock(&gameing.m);
				gameing_print_time(gameing.pool,gameing.cnt);
				pthread_mutex_unlock(&gameing.m);
			}
			else if(temp == 11)//fgameing-av//按比赛双方的平均分数排序从小到大输出。
			{
				pthread_mutex_lock(&gameing.m);
				gameing_print_average(gameing.pool,gameing.cnt);
				pthread_mutex_unlock(&gameing.m);
			}
		}
	}
	return 0;
	
	
	
	
//                            _ooOoo_  
//                           o8888888o  
//                           88" . "88  
//                           (| -_- |)  
//                            O\ = /O  
//                        ____/`---'\____  
//                      .   ' \\| |// `.  
//                       / \\||| : |||// \  
//                     / _||||| -:- |||||- \  
//                       | | \\\ - /// | |  
//                     | \_| ''\---/'' | |  
//                      \ .-\__ `-` ___/-. /  
//                   ___`. .' /--.--\ `. . __  
//                ."" '< `.___\_<|>_/___.' >'"".  
//               | | : `- \`.;`\ _ /`;.`/ - ` : | |  
//                 \ \ `-. \_ __\ /__ _/ .-` / /  
//         ======`-.____`-.___\_____/___.-`____.-'======  
//                            `=---='  
//  
//         .............................................  
//                  佛祖保佑             永无BUG 
//          佛曰:  
//                  写字楼里写字间,写字间里程序员;  
//                  程序人员写程序,又拿程序换酒钱。  
//                  酒醒只在网上坐,酒醉还来网下眠;  
//                  酒醉酒醒日复日,网上网下年复年。  
//                  但愿老死电脑间,不愿鞠躬老板前;  
//                  奔驰宝马贵者趣,公交自行程序员。  
//                  别人笑我忒疯癫,我笑自己命太贱;  
//                  不见满街漂亮妹,哪个归得程序员?

}

教程文件 readme.txt (必须与主函数文件处于同一文件夹下运行)

功能
       1:
         add      remove
        添加用户和删除用户进匹配池(匹配系统会根据添加进来的用户动态的进行匹配,每一个用户第一秒只会匹配根自己分数相差5分以内的对手,
        但是每过一秒他们的阈值会增加5分(就算是与跟自己分差很多的对手游戏也比没人好)及第二秒就可能会匹配到跟自己相差10分的对手了,以此类推)。
        add操作。
        add+(id)+(user_name)+(user_grade)             中间用空格隔开回车即可添加,(id和名字和分数)
       (其实是模拟前端用户点击匹配然后进行的操作--这里没有图形界面所以用linux类型的命令进行交互)
        remove操作。
        remove+(id)+(user_name)+(user_grade)             中间用空格隔开回车即可删除,(id和名字和分数)
       (模拟前端用户点击取消匹配然后进行的操作,注意,用户可能会匹配成功,如果匹配成功了就无法取消了。)
功能
       2:
        fgamewait     fgameing(-t)(-av)          fpoolsize
        查看匹配池或游戏池情况(匹配系统随时可能会匹配成功,成功的人会移除匹配池,所以我们随时可以查看一下匹配池情况(可看到池中各种数值))
        fgamewait(输入此命令然后回车,可以看到还在等待匹配的用户即匹配池中的所有人的详细情况)
        例如输出
        1:id= 1,name=lcy,grade= 1500 waiting for 5 seconds
          
         fgameing(-t)(-av)(输入此命令然后回车,可以看到正在游戏的用户即游戏池中人的数量,包括他们的游戏时长,并且这些信息存在game.txt中结束程序也不会消失)
       (可以加上后缀(-t)或者(-av)(分别表示按游戏"进行时间"和游戏玩家的"平均分数"从小到大排序后输出)(例如:(fgameing-t) (fgameing-av))
        例如输出
        1:
        lcy  vs  hdm
        played:5 seconds
         
        fpoolsize(输入此命令然后回车,可以看到还在等待匹配的用户即匹配池中人的数量)
        例如输出
        now the pool size is: 0
功能
       3:
         gameover 'id'          gameover 'name'
         结束某个用户的游戏(用来模拟游戏结束前端向服务器发送的请求)(用户必须要正在游戏才能结束哦)
        gameover+(id)或者gameover+(user_name) (中间用空格隔开回车即可删除)(id 和 名字 都行效果一样)
        随后那个用户就会从游戏池中被删除。。当然game.txt中他也会被删除。
功能
      4:
        查看各种历史
        history  (输入此命令然后回车,可以看到自己的所有历史输入,他将按顺序展示出来,(包括无意义的命令)(这些信息存在history.txt文件中))
        例如输出
        1:add 1 罗春阳 1500
        2:add 2 hdm 1530
        3:fgame
        4:fgamewait
          
         system-history(输入此命令然后回车,可以看到系统的所有历史信息,他将按顺序展示出来,(系统每次匹配到一个人或者加入一个用户都会产生一个信息)(这个信息存在history_system.txt文件中))
         例如输出
         1:add 1 and 2 succeed
         
功能
       5:
         切换系统信息输出模式
         system-change(输入此命令然后回车,可以将系统输出及时的输出到终端屏幕上)
         (系统每次匹配到一个人或者加入一个用户都会产生一个信息)(开启输出后这个信息将能及时的展示在终端屏幕上)
         (再输入一次即可关闭)。
功能
       6:
         查看帮助
         help(输入此命令然后回车 将再次展示此页面)
          
         输入一个字母'q'加回车可以刷新页面(如果你觉得页面太长不舒服的话)。
          

以上

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值