C语言——2048完整版

2048是一个简单又有趣的小游戏,相信大家都接触并了解过,那如何通过代码来实现他呢?下面就让我们来一起看看。

目录

1、头文件

2、主函数

3、 StarGame

 4、GetNum

 5、Show

6、Picture

 7、GetButton

8、MergeLeft

 9、MergeUp

10、MergeRight

11、MergeDown

 12、MergeNum

 13、IsGameover

 14、Run

15、最后附上运行结果一张


1、头文件

其中<graphics.h>是为了使用easyx图形工具,使我们的游戏最终成品得以图像化,<time.h>是为了生成随机种子,保证每一次所出现的数字足够具有随机性。同时还需要两个宏定义,来规范二维数组。以及各个方向的键盘扫描码。

#define _CRT_SECURE_NO_WARNINGS //这一句必须放在第一行
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <conio.h>
#include <graphics.h>		// 引用图形库头文件#define ROW 4
#define COL ROW
#define KEY_UP 72                                                                 /*  方向键'上'的扫描码码值     */
#define KEY_DOWN 80                                                          /*  方向键'下'的扫描码码值     */
#define KEY_LEFT  75                                                             /*  方向键'左'的扫描码码值     */
#define KEY_RIGHT 77                                                           /*  方向键'右'的扫描码码值     */

2、主函数

首先我们先建立一个图形窗口,设置为450*450像素,并且在代码最后关闭绘图窗口,然后设置一个数组,用来存放2048中的每一个数字。一切准备工作做好之后我们就可以调用StarGame与Run函数了。下面我们来一步一步实现这两个函数

int main()
{initgraph(450, 450);	// 创建绘图窗口,大小为 450x450 像素int arr [ROW][COL] = { 0 };StarGame(arr);Run(arr);//运行游戏closegraph();			// 关闭绘图窗口
}

3、 StarGame

想一想2048,游戏开始时会在随机位置生成一个数字,并且打印在屏幕上,所以在这个函数中我们需要“获取随机数字”GetNum,与“打印”Show。

void StarGame(int (*arr)[COL])
{GetNum(arr);GetNum(arr);//提供一个随机数字Show(arr);
}

 4、GetNum

在这个函数中我们通过两步随机数字组合套路对坐标随机性进行控制,再将生成数字的可能性进行调整,最后进行线性检查,如果生成的随机坐标的位置上已经有数字了就顺延到下一位,如果已经到了末尾就顺延到下一行

void GetNum(int(*arr)[COL])
{static int seed=0;//静态变量不会销毁每次都是一样的值srand((unsigned int)time(NULL) + seed);//上面两步是随机数字套路,产生随机种子seed++;//坐标随机int row = rand() % ROW;int col = rand() % COL;//数字随机int num = 2;if (rand() % 5 == 0)//把4的概率置为1/5num = 4;while (arr[row][col]!=0){col++;if (col == COL){row =(row + 1) % ROW;col = 0;}}//线性检查,如果第row行col列有数字就顺延到下一个arr[row][col] = num;
}

 5、Show

加载背景图片,并且打印在屏幕上,注意这里数字也需要背景图片,所以引入一个新函数Picture。

void Show(int(*arr)[COL])//打印
{//system("cls");IMAGE img;loadimage(&img, _T("bk.png"));putimage(0, 0, &img);for (int i = 0; i < ROW; i++){for (int j = 0; j < COL; j++){Picture(arr, i, j);//输出数字对应的照片}}
}

6、Picture

如果数字为“0”时则不需要调用图片,如果数字为“2”等其他数字时则需要调用图片,注意这里的loadimage为easyx的函数。如果有需要这些数字图片的,可以私信我。

bool Picture(int(*arr)[COL], int row, int col)
{IMAGE img;switch (arr[row][col]){case 0://不需要加载图片return false;case 2:loadimage(&img, _T("2.jpg"), 100, 100, true); //这些图片的大小都超过100,100,需要进行相应的缩小break;case 4:loadimage(&img, _T("4.jpg"), 100, 100, true);break;case 8:loadimage(&img, _T("8.jpg"), 100, 100, true);break;case 16:loadimage(&img, _T("16.jpg"), 100, 100, true);break;case 32:loadimage(&img, _T("32.jpg"), 100, 100, true);break;case 64:loadimage(&img, _T("64.jpg"), 100, 100, true);break;case 128:loadimage(&img, _T("128.jpg"), 100, 100, true);break;case 256:loadimage(&img, _T("256.jpg"), 100, 100, true);break;case 512:loadimage(&img, _T("512.jpg"), 100, 100, true);break;case 1024:loadimage(&img, _T("1024.jpg"), 100, 100, true);break;case 2048:loadimage(&img, _T("2048.jpg"), 100, 100, true);break;default:break;}putimage(10 + col * 110, 10 + row * 110, &img);return true;
}

 7、GetButton

想要控制游戏的方向,就需要从键盘读取,所以在这个函数里我们来进行“方向获取”这项工作。

int GetButton()
{ExMessage m;while (peekmessage(&m, EX_KEY)){if (m.message == WM_KEYDOWN){switch (m.vkcode){case VK_LEFT:return 1;case VK_UP:return 2;case VK_RIGHT:return 3;case VK_DOWN:return 4;}}}return 0;
}

接下来我们来上下左右四个方向来添加代码

8、MergeLeft

bool MergeLeft(int(*arr)[COL])
{int index;bool flg = false;for (int i = 0; i < ROW; i++){index = -1;for (int j = 0; j < COL; j++){if (arr[i][j] != 0 && index == -1)index = j;//如果第ij个数字不是0,并且第一个值还没找到,所以把index赋值成当前数字下标else if (arr[i][j] != 0 && arr[i][j] != arr[i][index])index = j;//如果第ij个数字不是0,并且与找到的前一个数字不相等,则抛弃上一个else if (arr[i][j] != 0){arr[i][index] *= 2;arr[i][j] = 0;//如果第ij个数字不是0,并且与找到的值相等,给找到的值*2,并把当前值赋为0flg = true;//如果发生了合并}}index = 0;//可以保存数据的项的下标for (int j = 0; j < COL; j++){if (arr[i][j] != 0)//需要移动{arr[i][index] = arr[i][j];if (index != j){arr[i][j] = 0;flg = true;//如果发生了移动}index++;}	}}return flg;
}

 9、MergeUp

bool MergeUp(int(*arr)[COL])
{int index;//第一个非0值的下标(行)bool flg = false;for (int j = 0; j < COL; j++)//列{index = -1;for (int i = 0; i < ROW; i++)//行,合并数据{if (arr[i][j] != 0 && index == -1)index = i;else if (arr[i][j] != 0 && arr[i][j] != arr[index][j])index = i;else if (arr[i][j] != 0)//合并{arr[index][j] *= 2;arr[i][j] = 0;flg = true;}}index = 0;//可以存放数据的下标(行)for (int i = 0; i < ROW; i++)//移动数据{if (arr[i][j] != 0){arr[index][j] = arr[i][j];if (index != i){arr[i][j] = 0;flg = true;}index++;}}}return flg;
}

10、MergeRight

bool MergeRight(int(*arr)[COL])
{int index;bool flg = false;for (int i = 0; i <ROW; i++){index = -1;for (int j = 3; j >=0; j--){if (arr[i][j] != 0 && index == -1)index = j;//如果第ij个数字不是0,并且第一个值还没找到,所以把index赋值成当前数字下标else if (arr[i][j] != 0 && arr[i][j] != arr[i][index])index = j;//如果第ij个数字不是0,并且与找到的前一个数字不相等,则抛弃上一个else if (arr[i][j] != 0){arr[i][index] *= 2;arr[i][j] = 0;//如果第ij个数字不是0,并且与找到的值相等,给找到的值*2,并把当前值赋为0flg = true;//如果发生了合并}}index = 3;//可以保存数据的项的下标for (int j =3; j >=0; j--){if (arr[i][j] != 0)//需要移动{arr[i][index] = arr[i][j];if (index != j){arr[i][j] = 0;flg = true;//如果发生了移动}index--;}}}return flg;
}

11、MergeDown

bool MergeDown(int(*arr)[COL])
{int index;//第一个非0值的下标(行)bool flg = false;for (int j = 0; j<COL; j++)//列{index = -1;for (int i =3; i >=0; i--)//行,合并数据{if (arr[i][j] != 0 && index == -1)index = i;else if (arr[i][j] != 0 && arr[i][j] != arr[index][j])index = i;else if (arr[i][j] != 0)//合并{arr[index][j] *= 2;arr[i][j] = 0;flg = true;}}index = 3;//可以存放数据的下标(行)for (int i = 3; i>=0; i--)//移动数据{if (arr[i][j] != 0){arr[index][j] = arr[i][j];if (index != i){arr[i][j] = 0;flg = true;}index--;}}}return flg;
}

 12、MergeNum

保存方向

bool MergeNum(int(*arr)[COL], int direct)
{bool flg = false;switch (direct)//当()里的表达式和某一个case值相同时进入{case 1://向左flg = MergeLeft(arr);break;case 2://向上flg= MergeUp(arr);break;case 3://向右flg = MergeRight(arr);break;case 4://向下flg = MergeDown(arr);break;default:break;}return flg;
}

 13、IsGameover

判断游戏是否结束

bool IsGameover(int(*arr)[COL])
{int count0 = 0;//统计0的个数int i;int j;for (i = 0; i < ROW; i++)//判断是否有空格{for (j = 0; j < COL; j++){if (arr[i][j] == 0)count0++;}}if (count0 != 0)//还有空格return false;//游戏没有结束for (i = 0; i < ROW; i++)//是否有相邻的数字一样{for (j = 0; j < COL; j++){if (j + 1 < COL)//判断当前的值和右边是否相同if (arr[i][j] == arr[i][j + 1])return false;//游戏没有结束if (i + 1 < ROW)//判断当前的值和下边是否相同if (arr[i][j] == arr[i + 1][j])return false;//游戏没有结束}}return true;
}

 14、Run

最后就是我们刚开始提到的Run函数

void Run(int(*arr)[COL])
{int direct;//从键盘获得一个方向while (1){direct= GetButton();//if (!MergeNum(arr, direct))//	continue;//如果没有发生合并或移动就不产生新的数据if (!MergeNum(arr, direct))continue;GetNum(arr);Show(arr);if (IsGameover(arr)){return;//判断游戏是否结束}}
}

15、最后附上运行结果一张

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/212835.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

webpack优化打包速度

webpack打包速度太慢 优化 1.多线程打包 js压缩和loader 2.优化启动速度 hard-source-webpack-plugin 3.删除无用的 分析类插件 4.DllPlugin通道打包 1.webpack多线程打包 loader loader 使用 thread-loader 将他放置你要使用的loader前面就行&#xff0c;不过这个lorder例如s…

HarmonyOS学习--TypeScript语言学习(一)

注意&#xff1a;这只是我学习的笔记&#xff01;&#xff01;&#xff01; 注意&#xff1a;这只是我学习的笔记&#xff01;&#xff01;&#xff01; 注意&#xff1a;这只是我学习的笔记&#xff01;&#xff01;&#xff01; 本章目录如下&#xff1a; 一、TypeScript语言…

cmake生成表达式

不积小流&#xff0c;无以成江海 <CONFIG:RELEASE> config这个关键字&#xff0c;主要是看CMAKE_BUILD_TYPE这个变量的值是不是和冒号后的一样&#xff0c;一样的话就返回true, 否则就是false. cmake_minimum_required(VERSION 3.10) project(Test) set(CMAKE_CXX_STA…

每天学习一点shell系列(2)—函数的参数传递

参考博客&#xff1a;shell 脚本-10函数_eno_zeng的博客-CSDN博客 $n 或 ${n} &#xff1a;函数内使用 $n 或 ${n} 访问对应的参数, 数字代表参数的前后顺序, $1 代表第一个参数, $2 代表第三个参数, $n 代表第n个参数&#xff1b;当n>10时&#xff0c;需要使用${n}来获取参…

harmony开发之Text组件的使用

TextInput、TextArea是输入框组件&#xff0c;通常用于响应用户的输入操作&#xff0c;比如评论区的输入、聊天框的输入、表格的输入等&#xff0c;也可以结合其它组件构建功能页面&#xff0c;例如登录注册页面。 图片来源黑马程序员 Text组件的使用&#xff1a; 文本显示组…

算法学习—排序

排序算法 一、选择排序 1.算法简介 选择排序是一个简单直观的排序方法&#xff0c;它的工作原理很简单&#xff0c;首先从未排序序列中找到最大的元素&#xff0c;放到已排序序列的末尾&#xff0c;重复上述步骤&#xff0c;直到所有元素排序完毕。 2.算法描述 1&#xff…

PostgreSQL 技术内幕(十二) CloudberryDB 并行化查询之路

随着数据驱动的应用日益增多&#xff0c;数据查询和分析的量级和时效性要求也在不断提升&#xff0c;对数据库的查询性能提出了更高的要求。为了满足这一需求&#xff0c;数据库引擎不断经历创新&#xff0c;其中并行执行引擎是性能提升的重要手段之一&#xff0c;逐渐成为数据…

Spring全面详解

目录 1. Spring 概述 1.1 Spring是什么 1.2 Spring的作用 1.3 Spring IoC是什么 2. Spring 快速入门 3. Spring Bean 3.1 的实例化方式 空参构造器 3.2 的属性注入 全参构造器注入 setter方法注入 策略模式 3.3 注解管理 3.4 注解方式的属性注入 1. Spring 概述 …

os.walk()遍历文件夹/文件

天行健&#xff0c;君子以自强不息&#xff1b;地势坤&#xff0c;君子以厚德载物。 每个人都有惰性&#xff0c;但不断学习是好好生活的根本&#xff0c;共勉&#xff01; 文章均为学习整理笔记&#xff0c;分享记录为主&#xff0c;如有错误请指正&#xff0c;共同学习进步。…

智能优化算法应用:基于法医调查算法无线传感器网络(WSN)覆盖优化 - 附代码

智能优化算法应用&#xff1a;基于法医调查算法无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用&#xff1a;基于法医调查算法无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.法医调查算法4.实验参数设定5.算法结果6.参考…

Unity传送门特效: The Beautiful Portal/Level up/Teleport/Warp VFX

7种不同风格的传送门特效! 每个传送门都有一个轻型和重型版本。 每个版本都有一个"无循环”和一个"无限”预制件:D 总共有28个预制件 -VFX完全使用Unity的粒子系统和基本的Unity着色器。 使用标准渲染管道中制作了这个资产。所以VFX的功能就像视频宣传片一样。 同时,…

基于Python+WaveNet+MFCC+Tensorflow智能方言分类—深度学习算法应用(含全部工程源码)(一)

目录 前言引言总体设计系统整体结构图系统流程图 运行环境Python环境TensorFlow 环境Jupyter Notebook环境Pycharm 环境 相关其它博客工程源代码下载其它资料下载 前言 博主前段时间发布了一篇有关方言识别和分类模型训练的博客&#xff0c;在读者的反馈中发现许多小伙伴对方言…

【GEE笔记】随机森林特征重要性计算并排序

随机森林是一种基于多个决策树的集成学习方法&#xff0c;可以用于分类和回归问题。在gee中可以使用ee.Classifier.smileRandomForest()函数来创建一个随机森林分类器&#xff0c;并用它来对影像进行分类。 随机森林分类器有一个重要的属性&#xff0c;就是可以计算每个特征&a…

什么是https加密协议?

前言&#xff1a; HTTPS&#xff08;全称&#xff1a;Hypertext Transfer Protocol Secure&#xff09; 是一个安全通信通道&#xff0c;它基于HTTP开发用于在客户计算机和服务器之间交换信息。它使用安全套接字层(SSL)进行信息交换&#xff0c;简单来说它是HTTP的安全版&…

MySQL导出ER图为图片或PDF

目录 1、Navicat 生成ER图 1、选择数据库&#xff0c;逆向数据库到模型 2、查看ER图 3、导出ER图 2、使用MySQL官方工具&#xff1a;MySQL Workbench 1、首先连接MySQL数据库 2、点击Database&#xff0c;选择Reverse Engineer 3、填写数据库信息&#xff0c;点Next …

算法复习——6种排序方法的简单回顾

算法复习——6种排序方法的简单回顾 常见排序方法&#xff1a;冒泡排序、选择排序、插入排序、堆排序、归并排序、快速排序的简单回顾 冒泡排序 重复“从序列右边开始比较相邻两个数字的大小,再根据结果交换两个数字的位置” 在冒泡排序中&#xff0c;第 1 轮需要比较 n - 1…

2024黑龙江省职业院校技能大赛信息安全管理与评估样题第二三阶段

2024黑龙江省职业院校技能大赛暨国赛选拔赛 "信息安全管理与评估"样题 *第二阶段竞赛项目试题* 本文件为信息安全管理与评估项目竞赛-第二阶段试题&#xff0c;第二阶段内容包括&#xff1a;网络安全事件响应、数字取证调查和应用程序安全。 极安云科专注技能竞赛…

火狐,要完了!

在过去几年中&#xff0c;关于Firefox 浏览器的衰落有过不少讨论。目前来说&#xff0c;很多公共的以及私营的大型网站都缺乏对Firefox的适当支持。但是Firefox也多次试图“自救”&#xff0c;甚至就在不久前&#xff0c;Mozilla 通过官博发文&#xff0c;表示 Firefox 在 2023…

Milvus 再上新!支持 Upsert、Kafka Connector、集成 Airbyte,助力高效数据流处理

Milvus 已支持 Upsert、 Kafka Connector、Airbyte&#xff01; 在上周的文章中《登陆 Azure、发布新版本……Zilliz 昨夜今晨发生了什么&#xff1f;》&#xff0c;我们已经透露过 Milvus&#xff08;Zilliz Cloud&#xff09;为提高数据流处理效率&#xff0c; 先后支持了 Up…

ardupilot开发 --- git 篇

一些概念 工作区&#xff1a;就是你在电脑里能看到的目录&#xff1b;暂存区&#xff1a;stage区 或 index区。存放在 &#xff1a;工作区 / .git / index 文件中&#xff1b;版本库&#xff1a;本地仓库&#xff0c;存放在 &#xff1a;工作区 / .git 中 关于 HEAD 是所有本地…