学习C语言/C++已经接近一个月了,在老师的带领下,我们已经学习了c语言数据的基本类型、变量的输入输出、进制转换、运算符和分支结构、循环结构、数组、指针、函数和字符串结构体等等,在老师带着我们作出了一个贪吃蛇的过程中让我深刻的体会到了字符界面做游戏的快感,原来c语言如此强大,利用所学的基础居然可以实现这样精巧的功能。然后老师又介绍了一个2048的游戏,说这个游戏的实现比较有挑战,本来就对c语言憧憬的我对2048这个游戏充满了好奇,然后自己下载了一个2048的游戏玩了一下就开始实现自己的代码了,挑战了一下自己。
下面我会把实现这个游戏的思路以及相应的解决办法进行了总结,并提供自己的代码和详细注释。
1.设计目标
(1)界面显示
////////////////
/ 2 2 2 8/
/ /
/ 2 /
/ /
/////////////////
(2)游戏操作
r ---> 开始游戏
q ---> 结束游戏
2 ----> 下移
4 ----> 左移
6 ----> 右移
8 ----> 上移
任意键 -> 重新开始
(3)游戏规则
按r键开始游戏,然后进行游戏,可以输入任意方向键进行操作;进行相应的平移操作,当两个相同的数字"相撞"则将它们两个数字合成一个是它们和的数字,当两个数字不同"相撞"则不进行合成;当所有格子满了并且无法进行移动的时则判断为输,当数字有一个出现2048的字样则判断为赢。
2.创新点
(1)可以改变游戏的胜利值(2048可以修改为1024等等)
(2)任何时刻都可以按住r重新开始游戏
(3)代码用一维数组代替二维数组,减少了遍历数组的时间复杂度
(4)操作方向的时候不需要输入回车,使用户得到更舒适的体验
(5)界面的刷新流畅
(6)屏蔽其他按键
3.对未来的展望
(1)修改成为图形界面并增加一些动画特效
(2)优化代码
4.重难点剖析
(1)如何利用2 4 6 8进行方向控制?
答:可以利用switch...case语句,当输入字符为2时调用下移函数,当输入字符为4时则调用左移函数等
(2)如何不输入回车就可以输入字符?
答:可以通过getch(),输入字符并且不用输入回车即可达到效果
(3)为什么地图数组用一维数组代替二维数组
答:由于每一帧画面都会要遍历该数组,使用一维数组可以方便的用一个循环就可以遍历数组
(4)怎么判断输
答:当数组中全部都被占用,并且每个数字的上下左右都没有与它相同的数字即为输
(5)怎么判断赢
答:遍历数组出现2048即为赢
(6)移动时内部数据怎么变化
答:由于上下左右比较类似,我就以左移做详细介绍,其他的可以类推。
分析左移代码
void MoveLeft()
{
int i = 0;
int tempmap[GAMERANGE ] = {0};
memcpy(tempmap,g_map,GAMERANGE *sizeof(int)); //拷贝移动的之前的数组
for (i; i < GAMERANGE ; ++i)
{
if (g_map[i])
{
MoveMostLeft(i); //移动单个元素0~15
}
}
HandleState(tempmap,g_map,GAMERANGE );//处理游戏对应的状态,判断输赢并做处理
}
HandleState函数我就不多解释了, 主要是判断输赢并做处理的函数
下面主要看一下MoveMostLeft函数, 这个函数是将数组中的pos位置的元素移动
/*游戏地图单个坐标左移*/
void MoveMostLeft(int pos)
{
int i = pos - 1; //i为pos左边的元素
while (i >= pos - pos % 4 && !g_map[i]) //i不出界 && i是空格
{
--i;
}
//此时的i指向的是刚刚出左边的界或者是pos左边的第一个数字
if (i < 0) //说明pos左边全为0 //i<0 说明左边全部是空格
{
g_map[i+1] = g_map[pos]; //将pos位置的数字赋值给最左边的数字
if (i+1 != pos) //排除i+1和pos位置一样,使得i+1的数值赋值为0
{
g_map[pos] = 0;
}
}
else //说明pos左边有非0数字, 左边坐标为i i指向的是左边第一个数字
{
if (g_map[i] == g_map[pos]) //判断pos位置的数字和左边第一个数字是不是相等的,如果是相等的话,i的位置的数字乘2,pos位置的值赋值为空格
{
g_map [i] = g_map[i] << 1;//如果i和pos数字相同,则将位置i的数值乘以2 <<左移1则是乘以2
g_map[pos] = 0;
}
else //如果pos位置的值不等于左边第一个数字的值则吧左边第一个数字的右边的一个空格修改为pos位置的值,然后修改pos位置的值为空格
{
g_map[i+1] = g_map[pos];
if (i+1 != pos)
{
g_map[pos] = 0;
}
}
}
}
上面主要是左移部分的代码已经详细解释, 右移,上移,下移都类似
5.总结
在刚刚写代码的时候感觉方向不明确,不知道如何下手,便写了一个左移函数后来发现其他方向类似,其他方向的代码基本上都是复制的左移代码,然后400多行的代码就出来了, 写出来之后感觉自己很有成就感,通过自己所学的东西完成了一个小小的项目,也算是对前面所学知识的一个综合性的运用。自己对项目的编写有了一定的体会, 先将整个项目分成一些小模块,然后在分开写代码,最后将代码整合出来一个项目,整个游戏就是这样出来了,当然一个项目的完成还会碰到一些问题,还了解了一些常见问题的解决办法。
附加: 编译方法
gcc 2048.c -l curses //使用了curses库