2048小游戏

写在开头:

本人初入iOS,刚刚学习OC一个月,学到的东西还比较有限,我利用这有限的知识尝试自己去写一个2048小游戏,难度极低,希望能帮助到广大新手编程爱好者,另外也借此记录下自己平时的学习。

本文主要讲游戏的思路,以及编程时候的注意点,不会刻意去讲代码,游戏代码非常简单,文章底部我会附上代码连接。


先上游戏展示:  设置的滑动屏幕实现移动,所以这里用鼠标代替的


首先先说下我开始打码之前做的准备工作:



第一步---登录2048游戏界面观察游戏界面,了解游戏规则,思考游戏机制,整理编程思路。

送上游戏链接,没玩过的朋友可以熟悉下游戏    点这里玩2048

上面的游戏名字,分数,以及新游戏,游戏信息等内容我们可以用一些简单的Label 或者Button之类的完成,如何将分数跟随游戏变化后面会说到,这里我们主要观察下这个正方形的游戏面板。

游戏机制非常简单,玩家只需要通过上下左右的移动即可参与游戏,游戏规则大家玩一两把就懂,这里直接跳过。观察完毕后我把程序中要实现的功能罗列出来,然后尽量在代码中完成这些功能:

1. 游戏开始的时候是在16个格子中随机出现两个2 

2. 每次移动的时候,数字会挤到移动方向的那一边堆在一起

3. 如果两个数字相同,会挤成一个数字,且是原来数字大小的2倍

细节注意:如果同一行有3个连续的2,如2224,往右边移动的时候是最右边的两个2变成4,结果为244,并非424,并且刚刚产生的这个4并不会与最右边的的4立马合并,而是到下次往右移动的时候才会。

4. 每次成功移动,会随机在一个没有数字的格子里出现一个2

细节注意:若出现下图情况,往右边移动的时候如果不会有变化,则不会出现随机的2,注意加点延迟,用户体验会更好。

5. 格子的颜色会随着数字不同而变化


好,这里游戏的大致规则以及思路想必大家都差不多了解了,应该没有遗漏的地方把。



第二步---游戏界面与二维数组的巧妙结合


第二步的标题我直接把我代码的最重要的地方说出来了,对的就是二维数组,想必聪明的读者看到这里是不是已经有一种恍然大悟的感觉了,把游戏界面转化为一个二维数组,是不是就可以为我们的开发减少了不少的难度呢,当然我也不知道这个游戏的作者的变成思路以及方法,可能也有更好的其它的方法,但我经验太少了,只想到了这一个方法,而且后来成功实现了,本文就以这种思路去进行讲解。

上图所示的界面是不是现在已经变成了这样的一个二维数组

 int array[4][4] = {{0,0,0,0},{0,0,0,2},{0,0,0,2},{0,0,0,0}};

所以我的编程思路就是图中出现的16个格子就是16个Label,它的text属性就是对应的数字,如果数字为0,则设置它的text属性为空即可。然后根据不同的数字给Label的backgroundColor属性设置对应的颜色即可,Label的font属性注意修改一个合适的数值,不然数字变大后很可能格子显示不出来,如果你对细节要求很高,则可以让字体的大小跟随着数字大小而变化。

这里建议手动创建label,并且用一个数组管理它们,这样每次根据二维数组赋值的时候,会比较方便。



第三步---格子移动的核心算法


我觉得这个游戏最核心的地方就在这里了,最难也是最有价值的地方,不过大家也不用害怕,难是难在很难去想到,但是非常容易理解,废话不多说,进入正题。

以往右移动为例子,这个理解后,其它四个方向的移动思路和这个都是一样的,所以搞懂一个就ok了

往右移动的时候就是同一行的会发生变化,对同列之间的数没有影响,所以,我们只要会移动每一行的数据,然后嵌套到一个for循环里是不是就搞定了所有4行的了,所以我们可以将整个问题缩小到对同一行四个数字的操作,问题是不是又简单了呢,我说了不难吧。

1. 先举个不需要合并的例子:

以{4,0,2,0}为例子,这就是一个普通的整形数组了,右移的结果就是达成{0,0,4,2}的效果

这里喜欢动脑筋的同学可以自己写这个方法,就是一个for循环里进行判断,自己想这种问题会非常有意思,这也是我觉得编程非常有意思的重要原因之一,我喜欢弄脑筋并想出办法的感觉,而不是靠记忆力硬生生的记住一个办法。

如果,你没想出来,希望我的办法会有所帮助

有过编程经验的同学看到这种问题基本都知道先敲个for循环是第一步,就如同冒泡排序差不多,这也算是一个排序问题,不过这可不是大小排序。

因为要往右移动,所以先判断右边的数字开始

第4个数字已经无法往右移动,所以进入下一步

第三个数字和第四个数字比较,如果第四个位0,则交换两个数字的位置,然后第三个数字到了第四个位置无法右移,下一步

第二个数字和第三个数字比较,如果第三个数子为0,交换位置,继续和第四个比,若第4个位0,交换位置,现在又无法移动了,下一步

第一个数字和第二个比较,后面省略,大家应该明白了吧。

我的语言表达能力比较差,可能说的不是特别清楚,这里再附上一小段打码,便于大家理解


int a[4] = {0,4,0,2};

int i, k, temp;

for ( i = 2; i >=0; i++)

{  

        k = j;

       while (k+1 <= 3   &&    a[k+1] == 0)                 

       {

                 temp = a[k];

                 a[k] = a[k+1];

                 a[k+1] = temp;

           }

}


大家写个C程序敲一敲应该是能理解的

2. 接下来是一个需要合并的例子:

这里以{2,0,2,4}为例子,移动后的结果应该是{0,0,4,4}

这种看起来虽然要比上一种情况复杂,但是我们是不是可以把它分成两步啊,这样就会简单很多

第一步就是按照不需要合并的方法进行移动,移动后的结果是{0,2,2,4}

第二步就非常加单了,只需从最后一个开始判断,这个数和它左边的进行比较,如果相等,让它乘以2,让它左边的数字为0即可

代码例子:

for(int i=3;i >= 1; i--)

{

         if (a[i] == a[i-1])

        {

                a[i] += a[i-1];

                a[i-1] = 0;                  

        }

}

刚才我说了两步,如果只写到这里还是有问题的,细心的读者估计已经发现了

如果是2244按照这种方法移动得到的是不是0408啊并不是0048

所以每次移动完了之后再进行一次非合并的移动方法就好了啊,所以大家写代码的时候不要忘了哦

好了,到这里整个对二维数组的移动大家应该都学会了把,将到这里,游戏精髓的地方也基本就差不多了



第四步---补充总结


这里顺便说下随机出2的方法

我的方法就是每次移动后,随机生成一个0到15到的数字,也就是第几个数字,如果这个数字不为0,则继续随机

我觉得我的方法可能不是特别好,应该还有更好的办法

-(void)new2

{

int n = arc4random()%16;

do {

n = arc4random()%16;

} while ((a[n/4][n%4] != 0));

a[n/4][n%4] = 2;

//    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{

//        [self reload];

//    });

}

注释的部分是延迟把2赋值给对应的label


再说下分数的问题

我显示的分数就是显示数组里面的最大值


最后再稍微谈谈不能移动的情况判断问题

我的方法比较呆,虽然能实现但看上去就挺没技术含量的

因为每次都是数组先变化再把数值给label显示的,所以每次移动之后的数组和移动前的数组比较,如果不一样再给label更新赋值。。。是的。我就是这么写的。。

好了,基本上说的差不多了,打了这么多字好累啊,大家能坚持看完我这个萌新写文章也真是苦了大家了,写这个小游戏的整个过程是非常有意思的,不断的去发现bug并且去改善,最终大致实现游戏的基本功能,虽然说技术含量不高,但对于新人来说自信心方面会得到极大的提升,而且这个过程中我体验到了编程的快乐,对于我以后的学习启到了很好的影响,也希望大家在有了一定的编程基础之后尝试自己做一些东西,自己去主动学习的感觉远远高过于被动接受。

最后附上代码的网盘链接    点这里下载     密码是rxeh

祝我和大家都能慢慢从一个萌新蜕变成大牛!

请大家多多留言和我交流!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,530评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 86,403评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,120评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,770评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,758评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,649评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,021评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,675评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,931评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,659评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,751评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,410评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,004评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,969评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,042评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,493评论 2 343

推荐阅读更多精彩内容

  • 背景 一年多以前我在知乎上答了有关LeetCode的问题, 分享了一些自己做题目的经验。 张土汪:刷leetcod...
    土汪阅读 12,719评论 0 33
  • 先声明哈:我做的这个也是跟着被人学习的,写文章是为了复习思路,还有巩固一下。总而言之呢,就是为了多理解思路,多折腾...
    酱油_阅读 1,630评论 10 13
  • 导语 本次将会从头到尾讲一个2048游戏的制作过程,中间也会穿插自己的理解 一.项目结构 除了html和css文件...
    酱油_阅读 4,972评论 16 39
  • 在慕课网学习制作了2048小游戏,代码放在Github,效果图如下 一、 初始化棋盘格(绝对定位) 二、并随机两...
    乘风破浪55阅读 554评论 0 0
  • 此次明城墙健走慢跑团部分队员参与了天坛乐跑组织的鸡鸣山半马活动,大家在赛事中检验我们平时锻炼的成果,参加活动的小伙...
    勤行乐道阅读 459评论 0 1