2048小游戏总结

利用html,css,jquery编写一个2048小游戏。

1. 首先我们来了解一下2048的游戏规则:
2048游戏的规则:一共有16个方格,可以4个方向滑动,相同的数字相遇就会合并,一个数字翻倍,另一个数字清零,清零的数字会腾出一个空格。当没有空白格子出现时,游戏结束。

2. 基本说明:
我把16个数字放在一个二维数组中,索引为0–15。0表示该方格中没有数字。

var square = [[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0]];
squareCellSpace;  //每一个小方格之间的间距;
squareWidth;  //每一个小方格的宽度。

3. 页面布局
从游戏页面布局开始说起:首先我们平常玩的2048都可以看到是由16个方格组成。所以,在html和css布局时,我使用
了一个大的div容器来包含了所有的方格。其中包括16个不会移动的背景方格和16个会随用户操作进行移动的数字方格,总共是32个小方格。
css方面:
父div进行相对定位,32个小方格进行绝对定位。
在js代码中:
首先我对背景方格进行定位。通过jquery来初始化每个方格的top值和left值。即:循环遍历16个方格,获取到每一个div,通过给每一个div设置不同的top值和left值,来对每一个div进行定位。

getPosTop(i,j){
    return squareCellSpace + i * (squareWidth + squareCellSpace);
}
getPosLeft(i,j){
    return squareCellSpace + j * (squareWidth + squareCellSpace);
}             

4. 数字显示
数字显示主要就是不同的数字会有不同的颜色和背景颜色。
不同的数字不同的颜色这一点的实现很简单,我主要就是进行了一个判断:

var getNumberColor = function(number){
    if(number <= 4){
        return "#666";
    }
    else{
        return "#fff";
    }
};

数字小于4是一种颜色,大于4统一为另一种颜色。

不同的数字不同的背景颜色这一点的实现,主要是:

var getNumberBackgroundColor = function(number){
    var color = ["","#eff0c8","#efe4da","#f2bc79",
        "#f59563","#f67c5f","#f65e3b",
        "#edcf72","#98cd01","#33b5e5",
        "#0f98cd","#ab56cd","#983451"];
    var x = 0;
    for(x=0; number-1>0; ++x,number/=2);
    return color[x];
};

将所有的颜色保存在一个数组中,添加判断语句for(x=0; number-1>0; ++x,number/=2);来得到不同数字对应的不同背景颜色。比如:当数字为2时,x的值为1,所以我在color数组的第一项添加了”“,同理,当数字为4时,x的值为2,得到数组的第三项,以此类推,对于不同的数字就会有不同的背景颜色。

5. 随机的位置产生两个随机的数字

这个问题刚开始时,我只是定义了两个变量randomX,randomY来确定数字的位置。

var randomX = parseInt(Math.floor(Math.random()*4));
var randomY = parseInt(Math.floor(Math.random()*4));
var randomNumber = Math.random() < 0.5 ? 2 : 4;
square[randomX][randomY] = randomNumber;
showNumber(randomX,randomY,randomNumber);

但是代码这样写,会产生错误。因为在页面初始化时,我是两次执行putOneNewNumber()函数来产生两个随机数的。会存在一个严重的问题,就是两次产生的随机数位于同一个位置,所以要改变这种情况。
解决方法:
我在每一次执行putOneNewNumber函数时,循环遍历16个方格,找到为空的方格,显示数字。

在putOneNewNumber()函数中,
我定义了一个随机次数变量randomTimes,当这个变量小于50时,产生一个随机位置,如果该位置为空,则显示数字。
当随机次数增大时,我需要循环遍历16个方格,找到位置为空的方格,显示随机的数字。putOneNewNumber在每一个方格移动完毕之后都会执行一次。还有一点需要注意,每一次在putOneNewNumber执行时,都要进行一次判断,判断当前是否还有空方格,如果存在空方格,则产生一个随机数,如果不存在空方格,则游戏结束。

var noSpace = function(){
    for(var i = 0;i < 4;i++){
        for(var j = 0;j < 4;j++){
            if(square[i][j] == 0){
                return false;
            }
        }
    }
    return true;
};

至此,整个游戏的页面布局和初始化时产生两个随机数就结束了。

接下来,最重要的就是实现数字方格的移动,在这里,我是采用了键盘的监听事件来实现。利用键盘的上下左右四个键来控制数字方格的移动。利用switch-case语句来分四种情况。对于每一种情况,首先需要判断数字方格是否可以进行该方向上的移动,如果可以移动,则进行移动,移动结束后,产生一个随机数,并进行判断当前游戏是否结束。

我以向上移动为例,进行说明:(在这里,我定义的i变量表示行,j变量表示列)

6. 设置键盘监听事件

$(document).keydown(function(event){
    event.preventDefault();  //阻止事件的默认行为
    switch(event.keyCode){
        .....
        case 38://用户按下上键
            if(canMoveUp(square)){  //判断是否可以向上移动
                moveUp(); //向上移动
                setTimeout("putOneNewNumber",300); //产生一个随机数
                setTimeout("isGameOver()",300);  //判断游戏是否结束
            }
        break;
         .....
     }
})

7. 向上移动

//判断当前情况能否向上移动
var canMoveUp = function(square){
    for(var j = 0;j < 4;j++){
        for(var i = 1;i < 4;i++){
            if(square[i][j] != 0 && (square[i - 1][j] == 0) || square[i][j] == square[i - 1][j]){
                return true;
            }
        }

    }
    return false;
}
//向上移动
var moveUp = function(){
    for(var j = 0;j < 4;j++){
        for(var i = 1;i < 4;i++){
            if(square[i][j] != 0){
                for(var k = 0;k < i;k++){
                    //情况一:当前位置的上列为空
                    if(square[k][j] == 0 ){
                        //move
                        moveAnimate(i,j,k,j);
                        square[k][j] = square[i][j];
                        square[i][j] = 0;
                        continue;
                    }
                    //情况二:当前位置的数字和上一列数字相等
                    else if(square[k][j] == square[i][j]){
                        //move
                        moveAnimate(i,j,k,j);
                        //add
                        square[k][j] += square[i][j];
                        square[i][j] = 0;
                        //add Score
                        score += square[k][j];
                        updateScore(score);

                        continue;
                    }
                }
            }
        }
    }
    setTimeout("update()",200);
};

刚开始我向上移动的代码是这样写的,对于情况一和情况二的判断就是上面的代码,但运行时出现了bug。
bug就是:两个相等的数中间存在一个数,比如第二行存在,32,4,16,4,这四个数,当我向右移动时,按照预想,结果是不会发生任何变化,但是真实的结果却是,4和4合并,出现了32,16,8这种情况,所以我需要对情况一和情况二进行修改。

于是我添加了一个函数noSquareVertical,用于判断两个相等的数之间是否有空格。

//判断某一列中的某点到另一点之间是否有空格,如果有空格,则返回true,如果没有空格,则返回false。
var noSquareVertical = function(col,row1,row2,square){
    for(var row = row2 + 1;row < row1;row++){
        if(square[row][row1] != 0){
            return false;
        }
    }
    return true;
};

所以向上移动的函数就变成了:

//向上移动
var moveUp = function(){
    for(var j = 0;j < 4;j++){
        for(var i = 1;i < 4;i++){
            if(square[i][j] != 0){
                for(var k = 0;k < i;k++){
                    //情况一:当前位置的上列为空
                    if(square[k][j] == 0 && noSquareVertical(j,i,k,square)){
                        //move
                        moveAnimate(i,j,k,j);
                        square[k][j] = square[i][j];
                        square[i][j] = 0;
                        continue;
                    }
                    //情况二:两个相等的数可以进行合并,但两数必须相邻,或两数之间有空格。
                /*noSquareVertical函数的作用就是如果两个不相邻的数相等且中间必须有空格的时候才能进行合并*/
                    else if(square[k][j] == square[i][j] && noSquareVertical(j,i,k,square)){
                        //move
                        moveAnimate(i,j,k,j);
                        //add
                        square[k][j] += square[i][j];
                        square[i][j] = 0;
                        //add Score
                        score += square[k][j];
                        updateScore(score);

                        continue;
                    }
                }
            }
        }
    }
    setTimeout("update()",200);
};

这样数字方格就可以正常的向上移动了。

向上,向左,向右,向下每个函数执行完毕之后,都要再执行update函数来对数据进行更新。

8. 关于score的情况

关于score的情况:我每次进行移动时,如果遇到两个相等的数进行合并,我就将数字合并之后的结果赋给score,然后执行updateScore函数,对分数进行更新。

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