JS与HTML、CSS实现2048小游戏(四)

前篇链接

JS与HTML、CSS实现2048小游戏(一)
JS与HTML、CSS实现2048小游戏(二)
JS与HTML、CSS实现2048小游戏(三)

逻辑分析

在编写游戏的主题逻辑之前,咱们需要先分析清楚游戏的一个主要流程。在这个网页版的2048中没有办法通过手机版那样滑动来操作,我就设定使用上下左右四个方向键(也可以改成其他键位)来控制这个游戏的运行。

在进行操纵的过程中,需要电脑做到以下几点判断(以下皆以向左移动为例):

  1. 判断每一行有数的格子的左侧格子是否有空格子,即这一行的数字能否左移。
  2. 如果左侧有一个盒子不是空格子,则判断这个格子和将要移动的格子的数值是否相同,相同则让两个格子合并数值相加,成为一个新的格子。

游戏内格子移动的逻辑大致就是这样,下面咱们便来开始编写今天的代码。因为是游戏与用户交互的逻辑便在游戏交互逻辑文件game.js中进行编写。

键盘响应

首先咱们要让游戏能够响应键盘的操作,所以先用一个$(document)来接收整个界面的操作信息。接着使用一个keydown()事件来对接收到的信息进行响应。这个事件如名字一般是对键盘按下这个事件进行响应的。然后在事件之中使用一个function来处理逻辑,在其中使用一个event参数来进行操作。

//键盘响应交互模块
$(document).keydown(function (event) {     //event是keydown事件自带的
}

键位呼应

接着在function中,使用switch方法来检测你所按下的是键盘上的哪一个键位。在这里使用event.keycode来表示检测得到的键盘键位所代表的值,大家可以搜索一下keycode查看每一个键位所对应的数值。在这里,我使用的是方向键左上右下,他对应的值是37到40。再在每一个case末尾加上break用以减少响应时间。

//键盘响应交互模块
$(document).keydown(function (event) {     //event是keydown事件自带的
            switch (event.keyCode) {
                case 37://left
                    break;
                case 38://up
                    break;
		        case 39://right
		            break;
		        case 40://down
		            break;
		        default:
	            break;
	    }
});

左移响应

事件捕获到之后咱们便要来编写具体的游戏逻辑了。首先如之前分析的那样咱们需要判断按下左方向键时,界面内的方块能不能向左移动。在这里呢,我采用了一个moveLeft()方法来进行操作。这个方法我将他写在了if的条件栏中,一方面要使用他来完成向左移动的逻辑,一方面通过他返回一个bool值来判断能否向左移动。倘若返回的是true则先随机生成一个数在使用isgameover()方法来判断游戏是否结束,这个方法咱们之后在进行编写。

switch (event.keyCode) {
		case 37://left
                //moveLeft()方法完成向左移动的运算,结果为bool型,判断是否可以向左移动
                if (moveLeft()){
                    //重新随机生成一个数字
                    generateOneNumber();
                    //判断这次移动之后游戏是否结束
                    isgameover();
                }
                break;

这样,对于响应键盘做方向键的描述就已经完成了,咱们要来设计向左移动的方法了。

向左移动——moveleft()

同样,moveLeft()方法也是游戏的逻辑依旧写在game.js中。如前文提到的,在这个方法中咱们需要实现两个功能。第一个是判断是否有格子能完成移动的逻辑,同时返回一个bool值。这里咱们就可以很简单的使用一个if来进行判断,再在IF中封装一个canMoveLeft(board)方法来进行判断。正如名称一样,在我的设想中这个方法判断上返回的就是能移动为true不能为false,但是能移动的方法涉及到的内容比较多,在if中进行编写的话不太容易查看,我便想在canMoveLeft(board)方法前加上一个!(非)来更改传回的bool值。

function moveLeft() {
    if (!canMoveLeft(board)){
        return false;
    }
    return true;
}

然后,如果能够经过if的判断那就说明可以向左移动,咱们便要在IF下面来编写向左移动的逻辑。首先咱们需要遍历十六个小格子,来看看拿个小格子需要左移。又因为第一列无法左移,咱们在遍历过程中就可以把第一列的小格子都排除,因此咱们的第二层循环就可以从1开始计数。而空的小格子是不需要移动的,所以咱们再循环中先要写一个if判断格子是否为空,即格子对应的board值是否为0。

for (var i = 0;i < 4; i++){
        for (var j = 1 ;j < 4; j++){
            //当前数字格有值
            if (board[i][j] != 0){
                //向左移动的逻辑
            }
        }
}

对于不为零的格子,咱们便需要来增加向左移动的逻辑。我在这里又做了一个新的for循环,来遍历当前取到的数字格左侧的格子。截取到这之前的格子之后,咱们分析一下它完成逻辑的情况。一种是当前值数字格左侧取到的数字格值为0且中间的其他数字格也为0,另一种是当前数字格左侧取到的数字格值与当前数字格相等且中间的其他数字格也为0。这个也就是文章开始时分析出来的游戏逻辑。

在这里我使用了if和else if 来进行判断,显示判断所取到数字格是否为0同时通过noBlokHorizontalCol(row, col1, col2, board)这个方法来判断中间的数字格是否为空,同样这个方法也是返回一个bool值。else if中则是判断所取到的数字格board[i][k]与当前board[i][j]的值是否相等并用noBlokHorizontalCol来判断中间的数字格是否为空。

for (var k = 0 ; k < j; k++){
	if (board[i][k] == 0 && noBlokHorizontalCol(i,k,j,board )){
		continue;
    }
	else if (board[i][k] == board[i][j]  && noBlokHorizontalCol(i,k,j,board) && !hasConflicted[i][k]){
		continue;
	}
}

条件提供好了就要开始编写移动的逻辑。我再使用了一个showMoveAnimation(i,j,i,k)的方法,同样也是通过动画实现格子的移动。接着咱们还要让取到的那个格子的值变成之前指定的那个各自的值,同时让指定格子的值变成0。也就是,让数从之前制定的位置变换到现在取到可以移动的位置。

if (board[i][k] == 0 && noBlokHorizontalCol(i,k,j,board )){
	//才能向左移动
	showMoveAnimation(i,j,i,k);
	//add
	board[i][k] = board[i][j];
	board[i][j] = 0;
	continue;
}

而第二种同样也是先引用showMoveAnimation方法,然后再让取到的那个格子值和之前的格子相加,之前的则直接归0,回归空值状态。

else if (board[i][k] == board[i][j]  && noBlokHorizontalCol(i,k,j,board) && !hasConflicted[i][k]){
	//才能向左移动
	showMoveAnimation(i,j,i,k);
	 //add
	 board[i][k] += board[i][j];
	 board[i][j] = 0;
	 continue;
}

数字格移动动画——showMoveAnimation()

接着,咱们要在animation.js中编写showMoveAnimation()方法了。在形参上,我使用了fromx,fromy,tox,toy四个比较形象的参数来表示,就是源格子的xy坐标的要移动到格子的xy坐标。在方法中咱们先要取到源格子的元素,再使用animate方法来设定移动的动画,其中传入要移动到的位置就是用getPostTop和getPostLeft来获取,再加上一个200毫秒的延迟就可以完成格子移动的动画了。

//数字格移动动画
function showMoveAnimation(fromx,fromy,tox,toy) {
    //获取当前数字格元素
    var numberCell = $("#number-cell-"+fromx+"-"+fromy);
    numberCell.animate({
        top: getPosTop(tox,toy),
        left: getPosLeft(tox,toy)
    }, 200);
}

是否能够左移的判定——canMoveLeft()

这样向左移动的基础逻辑就差不多完成了,咱们再返回来看之前还未编写canMoveLeft方法。这个方法同样是支撑游戏逻辑的,所以我放在support.js中进行编写。

在这个函数中我直接传入了board这个数组的全体,通过遍历来获取到每一个不为第一列的格子的元素,再通过if对其中不为空的格子的值进行判断。咱们判断的方法是当前的这个非空数字格左边第一个值为0或这个数字格与左边第一个数字格的值相同,这样这个数字格便可以向左移。如果达成了这两个中的任意一个条件,就说明再这个游戏界面中有可以向左移的格子,便可以直接返回一个true值进行以下的步骤了。而如果都遍历之后还没有找到可以左移的值才可以返回false,说明没有一个格子可以实现向左移动的逻辑。

//能否左移函数
function canMoveLeft(board){
    for (var i = 0; i < 4; i++){
        for (var j = 1; j < 4 ; j++){
            if (board[i][j] != 0){
                if (board [i][j - 1] == 0 || board[i][j - 1] == board[i][j] ){
                    return true;
                }
            }
        }
    }
    return false;
}

水平方向数字格能否移动判定——noBlokHorizontalCol()

这个时候如果你去运行这个网页,你会发现还是没办法达到想要的效果。因为再前面的逻辑中还有一个noBlokHorizontalCol方法咱们还没有进行编写。因为JS语言是按照函数顺序往下运行的,如果再其中又一处变量未定义或者一个函数没有编写完成,那这个函数的逻辑便不会运行完整而是卡在中间没有变化。

同样,这个函数也是支持游戏逻辑运行的函数,咱们也在support.js中进行编写。在这个函数中我传入了四个变量,row,col1,col2,board,意义就如英文名称一样,两个col分别表示要移动的格子的横坐标和要移动到的格子的横坐标。在方法中,我使用了一个for循环遍历两个格子中间的格子,并通过if判断中间每一个格子是否为空,不为空就立马返回false值,全部遍历后不为空就返回true。

//水平方向能否移动函数
function noBlokHorizontalCol(row, col1, col2, board) {
    for (var i = col1 + 1; i < col2; i++){
        if (board[row][i] != 0){
            return false;
        }
    }
    return true
}

这个方法写完之后,咱们还要再初始化一下数字格更新一下布局,我在moveLeft()函数的返回值之前使用了一个setTimeout(“updateBoardView();”,200);方法来增加了动画的延迟效果,让大家更清晰的看到移动的动画。

其余方向

这个时候再去调试这个页面便会发现向左移动的方法已经可以实现了,然后其他三个方向的内容大致相似我就不再描述,大家可以自己编写试试。

后续文章

JS与HTML、CSS实现2048小游戏(五)

  • 11
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值