C语言实现2048小游戏

 更新时间:2018年05月03日 16:34:37   作者:毒初莱式鲨壁  
这篇文章主要为大家详细介绍了C语言实现2048小游戏,注释清晰,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

本文实例为大家分享了C语言实现2048游戏的具体代码,供大家参考,具体内容如下

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

#include <stdio.h>
#include <stdlib.h>
#include <conio.h> /*使用getch()函数*/
#include <time.h>
#include <windows.h> /*使用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语言读写配置文件的方法

    C语言读写配置文件的方法

    这篇文章主要介绍了C语言读写配置文件的方法,包括C语言读写ini配置文件所涉及的文件读写技巧,以及完整的源文件及头文件实现方法,需要的朋友可以参考下
    2015-07-07
  • C语言实现memcpy函数的使用示例

    C语言实现memcpy函数的使用示例

    在C语言中,我们可以自己实现 memcpy 函数来实现内存数据的拷贝操作,本文就来介绍一下C语言实现memcpy函数的使用示例,感兴趣的可以了解一下
    2023-09-09
  • 详解VSCode下C++环境配置过程

    详解VSCode下C++环境配置过程

    这篇文章主要介绍了VSCode C++环境配置过程,在这大家需要在代码的目录下的.vscode文件夹下创建launch.json、tasks.json,具体实现过程跟随小编一起看看吧
    2021-11-11
  • 共用体的定义与应用详细解析

    共用体的定义与应用详细解析

    共同体的定义类似结构体,不过共同体的所有成员都在同一段内存中存放,起始地址一样,并且同一时刻只能使用其中的一个成员变量
    2013-08-08
  • c++中为什么不提倡使用vector示例详解

    c++中为什么不提倡使用vector示例详解

    这篇文章主要给大家介绍了关于c++中为什么不提倡使用vector的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用c++具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
    2019-08-08
  • C++如何将二叉搜索树转换成双向循环链表(双指针或数组)

    C++如何将二叉搜索树转换成双向循环链表(双指针或数组)

    这篇文章主要介绍了C++如何将二叉搜索树转换成双向循环链表(双指针或数组),具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-05-05
  • c++中关于max_element()函数解读

    c++中关于max_element()函数解读

    这篇文章主要介绍了c++中关于max_element()函数解读,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-02-02
  • Qt QML使用虚拟键盘的示例代码

    Qt QML使用虚拟键盘的示例代码

    这篇文章主要为大家详细介绍了Qt QML使用虚拟键盘的相关知识,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下
    2024-01-01
  • C语言数据的存储详解

    C语言数据的存储详解

    本文详细讲解了C语言数据的存储,文中通过示例代码介绍的非常详细。对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-12-12
  • getdate()函数的用法实例

    getdate()函数的用法实例

    getdate()函数的用法实例,需要的朋友可以参考一下
    2013-03-03

最新评论