C语言实现《2048游戏》

C语言实现《2048游戏》

滑块有颜色、有最高分(用到文件)

程序运行效果图

主页面
C语言实现《2048游戏》_第1张图片1、游戏规则
C语言实现《2048游戏》_第2张图片2、开始游戏

C语言实现《2048游戏》_第3张图片3、继续游戏(指不退出游戏,继续再来一局,而不是接着上一局,如果需要接着上一局,要实现点存档,然后读档就可以了)
C语言实现《2048游戏》_第4张图片当玩过一句游戏后,它会自动创建文件来保存最高分(破纪录后,会自动重写最高分),点存档也会创建文件来保存档案。两个文件都会直接存储在存放游戏的文件目录下。
C语言实现《2048游戏》_第5张图片

#include 
#include 
#include  /*使用getch()函数*/
#include 
#include  /*使用Sleep()函数*/ 

void Menu();//菜单
void Rule_of_game();//游戏规则 
void Begin(int max); //开始 
void Table();//打印4×4方格 
int Random_number1();//产生2或4的随机数 
int Random_number2();//产生0、1、2、3的随机数 
int Get(int *p_cnt, int score);//输入指令 
void Move();//保留上一次的棋盘布局 
int If_move();//判断是否移动 
int Over();//判断是否结束  
void Establish_game();//创建用于保存最高分的文件 
void Write_max(int score);//向2048游戏-最高记录写入最高分 
int Read_max();//读出最高分记录的文件
void Establish_file();//创建存档文件 
void Write_file(int *p_cnt, int scort);//存档 
int Read_file(int *p_cnt);//读档 
void again();//是否继续游戏
int color(int c);//更改颜色
void box_color(int x);//不同数值对应不同颜色 

int a[4][4] = {0};// 定义全局的二维数组 
int A[4][4]; //保留上一步的棋局 
char *name_max = "2048游戏-最高记录";
char *name_file = "[空白]-2048游戏";

int main() {
	system("mode con cols=90 lines=30");
	system("title 2048超级大大型游戏"); //程序标题 
	system("color F0");//F 表示背景颜色,0表示前景颜色 
	Menu();
	system("pause");   //暂停,输入任意键继续 
	system("cls"); //清屏 
	again(); //是否继续游戏
	return 0;
}

void Menu() //菜单 
{
	printf("\t\t╔══════════════════════════════════════════════╗\n"); 
	printf("\t\t║   欢迎使用由[空白]制作的2048超级大大型游戏   ║\n");
	printf("\t\t╟──────────────────────────────────────────────╢\n");
	printf("\t\t║请输入选项:                                  ║\n");
	printf("\t\t║              ┌───┐                           ║\n");
	printf("\t\t║              │ 1 │ 游戏规则                  ║\n");
	printf("\t\t║              └───┘                           ║\n");
	printf("\t\t║              ┌───┐                           ║\n");
	printf("\t\t║              │ 2 │ 开始游戏                  ║\n");
	printf("\t\t║              └───┘                           ║\n");
	printf("\t\t║              ┌───┐                           ║\n");
	printf("\t\t║              │ 3 │ 继续游戏                  ║\n");
	printf("\t\t║              └───┘                           ║\n");
	printf("\t\t║              ┌───┐                           ║\n");
	printf("\t\t║              │ 4 │ 退出游戏                  ║\n");
	printf("\t\t║              └───┘                           ║\n");
	printf("\t\t╚══════════════════════════════════════════════╝\n");
	int x = 1, max = 0;
	while(x){
		switch(getch()){
			case '1':
				x = 0;
				Rule_of_game();//游戏规则
				Menu();
				break;	 
			case '2':
				x = 0;
				system("cls");//清屏
				Establish_game(name_file);//创建新的读档文件 
				Establish_game(name_max);//创建新的保存最高记录的文件 
				Begin(max); //开始游戏 
				break;
			case '3':
				x = 0;
				system("cls");//清屏
				max = Read_max();//读取之前的最高记录 
				Begin(max); //开始游戏 
				break;
			case '4':
				exit(0); 
			default:
				printf("输入了非法选项,请重新选择!\n");
		}
	}
}

void Rule_of_game()
{ 
	system("cls");//清屏 
	printf("╔══════════════════════════════════════════════════════════════════════════════════╗\n"); 
	printf("║本游戏通过按键W、S、A、D(不区分大小写)四个键分别控制滑块上移、下移、左移和右移。║\n");
	printf("║滑块移动的过程中,如有相邻且相等数字的滑块将会相加,并获得相应的分数。            ║\n");
	printf("║当棋盘上的所有位置均有数字,且不能合成,则游戏结束。本游戏未设置游戏成功。        ║\n");
	printf("║游戏过程中输入I即为存档并退出游戏,输入O即为读档,输入P则退出游戏。               ║\n");
	printf("║“开始游戏”则清除最高记录及存档、“继续游戏”则保存之前的最高记录,且可以读档。  ║\n"); 
	printf("╚══════════════════════════════════════════════════════════════════════════════════╝\n");
	system("pause");//暂停 
	system("cls");//清屏 
}

void Begin(int max)
{
	int score = 0;
	int sign = 1;
	int h, l, cnt = 0;
	int *p_cnt = &cnt;
	while(1) {
		printf("\t\t╔══════════════════════════════════════════════╗\n"); 
		printf("\t\t║   欢迎使用由[空白]制作的2048超级大大型游戏   ║\n");
		printf("\t\t╟──────────────────────────────────────────────╢\n");
		printf("\t\t║移动:   ┌───┐        存档: 读档: 退出:    ║\n");
		printf("\t\t║         │ W │                                ║\n");		
		printf("\t\t║     ┌───┼───┼───┐    ┌───┐ ┌───┐ ┌───┐       ║\n");
		printf("\t\t║     │ A │ S │ D │    │ I │ │ O │ │ P │       ║\n");
		printf("\t\t║     └───┴───┴───┘    └───┘ └───┘ └───┘       ║\n");
		printf("\t\t╚══════════════════════════════════════════════╝\n");
		while(1){
			if(sign == 1){
				h = Random_number2();
				l = Random_number2();
				if(a[h][l] == 0){
					a[h][l] = Random_number1();
					cnt ++;
					break;
				}
			}
			else{
				break;
			}
			
		}
		Table();//打印棋盘 
		printf("\t\t移动的步数:%d\t当前得分:%d\n\t\t最高记录:%d\n", cnt-1, score, max);
		Move();//保留棋盘 
		score += Get(p_cnt, score);//得分
		sign = If_move();//判断棋盘是否有变动 
		if(Over() == 0){ 
			if(max < score){//打破记录 
				Establish_game(name_max);//清除之前的记录 
				Write_max(score);//保存此次记录
				printf("\t\t恭喜您已打破记录!\n"); 
			} 
			break;
		} 
		system("cls"); //清屏
	}
}

void Table()
{
	int h, l;
	for(h = 0; h < 4; h ++){
		if(h == 0){
			printf("\t\t\t┏━━━━━━┳━━━━━━┳━━━━━━┳━━━━━━┓\n");
		}
		else {
			printf("\t\t\t┣━━━━━━╋━━━━━━╋━━━━━━╋━━━━━━┫\n");
		}
		printf("\t\t\t┃      ┃      ┃      ┃      ┃\n");
		for(l = 0; l < 4; l ++){
			if(a[h][l] == 0){//如果二维数组与棋盘对应的位置为零,则不放入数据 
				if(l == 0){
					printf("\t\t\t┃      ");
				}
				else {
					printf("┃      ");
				}
			}
			else{//否则放入与二维数组对应的数据 
				if(l == 0){
					printf("\t\t\t┃");
					box_color(a[h][l]);//判断滑块的数值,给对应颜色 
					printf("%5d ", a[h][l]);
					color(0);//恢复白色背景 
				}
				else {
					printf("┃");
					box_color(a[h][l]);//判断滑块的数值,给对应颜色 
					printf("%5d ", a[h][l]); 
					color(0);//恢复白色背景 
				}
			}
		}
		printf("┃\n");
		printf("\t\t\t┃      ┃      ┃      ┃      ┃\n");
	}
	printf("\t\t\t┗━━━━━━┻━━━━━━┻━━━━━━┻━━━━━━┛\n");
}

int Random_number1()/*随机生成2 or 4*/
{ 
	int s;
	srand( time(NULL) ); 
	s = ((unsigned)rand() % 2);
	s = s == 0 ? 2 : 4;
	return s;
}

int Random_number2()/*随机生成二维数组的下标*/
{ 
	int x;
	x = ((unsigned)rand() % 4);
	return x;
}

int Get(int *p_cnt, int score)
{
	int h, l, t, sum = 0;
	char ch;
	ch = getch();//输入字符 
	switch (ch){
		/*滑块向上移动*/ 
		case 'w':
		case 'W':
			/*向上聚集数字*/
			for(l = 0; l < 4; l ++){
				for(t = 0; t < 4; t ++){
					for(h = 3; h > 0; h --){
						if(a[h-1][l] == 0){
							a[h-1][l] = a[h][l];
							a[h][l] = 0;
						}
					}
				}
			}
			/*竖直方向上,相邻且相同的数字相加*/ 
			for(l = 0; l < 4; l ++){
				for(h = 0; h < 3; h ++){
					if(a[h][l] == a[h+1][l]){
						a[h][l] += a[h+1][l];
						a[h+1][l] = 0;
						sum += a[h][l];
					}
				}
			}
			/*向上聚集数字*/ 
			for(l = 0; l < 4; l ++){
				for(t = 0; t < 4; t ++){
					for(h = 3; h > 0; h --){
						if(a[h-1][l] == 0){
							a[h-1][l] = a[h][l];
							a[h][l] = 0;
						}
					}
				}
			}
			break;
		case 's':
		case 'S':
			for(l = 0; l < 4; l ++){
				for(t = 0; t < 4; t ++){
					for(h = 0; h < 3; h ++){
						if(a[h+1][l] == 0){
							a[h+1][l] = a[h][l];
							a[h][l] = 0;
						}
					}
				}
			}
			for(l = 0; l < 4; l ++){
				for(h = 3; h > 0; h --){
					if(a[h][l] == a[h-1][l]){
						a[h][l] += a[h-1][l];
						a[h-1][l] = 0;
						sum += a[h][l];
					}
				}
			}
			for(l = 0; l < 4; l ++){
				for(t = 0; t < 4; t ++){
					for(h = 0; h < 3; h ++){
						if(a[h+1][l] == 0){
							a[h+1][l] = a[h][l];
							a[h][l] = 0;
						}
					}
				}
			}
			break;
		case 'a':
		case 'A':
			for(h = 0; h < 4; h ++){
				for(t = 0; t < 4; t ++){
					for(l = 3; l > 0; l --){
						if(a[h][l-1] == 0){
							a[h][l-1] = a[h][l];
							a[h][l] = 0;
						}
					}
				}
			}
			for(h = 0; h < 4; h ++){
				for(l = 0; l < 3; l ++){
					if(a[h][l] == a[h][l+1]){
						a[h][l] += a[h][l+1];
						a[h][l+1] = 0;
						sum += a[h][l];
					}
				}
			}
			for(h = 0; h < 4; h ++){
				for(t = 0; t < 4; t ++){
					for(l = 3; l > 0; l --){
						if(a[h][l-1] == 0){
							a[h][l-1] = a[h][l];
							a[h][l] = 0;
						}
					}
				}
			}
			break;
		case 'd':
		case 'D':
			for(h = 0; h < 4; h ++){
				for(t = 0; t < 4; t ++){
					for(l = 0; l < 3; l ++){
						if(a[h][l+1] == 0){
							a[h][l+1] = a[h][l];
							a[h][l] = 0;
						}
					}
				}
			}
			for(h = 0; h < 4; h ++){
				for(l = 3; l > 0; l --){
					if(a[h][l] == a[h][l-1]){
						a[h][l] += a[h][l-1];
						a[h][l-1] = 0;
						sum += a[h][l];
					}
				}
			}
			for(h = 0; h < 4; h ++){
				for(t = 0; t < 4; t ++){
					for(l = 0; l < 3; l ++){
						if(a[h][l+1] == 0){
							a[h][l+1] = a[h][l];
							a[h][l] = 0;
						}
					}
				}
			}
			break;
		case 'i':
		case 'I':       //存档当前游戏格局 
			Establish_file();//创建用于存档的文件 
			Write_file(p_cnt, score);//调用存档函数 
			break;
		case 'o':
		case 'O':
			sum = Read_file(p_cnt);//读档
			break;
		case 'p':
		case 'P':
			exit(0);//退出程序 
		default:
			break;
	}
	
	return sum;
}

void Move()
{
	int h, l;
	for(h = 0; h < 4; h ++){
		for(l = 0; l < 4; l ++){
			A[h][l] = a[h][l];
		}
	}
}

int If_move()
{
	int h, l, sign = 0;
	for(h = 0; h < 4; h ++){
		for(l = 0; l < 4; l ++){
			if(a[h][l] != A[h][l]){//未进入条件框,说明滑块没有发生移动 
				sign = 1;
				goto out;
			}
		}
	}
	out:
		return sign;
}

int Over()
{
	int over = 0;
	int h, l;
	for(h = 0; h < 4; h ++){
		for(l = 0; l < 4; l ++){
			if(a[h][l] == 0){//有空格 
				over = 1;//游戏继续 
				return 1;	
			}
		}
	}
	if(over == 0){//没有空格 
		for(h = 0; h < 3; h ++){
			for(l = 0; l < 3; l ++){
				if(a[h][l] == a[h][l+1]){
					over = 1;//游戏继续 
					break;
				}
				else if(a[h][l] == a[h+1][l]){
					over = 1;//游戏继续 
					break;
				}
			}
			if(over == 1){
				break;
			} 
		}
	}
	return over;//游戏结束 
}

void Establish_game()//创建文件 
{
	int h;
    if(h = fopen(name_max, "wb") == NULL){   //函数fopen()返回NULL则创建文件失败 
    	printf("\t\t创建文件失败!程序即将自动退出 . . .\n");
    	Sleep(3000);//睡眠3000毫秒,即停留3秒钟 
		exit(0); //退出程序
    }
}

void Write_max(int score)//写入文件 
{
	/*FILE *fp是指向文件的指针*/ 
	FILE *fp=fopen(name_max,"at+");// at+读写打开或着建立一个文本文件;允许读写。
	if(fp==NULL)  //函数fopen()返回NULL则创建文件失败
	{
		printf("\t\t保存最高分失败!程序即将自动退出 . . .");
    	Sleep(3000);//睡眠3000毫秒,即停留3秒钟 
		exit(0); //退出程序
	}
	else{
		fprintf(fp, "%d", score);//将score的值写入*pf指向的文件内 
	}
	fclose(fp);//关闭*pf指向的文件 
}

int Read_max()//读出文件 
{
	int max_score = 0;
	FILE *fp=fopen(name_max,"at+");// at+读写打开或着建立一个文本文件;允许读写。
	if(fp==NULL)
	{
		printf("\t\t读取失败!程序即将自动退出 . . .");
    	Sleep(3000);//睡眠3000毫秒,即停留3秒钟 
		exit(0); //退出程序
	}
	else{
		fscanf(fp, "%d", &max_score);//从*pf指向的文件内数值赋值给max_score
	}
	fclose(fp);//关闭*pf指向的文件
	
	return max_score;//返回最高记录的值 
}

void Establish_file()//创建文件 
{
	int h;
    if(h = fopen(name_file, "wb") == NULL){   //函数fopen()返回NULL则创建文件失败 
    	printf("\t\t创建文件失败!程序即将自动退出 . . .\n");
    	Sleep(3000);//睡眠3000毫秒,即停留3秒钟 
		exit(0); //退出程序
    }
}

void Write_file(int *p_cnt, int score) 
{
	int h, l;
	FILE *fp=fopen(name_file,"at+");// at+读写打开或着建立一个文本文件;允许读写。
	if(fp==NULL)
	{
		printf("\t\t存档失败!程序即将自动退出 . . .\n");
		Sleep(3000);//睡眠3000毫秒,即停留3秒钟 
		exit(0);
	}
	else{
		for(h = 0; h < 4; h ++){
			for(l = 0; l < 4; l ++){
				fprintf(fp, "%d ", a[h][l]);
			}
		}
	}
	fprintf(fp, "%d ", score);
	fprintf(fp, "%d ", *p_cnt-1);
	printf("\t\t存档成功!游戏即将自动退出 . . .\n");
	Sleep(3000); //睡眠3000毫秒,即停留3秒钟 
	exit(0);
	fclose(fp);//关闭文件 
}

int Read_file(int *p_cnt)
{
	int h, l, score = 0;
	FILE *fp=fopen(name_file,"at+");// at+读写打开或着建立一个文本文件;允许读写。
	if(fp==NULL)
	{
		printf("\t\t读档失败!程序即将自动退出 . . .\n");
		Sleep(3000); //睡眠3000毫秒,即停留3秒钟 
		exit(0);
	}
	else{
		for(h = 0; h < 4; h ++){
			for(l = 0; l < 4; l ++){
				fscanf(fp, "%d ", &a[h][l]);
			}
		}
	}
	fscanf(fp, "%d ", &score);
	fscanf(fp, "%d ", p_cnt);
	fclose(fp);	//关闭文件 
	
	return score;
} 

void again()//是否继续游戏 
{
    printf("\t\t╔══════════════════════════════════════════════╗\n"); 
    printf("\t\t║                   您已失败                   ║\n");
    printf("\t\t╟──────────────────────────────────────────────╢\n");
    printf("\t\t║是否继续:                                    ║\n");
    printf("\t\t║          ┌───┐                               ║\n");
    printf("\t\t║          │ 1 │ 扶我起来,我还能再来一局!    ║\n");
    printf("\t\t║          └───┘                               ║\n");
    printf("\t\t║          ┌───┐                               ║\n");
    printf("\t\t║          │ 2 │ 不了不了,我要学习!          ║\n");
    printf("\t\t║          └───┘                               ║\n");
    printf("\t\t╚══════════════════════════════════════════════╝\n");
	if(_getch() == '1'){
		system("cls");//清屏
		int h, l;
		for(h = 0; h < 4; h ++){
			for(l = 0; l < 4; l ++){
				a[h][l] = 0;
				A[h][l] = 0;
			}
		}
		Menu();//回到菜单  
	}
	else {
		printf("\t\t游戏结束!\n");
	} 
}

int color(int c)
{
	SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),
							BACKGROUND_INTENSITY |
							BACKGROUND_BLUE |
							BACKGROUND_RED |
							BACKGROUND_GREEN |
							c);
	return 0;
}

void box_color(int x)
{
	switch(x){
		case 2:
			color(8);
			break;
		case 4:
			color(0);
			break;
		case 8:
			color(2);
			break;
		case 16:
			color(6);
			break;
		case 32:
			color(10);
			break;
		case 64:
			color(3);
			break;
		case 128:
			color(9);
			break;
		case 256:
			color(11);
			break;
		case 512:
			color(5);
			break;
		case 1024:
			color(13);
			break;
		case 2048:
			color(12);
			break;
		default :
			color(4);
			break;
	}
}

你可能感兴趣的:(C)