学习JavaScript完成2048小游戏

学习JavaScript做了一个2048游戏(此内容涉及到了JQuery)

游戏截图

           学习JavaScript完成2048小游戏_第1张图片

主要实现的步骤

1.首先随机生成两个2或4的格子

2.方块的上下左右的移动,合并后颜色和内容数字的改变

3.判断是否可以移动

4.随机生成数字时判断16个格子中是否还有空位,有则随机生成以为2或4的数字

5.判断输,16个格子占满 格子无法上下左右移动

6.分数  任意两个格子合并后,分数加上合并格子的数值

7.重要的是判断格子移动的位置,格子是否应该合并

步骤讲解完成,具体代码的实现和细节的讲解继续向下 。

 
HTML代码



 

    
    
    
    2048游戏
    
    
    
    


    

2048

New Game

分数: 0

Game Over

CSS代码

*{
    margin: 0;
    padding: 0;
}
header{
    display: block;
    margin:0 auto;
    width: 500px;
    text-align: center;
}
header h1{
    font-size: 60px;
    font-weight: bold;
    margin-top:20px;
    margin-bottom:20px;
}
header #newGameButton{
    width:100px;
    padding:10px;
    background:#8f7a66;
    color:white;
    border-radius: 10px;
    text-decoration: none;
}
header #newGameButton:hover{
    background:#9f8b77;
}
header p{
    font-size: 25px;
    margin:20px auto;
}
#grid-container{
    width:460px;
    height: 460px;
    padding:20px;
    margin:40px auto;
    background: #bbada0;
    border-radius: 10px;
    position: relative;
}
.grid-cell{
    width:100px;
    height:100px;
    border-radius: 6px;
    background:#ccc0b3;
    position: absolute;
}
.number-cell{
    width:100px;
    height:100px;
    border-radius: 6px;
    line-height:100px;
    font-size:50px;
    text-align:center;
    position: absolute;
    font-weight: blod;
}
 
#gameOver{
    background-color:black;
    color: white;
    font-size:60px;
    position: absolute;
    top:30%;
    left:25%;
    width:250px;
    text-align:center;
    z-index: 999;
}

grid-cell是底部的无数字的白块,number-cell是后面移动的格子,gameover是游戏结束的提示,number-cell在后面初始化等操作中覆盖掉到grid-cell,gameover在游戏结束后显示。

 

以上完成了前端页面,下面是Javascript代码

var board = new Array();  //所有的格子
var added = new Array();  //所有格子之间的合并关系
var score = 0;   //分数
 
//打开页面完成的动作
$(document).ready(function() {
    newGame();
})
 
//初始化游戏
function newGame() {
    init();
    createOneNumber();
    createOneNumber();
}
 
//初始化操作
function init(){
    score = 0;
    document.getElementById("score").innerHTML = score;
    $("#gameOver").css("display","none");
    for(var i=0;i<4;i++){
        for(var j=0;j<4;j++){
            var grildCell = $("#grid-cell-"+i+"-"+j);
            grildCell.css("top",getTop(i,j));
            grildCell.css("left",getLeft(i,j));
        }
    }
    //初始化格子数组
    for(var i =0;i<4;i++){
        board[i] = new Array();
        for(var j =0;j<4;j++){
            board[i][j] = 0;
        }
    }
    //初始化判定合并的数组
    for(var i =0;i<4;i++){
        added[i] = new Array();
        for(var j =0;j<4;j++){
            added[i][j] = 0;
        }
    }
    updateBoardView();
}
 
//生成number-cell覆盖在gril-cell上 更新数组的前端样式
function updateBoardView(){
    $(".number-cell").remove();
    for(var i = 0;i<4;i++){
        for(var j=0;j<4;j++){
            $("#grid-container").append('
'); var theNumberCell = $("#number-cell-"+i+"-"+j); if(board[i][j] == 0){ theNumberCell.css('width','0px'); theNumberCell.css('height','0px'); theNumberCell.css('top',getTop(i,j)); theNumberCell.css('left',getLeft(i,j)); }else{ theNumberCell.css('width','100px'); theNumberCell.css('height','100px'); theNumberCell.css('top',getTop(i,j)); theNumberCell.css('left',getLeft(i,j)); theNumberCell.css('background-color',getNumberBackgroundColor(board[i][j])); theNumberCell.css('color',getNumberColor(board[i][j])); theNumberCell.text(board[i][j]); } } } } //随机产生格子 function createOneNumber() { //判断是否有空位 if(nospace(board)) return false; var randx = parseInt(Math.floor(Math.random()*4)); var randy = parseInt(Math.floor(Math.random()*4)); while(true){ if(board[randx][randy] == 0){ break; } randx = parseInt(Math.floor(Math.random()*4)); randy = parseInt(Math.floor(Math.random()*4)); } var randNumber = Math.random()<0.5 ? 2 : 4; board[randx][randy] = randNumber; showNumberWithAnimation(randx,randy,randNumber); return true; } //随机数字的样式 function showNumberWithAnimation(i,j,randNumber){ var numberCell = $("#number-cell-"+i+"-"+j); numberCell.css('background-color',getNumberBackgroundColor(randNumber)); numberCell.css("color",getNumberColor(randNumber)); numberCell.text(randNumber); numberCell.animate({ width:'100px', height:'100px', top:getTop(i,j), left:getLeft(i,j) },50); } //在随机生成数字的时候判断16宫格中是否还有空间 function nospace(board) { for ( var i = 0; i < 4; i++){ for ( var j = 0; j < 4; j++){ if (board[i][j] == 0){ return false; } } } return true; }

首先确立我们以数组的形式实现,board数组存放的是16个格子的数值,added数组存放的是格子之间能否合并的关系(这里可能会模糊,继续向下看会明白的),首先我们初始化内容,随机生成两个数值为2或4的格子,生成number-cell覆盖在gril-cell上我们具体是对number-cell进行操作。

然后根据数值的不同进行颜色的更改(这里应该不用说明)

//top值
function getTop(i,j){
    return 20+i*120;
}
//left值
function getLeft(i,j){
    return 20+j*120;
}
 
//判断数字的大小 给定背景颜色
function getNumberBackgroundColor(number) {
    switch (number) {
    case 2:
        return "#eee4da";
        break;
    case 4:
        return "#eee4da";
        break;
    case 8:
        return "#f26179";
        break;
    case 16:
        return "#f59563";
        break;
    case 32:
        return "#f67c5f";
        break;
    case 64:
        return "#f65e36";
        break;
    case 128:
        return "#edcf72";
        break;
    case 256:
        return "#edcc61";
        break;
    case 512:
        return "#9c0";
        break;
    case 1024:
        return "#3365a5";
        break;
    case 2048:
        return "#09c";
        break;
    case 4096:
        return "#a6bc";
        break;
    case 8192:
        return "#93c";
        break;
    }
    return "black";
}
//判断数字大小给定数字颜色
function getNumberColor(number) {
    if (number <= 4){
        return "#776e65";
    }
    return "white";
}

主要的是移动函数(以左移动为例)

先判断格子是否能够向左移动,如果可以,循环每一个格子,如果这个格子的值不为0,遍历格子左侧的元素,判断落脚的位置是否为空以及落脚位置的数字是否和本来的数字相等 。如果落脚的位置为空 && 中间没有障碍物,更新样式,将落脚位置格子的值设为移动格子的值,原格子值设为空。如果落脚位置的数字和本来的数字相等&& 中间没有障碍物,更新样式,将落脚位置格子的值设为移动格子值与落脚位置格子值相加后的值,原格子值设为空。

    (added数组体现出来了)如果这样写的话有个问题是如果出现类似4 4 8 0  移动后会为16 0 0 0,我的解决办法是设定一个一样的4x4数组,将每个格子初始值赋为0,相加过的格子赋值为1,合并的时候判断相应位置的数组值是否为0,若为0则合并,为1则证明已经完成了一遍相加不合并,每次判断时每个格子值赋为0。
 

//判断能否左移
function canMoveLeft(board){
    for(var i = 0;i<4;i++){
        for(var j = 0;j<4;j++){
            if(board[i][j] != 0 && j!=0){
                if(board[i][j-1] == 0 || board[i][j-1] == board[i][j]){
                    return true;
                }
            }
        }
    }
    return false;
}
//判断水平是否有障碍物
function noBlockHorizontal(row,col1,col2,board){
    for(var i = col1+1;i

键盘的上下左右键的功能

$(document).keydown(function (event) {
    switch (event.keyCode) {
        case 37: //left
            if (moveLeft()) {
                getScore();
                createOneNumber();
                setTimeout("isGameOver()",400);
            }
            break;
        case 38: //up
            if (moveUp()) {
                getScore();
                createOneNumber();
                setTimeout("isGameOver()",400);
            } break;
        case 39: //right
            if (moveRight()) {
                getScore();
                createOneNumber();
                setTimeout("isGameOver()",400);
            } break;
        case 40: //down
            if (moveDown()) {
                getScore();
                createOneNumber();
                setTimeout("isGameOver()",400);
            }
    }
})

判断游戏的结束

//在随机生成数字的时候判断16宫格中是否还有空间
function nospace(board) {
    for ( var i = 0; i < 4; i++){
        for ( var j = 0; j < 4; j++){
            if (board[i][j] == 0){
                return false;
            }
        }
    }  
    return true;
}
//没法移动
function nomove(board){
    if(canMoveLeft(board) || canMoveRight(board) || canMoveUp(board) || canMoveDown(board)){
        return false;
    }
    return true;
}
 
//游戏结束
function isGameOver(){
    if(nospace(board) && nomove(board)){
        gameOver();
    }
}
function gameOver(){
    $("#gameOver").css("display","block");
}

//分数变更
function getScore(){
    document.getElementById("score").innerHTML = score;
}

完整代码参考 GitHub

你可能感兴趣的:(学习JavaScript完成2048小游戏)