周末写了个2048小游戏也是没想到自己成功做出来了,成就感满满,下面跟大家分享一下是怎么制作的。
这个函数是老师提供的,就是可以让终端不显示输入内容以及不用按回车就可以输入的函数。
下面将从主函数开始讲起。
首先这里用到了一个之前说过的随机种子,以时间作为参数,用来生成随机数,之前说过可以对生成的随机数做一些处理,就可以将随机值固定在一个范围内,今天做的2048用到的是4*4的棋盘,所以我们需要生成的随机位置是0-3,2048最开始会生成两个随机数,在后面每次棋盘有变化后又会生成一个数,这个数一般是2或4,但是2出现的概率比4高,所以当生成的随机数是0-2时返回2,是3时才返回4。
starGame函数为游戏的开始界面,打印后延时3秒,这里我是让豆包给我生成了一个界面,大家想要什么样的可以告诉自己的豆包。
下面是循环过程,直到用户选择退出才结束。首先打印菜单供用户选择。
选项2效果
选项3效果
下面进入最主要的部分,游戏实现部分。
这里简单介绍这个函数的内容,首先先清屏,然后定义了两个数组,第一个数组用于存放当前棋盘上的内容,第二个数组等后面用到再讲解。先生成两个随机位置(在数组中包括i,j)以及两个随机数,调用复制的函数将a数组的值复制到p数组,然后调用打印数组的函数。
这里当数组中的数为0时就打印" ",将位置空出来。其他就照常打印。
然后开始判断用户输入时"WSAD"还是"上下左右",(提示:上下左右计算机读到的是"\033[A","\033[B","\033[C","\033[D")所以需要先读取是不是'\033'(也就是esc,ascii码值为27),然后再吞掉一个字符,再来判断第三个字符。通过不同的输入调用向不同方向合并和移动的函数。在移动完后再打印一次移动过后的棋盘,此时来判断数组a和数组p有没有区别,因为只有在元素有变化的时候才生成新数据。如果没变化也生成新数据的话,再后面数组被填满但你按了一个没有合成数据的方向,就会卡死在后面我while循环,因为一直找不到一个空位置来放这个数据,所以要在有变化时才生成新数据。生成完新数据后来判断游戏赢了没(出现2048就算赢)。
如果成功了就返回成功,如果没成功就来判断一下是不是失败了。
失败的条件是棋盘中没有空位置且相邻两元素没有相等的数据,所以这里先判断棋盘中有没有0,有0就代表还有空位,就直接返回1,相邻元素相等用的是先判断这个元素的右侧元素和它是否相等,在判断他下方的元素是否相等,一行的最后一个数据不用判断和右边是否相等,一列的最后一个数据不用判断是不是和下面的数据相等,所以if里面有两个条件。在这里我写的是数组指针形式,大家可以改为数组形式就是p[i][j]。如果没失败就继续读取输入,如果失败了就打印失败界面,等待用户退出。
下面讲解合并函数和移动函数。
合并函数(因为向左和向右的函数只是起始位置不同,所以这里只展示向左和向上)
合并就是先找到第一个不为0的数,然后再找下一个不为0的数,判断两者是否相等,如果相等就将第一个数变为他的2倍,第二个数变为0,如果不相等就将第二个数当做第一个数,再继续找下一个不为0的数,继续判断是否相等。
思想与向左相同,但是移动的是行。
移动函数(这里只展示向左和向上)
我们用now来记录要放数据的位置,如果第一个位置有值的话now就++,然后将数据移动到now的位置,原位置清0,now其实就相当于一个指针,指向现在能放数据的位置。
向上与向左不同的地方就是向左动列,向上动行(如果不理解可以将的写的指针形式转化为数组形式)。
游戏展示(初始界面)
可优化部分
上面的代码只是可以做到完成整游戏,但是这个代码其实还有很多可以继续优化的地方,在这里我举两个例子
1.给数字增加颜色
VT100是一个古老的终端定义,后面出现的终端几乎都兼容这种终端。VT100控制码是用来在终端扩展显示的代码。以下的宏定义即可完成对颜色的控制。
通过判断数字来选择不同的颜色,记得在打印完数字以后一定要将颜色恢复。
2.生成随机数
原来我使用的是生成一个随机位置判断它是不是0,如果是0,就给这个位置生成一个随机数,但是这么写在前期空格很多的情况下很容易实现,但是在后期空格很少的时候就会比之前需要更多的时间。所以这里给出一个优化的方法。
定义一个16行2列的数组来记录为0的位置,然后我们在这个位置中随机选择一个位置(rand( )%t就是生成一个0-t的数,然后通过这个数组中存的位置,再给随机数)这样在后期空位非常少的情况下非常好用。
这个小游戏我就说这么多,大家有什么其他的意见可以告诉我噢!!!