2048小游戏

写在开头:

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

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


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

2048小游戏_第1张图片


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



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

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

2048小游戏_第2张图片

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

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

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

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

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

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

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

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

2048小游戏_第3张图片

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

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

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

你可能感兴趣的:(2048小游戏)