牛刀小试 - C++ 实现2048(可存档)

2024-01-10 13:52

本文主要是介绍牛刀小试 - C++ 实现2048(可存档),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

参考文档

借助了这位大佬的开发思路, 开发过程中学到了很多
C语言实现《2048游戏》

技术点:

system调整控制台大小的问题

unsigned and 符号位

C++对齐输出(左对齐和右对齐)

C++ goto语句详解

完整代码

/*********************************************************************
程序名: 贪吃蛇
*********************************************************************/
#define _CRT_SECURE_NO_WARNINGS
#define _CRT_NONSTDC_NO_DEPRECATE
#include <iostream> // 对应c中的#include <stdio.h>
#include <cstdlib>  // 对应C中的#include <stdlib.h>
#include <ctime>	// 对应c中的#include <time.h>
#include <conio.h> // 使用getch()函数
#include <windows.h> //使用Sleep()函数
#include <iomanip> // C++ 输出对齐函数
#include <fstream> // 文件操作头函数using namespace std;void Menu();//菜单
void Rule_of_game();//游戏规则 
void Begin(); //开始 
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 Write_max(int score);//向2048游戏-最高记录写入最高分 
int Read_max();//读出最高分记录的文件
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游戏-最高记录.txt";
char *name_file = "[山海]-2048游戏.txt";int main()
{system("mode con cols=90 lines=30");  //调整控制台大小system("title 2048超级大大型游戏"); //程序标题 system("color F0");//F 表示背景颜色,0表示前景颜色Menu();system("PAUSE");return 0;
}void Menu() //菜单
{cout << "\t\t║   欢迎使用由[山海]制作的2048超级大大型游戏   ║\n";cout << "\t\t╟──────────────────────────────────────────────╢\n";cout << "\t\t║请输入选项:                                  ║\n";cout << "\t\t║              ┌───┐                           ║\n";cout << "\t\t║              │ 1 │ 游戏规则                  ║\n";cout << "\t\t║              └───┘                           ║\n";cout << "\t\t║              ┌───┐                           ║\n";cout << "\t\t║              │ 2 │ 开始游戏                  ║\n";cout << "\t\t║              └───┘                           ║\n";cout << "\t\t║              ┌───┐                           ║\n";cout << "\t\t║              │ 3 │ 继续游戏                  ║\n";cout << "\t\t║              └───┘                           ║\n";cout << "\t\t║              ┌───┐                           ║\n";cout << "\t\t║              │ 4 │ 退出游戏                  ║\n";cout << "\t\t║              └───┘                           ║\n";cout << "\t\t╚══════════════════════════════════════════════╝\n";int x = 1, max = 0;while (x){switch (getch())		// getch()函数检测按键。{case '1':x = 0;Rule_of_game();//游戏规则Menu();break;case '2':x = 0;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;}}Begin(); //开始游戏 break;case '3':x = 0;system("cls");//清屏max = Read_max();//读取之前的最高记录 Begin(); //开始游戏 break;case '4':exit(0);default:cout << "输入了非法选项,请重新选择!" << endl;}}
}void Rule_of_game()
{system("cls");//清屏 cout << "╔══════════════════════════════════════════════════════════════════════════════════╗" << endl;cout << "║本游戏通过按键W、S、A、D(不区分大小写)四个键分别控制滑块上移、下移、左移和右移。 ║" << endl;cout << "║滑块移动的过程中,如有相邻且相等数字的滑块将会相加,并获得相应的分数。            ║" << endl;cout << "║当棋盘上的所有位置均有数字,且不能合成,则游戏结束。本游戏未设置游戏成功。         ║"<< endl;cout << "║游戏过程中输入I即为存档并退出游戏,输入O即为读档,输入P则退出游戏。               ║"<< endl;cout << "║“开始游戏”则清除最高记录及存档、“继续游戏”则保存之前的最高记录,且可以读档。       ║" << endl;cout << "╚══════════════════════════════════════════════════════════════════════════════════╝" << endl;system("pause");//暂停 system("cls");//清屏 
}void Begin()
{int score = 0;int sign = 1;int h, l, cnt = 0;int *p_cnt = &cnt;while (1){cout << "\t\t╔══════════════════════════════════════════════╗" << endl;cout << "\t\t║   欢迎使用由[山海]制作的2048超级大大型游戏  ║" << endl;cout << "\t\t╟──────────────────────────────────────────────╢" << endl;cout << "\t\t║移动:   ┌───┐        存档: 读档: 退出:  ║" << endl;cout << "\t\t║         │ W │                                ║" << endl;cout << "\t\t║     ┌───┼───┼───┐    ┌───┐ ┌───┐ ┌───┐       ║" << endl;cout << "\t\t║     │ A │ S │ D │    │ I │ │ O │ │ P │       ║" << endl;cout << "\t\t║     └───┴───┴───┘    └───┘ └───┘ └───┘       ║" << endl;cout << "\t\t╚══════════════════════════════════════════════╝" << endl;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(); // 打印棋盘int max = Read_max();printf("\t\t移动的步数:%d\t当前得分:%d\n\t\t最高记录:%d\n", cnt - 1, score, max);Move(); //保留棋盘score += Get(p_cnt, score);//得分if (score > max){Write_max(score);//保存此次记录}sign = If_move();//判断棋盘是否有变动 if (Over() == 0){if (max < score){//打破记录 Write_max(score);//保存此次记录cout << "\t\t恭喜您已打破记录!" << endl;}break;}system("cls"); //清屏}
}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':       //存档当前游戏格局 Write_file(p_cnt, score);//调用存档函数 break;case 'o':case 'O':sum = Read_file(p_cnt);//读档break;case 'p':case 'P':system("cls"); //清屏Menu();//回到菜单 default:break;}return sum;
}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(0));s = ((unsigned)rand() % 2);s = s == 0 ? 2 : 4;return s;
}int Random_number2() //随机生成二维数组的下标
{int x;x = ((unsigned)rand() % 4);return x;
}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 Write_max(int score)//写入文件 
{ofstream fout(name_max);        //读写操作,对打开的文件可进行读写操作 fout << score;fout.close();
}int Read_max() // 读取文件
{int max_score = 0;ifstream fin(name_max, ios::in);if (!fin){cout << "\t\t读取失败!程序即将自动退出 . . .";Sleep(3000);//睡眠3000毫秒,即停留3秒钟 exit(0); //退出程序}else{fin >> max_score;fin.close();}return max_score;//返回最高记录的值 
}void Write_file(int *p_cnt, int score)
{int h, l;ofstream fout(name_file);   if (!fout){cout << "\t\t存档失败!程序即将自动退出 . . ." << endl;Sleep(3000);//睡眠3000毫秒,即停留3秒钟 exit(0);}else{for (h = 0; h < 4; h++){for (l = 0; l < 4; l++){fout << a[h][l] << " ";}}}fout << score << " ";fout << *p_cnt - 1;	cout << "\t\t存档成功!游戏即将自动退出 . . ." << endl;Sleep(3000); //睡眠3000毫秒,即停留3秒钟 exit(0);fout.close();
}int Read_file(int *p_cnt)
{int h, l, score = 0;ifstream fin(name_file , ios::in);if (!fin){cout << "\t\t读档失败!程序即将自动退出 . . ." << endl;Sleep(3000); //睡眠3000毫秒,即停留3秒钟 exit(0);}else{for (h = 0; h < 4; h++){for (l = 0; l < 4; l++){fin >> a[h][l];}}}fin >> score;fin >> *p_cnt;fin.close();Table(); // 打印棋盘return score;
}void again()
{cout << "\t\t╔══════════════════════════════════════════════╗" << endl;cout << "\t\t║                   您已失败                    ║" << endl;cout << "\t\t╟──────────────────────────────────────────────╢" << endl;cout << "\t\t║是否继续:                                     ║" << endl;cout << "\t\t║          ┌───┐                               ║" << endl;cout << "\t\t║          │ 1 │ 扶我起来,我还能再来一局!      ║" << endl;cout << "\t\t║          └───┘                               ║" << endl;cout << "\t\t║          ┌───┐                               ║" << endl;cout << "\t\t║          │ 2 │ 不了不了,我要学习!            ║" << endl;cout << "\t\t║          └───┘                               ║" << endl;cout << "\t\t╚══════════════════════════════════════════════╝" << endl;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 {cout << "\t\t游戏结束!" << endl;}
}
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++ 实现2048(可存档)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/591034

相关文章

Python如何实现读取csv文件时忽略文件的编码格式

《Python如何实现读取csv文件时忽略文件的编码格式》我们再日常读取csv文件的时候经常会发现csv文件的格式有多种,所以这篇文章为大家介绍了Python如何实现读取csv文件时忽略文件的编码格式... 目录1、背景介绍2、库的安装3、核心代码4、完整代码1、背景介绍我们再日常读取csv文件的时候经常

Golang中map缩容的实现

《Golang中map缩容的实现》本文主要介绍了Go语言中map的扩缩容机制,包括grow和hashGrow方法的处理,具有一定的参考价值,感兴趣的可以了解一下... 目录基本分析带来的隐患为什么不支持缩容基本分析在 Go 底层源码 src/runtime/map.go 中,扩缩容的处理方法是 grow

Go 1.23中Timer无buffer的实现方式详解

《Go1.23中Timer无buffer的实现方式详解》在Go1.23中,Timer的实现通常是通过time包提供的time.Timer类型来实现的,本文主要介绍了Go1.23中Timer无buff... 目录Timer 的基本实现无缓冲区的实现自定义无缓冲 Timer 实现更复杂的 Timer 实现总结在

基于Python实现多语言朗读与单词选择测验

《基于Python实现多语言朗读与单词选择测验》在数字化教育日益普及的今天,开发一款能够支持多语言朗读和单词选择测验的程序,对于语言学习者来说无疑是一个巨大的福音,下面我们就来用Python实现一个这... 目录一、项目概述二、环境准备三、实现朗读功能四、实现单词选择测验五、创建图形用户界面六、运行程序七、

Vue中动态权限到按钮的完整实现方案详解

《Vue中动态权限到按钮的完整实现方案详解》这篇文章主要为大家详细介绍了Vue如何在现有方案的基础上加入对路由的增、删、改、查权限控制,感兴趣的小伙伴可以跟随小编一起学习一下... 目录一、数据库设计扩展1.1 修改路由表(routes)1.2 修改角色与路由权限表(role_routes)二、后端接口设计

C#集成DeepSeek模型实现AI私有化的流程步骤(本地部署与API调用教程)

《C#集成DeepSeek模型实现AI私有化的流程步骤(本地部署与API调用教程)》本文主要介绍了C#集成DeepSeek模型实现AI私有化的方法,包括搭建基础环境,如安装Ollama和下载DeepS... 目录前言搭建基础环境1、安装 Ollama2、下载 DeepSeek R1 模型客户端 ChatBo

Qt实现发送HTTP请求的示例详解

《Qt实现发送HTTP请求的示例详解》这篇文章主要为大家详细介绍了如何通过Qt实现发送HTTP请求,文中的示例代码讲解详细,具有一定的借鉴价值,感兴趣的小伙伴可以跟随小编一起学习一下... 目录1、添加network模块2、包含改头文件3、创建网络访问管理器4、创建接口5、创建网络请求对象6、创建一个回复对

C++实现回文串判断的两种高效方法

《C++实现回文串判断的两种高效方法》文章介绍了两种判断回文串的方法:解法一通过创建新字符串来处理,解法二在原字符串上直接筛选判断,两种方法都使用了双指针法,文中通过代码示例讲解的非常详细,需要的朋友... 目录一、问题描述示例二、解法一:将字母数字连接到新的 string思路代码实现代码解释复杂度分析三、

grom设置全局日志实现执行并打印sql语句

《grom设置全局日志实现执行并打印sql语句》本文主要介绍了grom设置全局日志实现执行并打印sql语句,包括设置日志级别、实现自定义Logger接口以及如何使用GORM的默认logger,通过这些... 目录gorm中的自定义日志gorm中日志的其他操作日志级别Debug自定义 Loggergorm中的

Spring Boot整合消息队列RabbitMQ的实现示例

《SpringBoot整合消息队列RabbitMQ的实现示例》本文主要介绍了SpringBoot整合消息队列RabbitMQ的实现示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的... 目录RabbitMQ 简介与安装1. RabbitMQ 简介2. RabbitMQ 安装Spring