前言
这是第一个proj,我记得在我第一次学习这门课时感觉无从下手,随着不断的学习,大概是一年之后再看这个proj似乎也没有当时的那种恐惧,大概花了四个小时全部做完,下面我仅分享一下我的思路,本文不涉及重要的代码。
2048的玩法
在第一次玩的时候,我就像AI一样在那随便乱窜,完全不知道怎么玩。后来才知道原来相同的数字可以进行叠加,2 + 2 = 4, 4 + 4 = 8….然后是1024+1024 = 2048,也就是说,只要你格子的最大数字是2048,那么你就获胜了!
同理,游戏有赢也有输,不能总是赢赢赢
如果说当前方格内没有空格子时,你基本就要完蛋了,这个时候还需要检查是否可以有上下左右可以合成的相邻格子,如果没有,那么真就Game Over了!
思考:我们已经得到了结束游戏的条件,即当前格子最大值为
2048或者当前无法合成新的数字。
我们先跟着文档指导来完成一下一些前置函数。
首先是检查当前是否 有空格子的函数
emptySpaceExists(Board b)
这个函数不难,不过对于刚上手的人来说,我觉得可能不知道怎么获取一个格子才是比较难的地方。不过跟着官方文档来,也还是很简单的。
For this method, you’ll want to use the
tile(int col, int row)andsize()methods of theBoardclass.
官方文档提示我们可以使用tile这个函数,这个函数长这样
|
|
其实为了更加工程化,官方对这个2048进行了包装,要让我来实现,直接返回一个数组的arr[col][row]就行了,似乎这就是我与大佬之间的差距。
所以,当我们调用这个方法时,本质就是去获取方格子上的一个格子。于是乎,这样我们就可以进行这个函数的编写了。显然,如果这个函数的返回值是null,说明当前是一个emptySpace,否则就是存在一个格子。
maxTileExists(Board b)
这个函数返回的是当前方格子的最大值,找最大值这个不难,相信大家都会。我们获取一个格子后,就可以调用这个格子的value方法来获取其内存储的数字,这样就可以进行比较。
atLeastOneMoveExists(Board b)
这个函数的意思要我们判断当前格子至少能进行一次移动,判断的标准就是
- 当前格子有空格子
- 格子满了,但是相邻的两个格子数字相同,也就是可以合并,这样也算一次移动
这样也可以进行判断,不过,进行相邻格子进行搜索的时候有个技巧,如果你是第一次实现这个功能,很容易把代码写成下面这个样子
|
|
这样写相当不好维护,其实你可能没有注意到我们可以用循环来替代这个上下左右搜索
|
|
更节省空间的,我们可以只使用一个数组,你可以自己试一下。
tilt(Side side)
在正确编写完上面的代码并测试完后,你可以运行Main试一下,如果一切正常,格子里面就会出现一些数字。
这里,我们先不考虑怎么合并,先考虑怎么把格子进行移动。在Board类中,有一个方法是move函数,它的定义如下
|
|
也就是说,指定一个坐标和格子,调用move方法就可以移动这个格子,而且,这个move方法还可以合并两个格子,即如果移动到的那个坐标没有数字,那么就移动到上面;否则,就合并两个格子。我们先来看看怎么移动一个格子吧,在此之前,我们先要熟悉这个网格的坐标。
左下角是原始坐标,这样,我们就可以直接去移动一个点
|
|
这样,当我们键入上下左右时,就应该可以把这个点移动到右上角。
你键入“上下左右”时,可能会发现什么都不起作用,这可能是因为你的操作系统或者
IDEA的语言不是英文导致的我们可以
违反适应规则,修改一些其它的代码。打开
GUISource.java,把case部分的代码进行修改
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20switch (command) { case "↑" : case "向上箭头" : command = "Up"; break; case "→" : case "向右箭头" : command = "Right"; break; case "↓" : case "向下箭头" : command = "Down"; break; case "←" : case "向左箭头" : command = "Left"; break; default : break; }这样,你应该可以移动了,不用担心,自动评分只会使用
Model这个程序。
官方文档提示我们可以先完成一个向上合并的操作,然后通过测试。其实通过测试你就可以明白2048的每个格子之间是怎么进行合并的。我们需要注意一些特例,即每个格子在这一列上最多会被合并一次。
来举个例子,请考虑下面这个格子
|
|
如果向上合并的话,答案应该是多少呢?是
|
|
还是
|
|
应该是前者,对吧?你需要记住我上文说的:每个格子至多会有一次合并,这样来看,上面两个2已经被合成4了,所以那个格子不应该再和下面那个4进行合并了。
补全其它方向
实际上,如果我们要给每个方向都写一份代码,那么这是不太好维护的。官方文档想了一个十分巧妙的方法,就是坐标变换,只要我们有向上合并的代码,那么经过行列转置,我们就可以拥有其它方向。
例如,这是一个随机的格子
|
|
显然,如果我们按下<-,这样就可以合并第二行的格子。经过旋转后,格子可以变为
|
|
这样就转换为向上合并的情况,合并完后,我们就再反转回来即可。
官方给我提供了十分方便的坐标轴旋转函数,对应的就是”上北下南,左西右东“。我们可以通过
|
|
来设置坐标系,记得最后还原!
通过测试
写完所有代码后,就可以运行TestModel测试,如果你全部通过了,可以提交到自动评分机上!
我的代码通过了所有的测试
一次失败的挑战
你能通关吗?欢迎贴图证明哦!