2048

作者nasiapp

10月 26, 2022

2048插图

点击蓝字 关注我们

C语言项目2048游戏制作

前言

小年,北方地区是腊月二十三,南方地区是腊月二十四,尽管时间上有差异,但小年一到,意味着所有学生都进入了寒假,小编在这里祝大家小年愉快。

本期目标:实现2048小游戏游戏的基本功能

制作环境:   VS2015

支持VC++2010,VS各个版本

easyx图形库(不知道图形库的点我)

效果预览:

关闭
观看更多
更多
正在加载
正在加载
退出全屏

视频加载失败,请刷新页面再试

2048插图1刷新
2048插图2

2048插图3

因为没有去找图片素材,简单的用easyx提供的绘图函数绘制这样一个简陋的界面。这个游戏呢,对于追求快速节奏的我们来说,不好玩,讲真的我没通过关,也是达成2048这个数字。但是呢,因为2048是个益智游戏,这里面的逻辑还是值得去思考的。

目录

游戏设计

游戏三部曲

游戏优化

01

游戏设计

游戏规则

游戏的规则很简单,你需要控制所有方块向同一个方向运动,两个相同数字方块撞在一起之后合并成为他们的和,每次操作之后会随机生成一个2或者4,终得到一个2048的方块算胜利了。

数字碰撞

数字碰撞是两个相同的数字碰撞之后成为一个他们的和的数字

场景示例:

2048插图4

在这张图片里面我们看列数字{ 2 2 0 4 },这其实是一个一维数组,然后当玩家按下W或者↑键时我们需要对这个一维数组进行数据处理,是将{ 2 2 0 4 }变成{ 4 4 0 0 }。

然后我是怎么实现的呢,分两步,先将数字{ 2 2 0 4 }变成{ 2 2 4 0 },然后循环判断相邻的两个数字是否相同,相同合并。

我们来看一下代码中的实现方式

case72://上caseW:casew://把0向下移动for(intj =0; j <4; j++)//4列分别操作{len =4;for(inti =0; i < len –1; i++){if(map[i][j] ==0){//下面的数字往上移一个格子for(intk = i; k <3; k++){map[k][j] =map[k +1][j];map[k +1][j] =0;}len–;//出现一个 0 len减一i–;//返回原位置检测是否有 0}}for(inti =0; i < len –1; i++){if(map[i][j] ==0)break;//行为0 后面都是0,不进行操作if(map[i][j] ==map[i +1][j])//检测相邻两个数字是否相同,相同合并{map[i][j] *=2;//合并//合并之后后面的数字往前移动一位for(intk = i +1; k <3; k++){map[k][j] =map[k +1][j];map[k +1][j] =0;}//进行打分*score +=map[i][j];}}}break;

别看代码挺长的,其实理解起来特别简单,并且四个方向的代码都是一个模型,复制粘贴,修改点东西,整个游戏的核心代码掌握了,然后是界面弄好看点。由于图方便快捷,我没有去找图片资源,所以做的界面可能比较,嗯,垃圾。这个呢仅供学习,别当真,千万别一根筋的说我要通关,我要2048,微信小程序搜索2048,那个界面好看点。

02

游戏三部曲

主函数 int main()

intmain(){initgraph(MAP_ROW * PIXEL +100, MAP_COL * PIXEL +100);//加载窗口init(map, &score);//初始化地图数据while(1){DrawMap(map, score);//绘制地图Play(map, &score);//玩家操作switch(Judg(map))//判断输赢  对结果进行匹配{case0://赢break;case-1://输break;case1://没有空位置break;case2://还有空位置break;default:break;}}closegraph();return0;}

这个没啥好说的,游戏三部曲

1、加载游戏数据初始化init();)

2、绘制图形(绘图DrawMap();)

3、玩家操作(数据更新Play();)

初始化init()

voidinit(intmap[][MAP_COL],int*score){intx, y;//随机位置参数*score =0;//对成绩进行初始化memset(map,0,sizeof(int)*MAP_ROW*MAP_COL);//初始化地图//对地图进行初始化for(inti =0; i <2😉{x = rand() %4;y = rand() %4;if(map[x][y] ==0){if(rand() %9==0)map[x][y] =4;elsemap[x][y] =2;i++;}}}

2048由于游戏简单,没有什么图片资源啊什么的各种资源的加载,所以初始化函数只需要初始化一些基本的数据。

绘图DrawMap()

voidDrawMap(intmap[][MAP_COL],intscore){wchar_tarr[20];//临时参数setbkcolor(RGB(0,0,0));//背景颜色setlinecolor(RGB(0,255,0));//线条颜色setlinestyle(PS_SOLID,3);//线条风格settextcolor(RGB(0,255,0));//字体颜色settextstyle(20,0,L”宋体”);//字体风格 和 字体大小cleardevice();//清屏BeginBatchDraw();//开始绘制地图for(inti =0; i <=4; ++i){line(PIXEL * i,0+50, PIXEL * i, PIXEL *4+50);//竖线line(0, PIXEL * i +50, PIXEL *4, PIXEL * i +50);//横线}for(inti =0; i <4; ++i){for(intj =0; j <4; ++j){wsprintf(arr,L”%d”,map[i][j]);//将数字写入字符串outtextxy(j * PIXEL +32, i * PIXEL +50+30, arr);//指定位置输出字符串}}//分数settextcolor(RGB(0,255,0));//字体颜色 红色wsprintf(arr,L”score: %d”, score);outtextxy(0,15, arr);//指定位置输出字符串//高分outtextxy(MAP_ROW * PIXEL +10,5,L”高分:”);//指定位置输出字符串wsprintf(arr,L”%d”, MaxScore);outtextxy(MAP_ROW * PIXEL +15,25, arr);//指定位置输出字符串outtextxy(MAP_ROW * PIXEL +10,80,L”↑↓←→”);//指定位置输出字符串outtextxy(MAP_ROW * PIXEL +10,120,L”WSAD”);//指定位置输出字符串outtextxy(MAP_ROW * PIXEL +10,160,L”控制游戏”);//指定位置输出字符串outtextxy(80,360,L”微信公众号:编程学习基地”);//指定位置输出字符串EndBatchDraw();//结束绘制地图}

绘制地图是设置一些字体啊,背景颜色啊,然后是将16宫格画上去,地图里面的数字显示到16宫格上,虽然很繁琐,但是也很简单,调用这些个函数可以了。

数据更新Play()

voidPlay(intmap[][MAP_COL],int* score){intlen;switch(getch()){case75://左caseA:casea:for(inti =0; i <4; i++){len =4;for(intj =0; j < len –1; j++){if(map[i][j] ==0){for(intk = j; k <3; k++){map[i][k] =map[i][k +1];map[i][k +1] =0;}len–;j–;}}for(intj =0; j <3; j++){if(map[i][j] ==0)break;if(map[i][j] ==map[i][j +1]){map[i][j] *=2;for(intk = j +1; k <3; k++){map[i][k] =map[i][k +1];map[i][k +1] =0;}*score +=map[i][j];}}}break;default:break;}}

在游戏设计里面已经说得挺明白了,也示例了W和↑键的代码,这里复制下左和←键的代码凑个牌面。

这里简单提下↑↓←→键的ASCII码值

键ASCII↑72↓80←75→77

添加数字Add()

voidAdd(intmap[][MAP_COL]){//添加数字intx, y;do{x = rand() %4;y = rand() %4;}while(map[x][y] !=0);//找到数字为零的位置if(rand() %9==0)//设置4出现的概率为1/9map[x][y] =4;elsemap[x][y] =2;}

2048游戏是通过没次添加一个数字逼迫玩家消灭数字,函数的功能实现也简单,直接看代码能看得懂,在这里我加了个限制来控制2和4出现的概率。

判断输赢Judg()

intJudg(intmap[][MAP_COL]){intnum =0;//记录0的个数intflag =0;//如果存在一组可以合并的元素 那么flag置为1for(inti =0; i <4; ++i){for(intj =0; j <4; ++j){if(map[i][j] >=2048)return0;//赢if(map[i][j] ==0) num++;//记录0的个数if(j +1<4&&map[i][j] ==map[i][j +1]) flag =1;//右边是不是一样if(i +1<4&&map[i][j] ==map[i +1][j]) flag =1;//下方是不是一样}}if(num ==0&& flag ==0)return-1;//满了并且不能合并  输if(num ==0)return1;//满了 但是可以合并return2;}

判断输赢里面赢好判断了,出现2048赢了,输的话是flag=0,num=0也是地图中没有0,并且每个数字的左边和下面没有相同的数字是输,把逻辑整明白,代码写起来简单。

保存数据WriteData()ReadData()

voidWriteData(intmap[][MAP_COL],intscore){FILE*fp = fopen(“D:\\2048.dat”,“wb”);if(fp ==NULL)return;fwrite(map,sizeof(int)*MAP_ROW*MAP_COL,1, fp);fwrite(&score,sizeof(int),1, fp);fwrite(&MaxScore,sizeof(int),1, fp);fclose(fp);}voidReadData(intmap[][MAP_COL],int* score){FILE*fp = fopen(“D:\\2048.dat”,“rb”);if(fp==NULL)return;fread(map,sizeof(int)*MAP_ROW*MAP_COL,1, fp);fread(score,sizeof(int),1, fp);fread(&MaxScore,sizeof(int),1, fp);fclose(fp);}

这个是将地图中的数据写入到磁盘中,然后怎么写入的怎么读取,我也简单地实现了下数据保存功能,详细的文件操作请看

C语言语法篇之文件操作

03

游戏优化

1. 用带颜色的图片替代简陋的数字,不图啥,图界面好看。

2. 可以加载一张图片做背景,可以是你女朋友友的,如果没有,那用你自己的也可以

3. 学过数据结构,知道栈的同学可以实现操作回退功能,这个我准备年后用推箱子来做个实例演示。

发送关键字「2048」获取源码及示例程序

作者:梦凡

代码:手敲

往期推荐:

热门推荐    扫雷篇

梦凡推荐    贪吃蛇

梦凡推荐    拼图

2048插图5

编程学习看梦凡操作

微信公众号:编程学习基地

QQ学习交流群:879098023

喜欢本篇内容请给我们点个在看

2048插图

作者 nasiapp

在线客服
官方客服
我们将24小时内回复。
12:01
您好,有任何疑问请与我们联系!

选择聊天工具: