基于网页版的2048游戏

前段时间有个很火的游戏叫2048,刚好趁着暑假想练习前端,顺带就把它作为练习项目做成Web Applications

该游戏基于HTML5+JS+CSS

文件结构:

index.html  游戏界面展示

index.css  主界面的CSS样式,16方格采用绝对布局的方式

main.js   游戏的主要逻辑

show.js   游戏的一些动画效果

support.js  底层支撑

jquery.js

页面做了响应式布局,游戏效果如下:

  

代码如下:

index.hml

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta name="viewport" content="width=device-width,height=device-height,initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"/>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>New Game 2048</title>
<script type="text/javascript" src="jquery-1.8.2.min.js"></script>
<script type="text/javascript" src="show.js"></script>
<script type="text/javascript" src="support.js"></script>
<script type="text/javascript" src="main.js"></script>
<link type="text/css" rel="stylesheet" href="index.css" />
</head>
<body>
    <header>
        <h1>2048</h1>
        <a href="javascript:newGame();" id="newGameButton">New Game</a>
        <p>Score:<span id="score">0</span></p>
    </header>
    
    <div id="grid-container">
        <div class="grid-cell" id="grid-cell-0-0"></div>
        <div class="grid-cell" id="grid-cell-0-1"></div>
        <div class="grid-cell" id="grid-cell-0-2"></div>
        <div class="grid-cell" id="grid-cell-0-3"></div>
        
        <div class="grid-cell" id="grid-cell-1-0"></div>
        <div class="grid-cell" id="grid-cell-1-1"></div>
        <div class="grid-cell" id="grid-cell-1-2"></div>
        <div class="grid-cell" id="grid-cell-1-3"></div>
        
        
        <div class="grid-cell" id="grid-cell-2-0"></div>
        <div class="grid-cell" id="grid-cell-2-1"></div>
        <div class="grid-cell" id="grid-cell-2-2"></div>
        <div class="grid-cell" id="grid-cell-2-3"></div>
        
        <div class="grid-cell" id="grid-cell-3-0"></div>
        <div class="grid-cell" id="grid-cell-3-1"></div>
        <div class="grid-cell" id="grid-cell-3-2"></div>
        <div class="grid-cell" id="grid-cell-3-3"></div>
        
        
    </div>

</body>
</html>

index.css

@charset "utf-8";
/* CSS Document */
header{
    display:block;
    margin:0 auto;
    width:100%;
    text-align:center;
}

header h1{
    font-family:Arial, Helvetica, sans-serif;
    font-size:40px;
    font-weight:bold;
}

header #newGameButton{
    display:block;
    margin:20px auto;
    padding:10px 10px;
    width:100px;
    background-color:#930;
    font-family:Arial, Helvetica, sans-serif;
    color:#FFF;
    border-radius:10px;
    text-decoration:none;
}

header #newGameButton:hover{
    background-color:#963;
}

header p{
    font-family:Arial, Helvetica, sans-serif;
    font-size:25px;
    margin:10px auto;
}

#grid-container{
    width:460px;
    height:460px;
    padding:20px;
    
    margin:10px auto;
    background-color:#930;
    border-radius:10px;
    position:relative;
}

.grid-cell{
    width:100px;
    height:100px;
    background-color:#96F;
    border-radius:6px;
    
    position:absolute;
}

.number-cell{
    font-family:Arial, Helvetica, sans-serif;
    border-radius:6px;
    font-size:60px;
    line-height:100px;
    font-weight:bold;
    text-align:center;
    position:absolute;
}
    

main.js

// JavaScript Document
var board=new Array();
var score=0;

sx=0;
sy=0;
ex=0;
ey=0;

$(document).ready(function(e) {
    newGame();
});

function newGame(){
        //初始化游戏
        forMobile();
        init();
        //随机生成2个数
        getOneNumber();
        getOneNumber();
    
    }
    
function init(){
    for(var i=0;i<4;i++){//遍历div
        for(var j=0;j<4;j++){
            var gridCell=$("#grid-cell-"+i+"-"+j);
            gridCell.css("top",getTop(i,j));
            gridCell.css("left",getLeft(i,j));
            }
        }
        //board一维转二维
        for(var i=0;i<4;i++){
            board[i]=new Array();
            for(var j=0;j<4;j++){
                board[i][j]=0;        
                }
            }
        updateBoardView();
        score=0;
    }
    
function forMobile(){
    
     if( documentWidth > 500 ){
        gridContainerWidth = 500;
        cellSpace = 20;
        cellSideLength = 100;
    }

    $('#grid-container').css('width',gridContainerWidth - 2*cellSpace);
    $('#grid-container').css('height',gridContainerWidth - 2*cellSpace);
    $('#grid-container').css('padding', cellSpace);
    $('#grid-container').css('border-radius',0.02*gridContainerWidth);

    $('.grid-cell').css('width',cellSideLength);
    $('.grid-cell').css('height',cellSideLength);
    $('.grid-cell').css('border-radius',0.02*cellSideLength);
}
    
function getOneNumber(){//noSpace没空间返回true
        if(noSpace(board)){
            return false;    
            }else{
                // 随机一个位置
                var x=parseInt(Math.floor(Math.random()*4));
                var y=parseInt(Math.floor(Math.random()*4));
                
                var flag=0;
                while(flag<40){
                    if(board[x][y]==0)break;
                    var x=parseInt(Math.floor(Math.random()*4));
                    var y=parseInt(Math.floor(Math.random()*4));
                    flag++;
                    }
                    
                if(flag==40){
                    for(var i=0;i<4;i++){
                        for(var j=0;j<4;j++){
                            if(board[i][j]==0){
                                x=i;
                                y=j;
                                }
                            }
                        }
                    }
                    
                //随机生成一个数(2or4)
                var number=Math.random()<0.5?2:4;
                
                //在随机的位置显示生成的随机数
                board[x][y]=number;
                showNumber(x,y,number);
                return true;
                    
            }
    }
    
function updateBoardView(){//显示数字
    $(".number-cell").remove();
    for(var i=0;i<4;i++){
        for(var j=0;j<4;j++){
            $("#grid-container").append('<div class="number-cell" id="number-cell-'+i+'-'+j+'"></div>');
            var numberCell=$("#number-cell-"+i+"-"+j);
            //若数字为0则不显示
            if(board[i][j]==0){
                numberCell.css("width","0px");
                numberCell.css("height","0px");
                numberCell.css('top',getTop(i,j) + cellSideLength/2 );
                numberCell.css('left',getLeft(i,j) + cellSideLength/2 );
                }else{
                    numberCell.css('width',cellSideLength);
                    numberCell.css('height',cellSideLength);
                    numberCell.css("top",getTop(i,j));
                    numberCell.css("left",getLeft(i,j));
                    //填充div的背景颜色和前景颜色
                    numberCell.css("background-color",getNumberBackgroundColor(board[i][j]));
                    numberCell.css("color",getNumberColor(board[i][j]));
                    numberCell.text(board[i][j]);
                }
            }
        }
            $('.number-cell').css('line-height',cellSideLength+'px');
               $('.number-cell').css('font-size',0.6*cellSideLength+'px');
    }
    
function isOver(){
    if(noSpace(board)&&noMove(board)){
        //alert(111);
        gameOver();
        }
    }
    
function gameOver(){
    alert("游戏结束!");
    }
    
//监听键盘事件
$(document).keydown(function(event){
    
    switch(event.keyCode){
        
        case 37://left
            if(moveLeft()){
                event.preventDefault();
                setTimeout("getOneNumber()",200);
                isOver();
            }
            break;
            
        case 38://up
            if(moveUp()){
                event.preventDefault();
                setTimeout("getOneNumber()",200);
                isOver();
            }
            break;
            
        case 39://right
            if(moveRight()){
                event.preventDefault();
                setTimeout("getOneNumber()",200);
                isOver();
                }
            break;
            
        case 40://down
            if(moveDown()){
                //alert(1);
                event.preventDefault();
                setTimeout("getOneNumber()",200);
                isOver();
            }
            break;
            
        default:
            break;
        
        
        }
    
    });
    
    
document.addEventListener('touchstart',function(event){//回调函数,返回信息存在event
    sx=event.touches[0].pageX;
    sy=event.touches[0].pageY;
    
    });
    
document.addEventListener('touchend',function(event){
    ex=event.changedTouches[0].pageX;
    ey=event.changedTouches[0].pageY;
    
    dx=ex-sx;
    dy=ey-sy;
    
    if(Math.abs(dx)<documentWidth*0.3&&Math.abs(dy)<documentWidth*0.3)return;// 防误触碰
    
    if(Math.abs(dx)>=Math.abs(dy)){
        //x
        if(dx>0){
            //
            if(moveRight()){
                setTimeout("getOneNumber()",200);
                isOver();
            }
            }else{
                //
            if(moveLeft()){
                setTimeout("getOneNumber()",200);
                isOver();
            }
                }
        }else{
            //y
            if(dy>0){
                //
            if(moveDown()){
                setTimeout("getOneNumber()",200);
                isOver();
            }
                }else{
                    //
                if(moveUp()){
                    setTimeout("getOneNumber()",200);
                    isOver();
            }
                    }
            }
    });
    
document.addEventListener('touchmove',function(event){
    event.preventDefault();//安卓4.0以上会有触碰bug
    });
    
function moveLeft(){
        if(!canMoveLeft(board))return false;
         
         for(var i=0;i<4;i++){
             for(var j=1;j<4;j++){
                 if(board[i][j]!=0){
                     for(var k=0;k<j;k++){
                         if(board[i][k]==0&&noBlockH(i,k,j,board)){
                                 //move
                                showMoveAnimation(i,j,i,k);
                                board[i][k]=board[i][j];
                                board[i][j]=0;
                                continue;
                             }else if(board[i][k]==board[i][j]&&noBlockH(i,k,j,board)){
                                     showMoveAnimation( i , j , i , k );
                                    //叠加
                                    board[i][k]+=board[i][j];
                                    board[i][j]=0;
                                    
                                    score+=board[i][k];
                                    updateScore(score);
                                    continue;
                             }
                         }
                     }
                 }
             }
        setTimeout("updateBoardView()",200);
        return true;
    }
    
function moveRight(){
    if(!canMoveRight(board))return false;
    
    for(var i=0;i<4;i++){
        for(var j=2;j>=0;j--){//除最右列以外,遍历所有
            for(var k=3;k>j;k--){
                if(board[i][k]==0&&noBlockH(i,k,j,board)){
                        showMoveAnimation( i , j , i , k );
                        board[i][k]=board[i][j];
                        board[i][j]=0;
                        continue;
                    }else if(board[i][k]==board[i][j]&&noBlockH(i,k,j,board)){
                            showMoveAnimation( i , j , i , k );
                            board[i][k]+=board[i][j];
                            board[i][j]=0;
                            
                            score+=board[i][k];
                            updateScore(score);
                            continue;
                        }
                }
            }
        }
        setTimeout("updateBoardView()",200);
        return true;
    }
    
function moveUp(){
    if(!canMoveUp(board))return false;
    
    //能移动,怎么移
    for(var j=0;j<4;j++){
        for(var i=1;i<4;i++){
            for(var k=0;k<i;k++){
                if(board[k][j]==0&&noBlockV(j,k,i,board)){
                        showMoveAnimation( i , j , k , j );
                        board[k][j]=board[i][j];
                        board[i][j]=0;
                        continue;
                    }else if(board[k][j]==board[i][j]&&noBlockV(j,k,i,board)){
                        showMoveAnimation( i , j , k , j );
                        board[k][j]+=board[i][j];
                        board[i][j]=0
                        
                        score+=board[i][k];
                        updateScore(score);
                        continue;
                                
                    }
                }
            }
        }
            setTimeout("updateBoardView()",200);
            return true;
    }
    
function moveDown(){
    //先判断是否能移动
    if(!canMoveDown(board))return false;
    
    for(var j=0;j<4;j++){
        for(var i=2;i>=0;i--){
            for(var k=3;k>i;k--){
                 if( board[k][j] == 0 && noBlockV( j , i , k , board ) ){
                        showMoveAnimation( i , j , k , j );
                        board[k][j] = board[i][j];
                        board[i][j] = 0;
                        continue;
                    }else if( board[k][j] == board[i][j] && noBlockV( j , i , k , board ) ){
                        showMoveAnimation( i , j , k , j );
                        board[k][j]+= board[i][j];
                        board[i][j] = 0;
                        
                        score+=board[i][k];
                        updateScore(score);
                        continue;
                    }
                
                }
        }
    }
     setTimeout("updateBoardView()",200);
     return true;
}

show.js

// JavaScript Document
function showNumber(x,y,number){
    var numberCell=$("#number-cell-"+x+"-"+y);
    //填充文字的颜色
    numberCell.css('background-color',getNumberBackgroundColor(number));
    numberCell.css('color',getNumberColor(number));
    numberCell.text(number);
    
    numberCell.animate({
        cellSideLength+"px",
        height:cellSideLength+"px",
        top:getTop(x,y),
        left:getLeft(x,y)
        },60)
    }
    
function showMoveAnimation(fromx,fromy,tox,toy){
         var numberCell = $('#number-cell-' + fromx + '-' + fromy );
         numberCell.animate({
        top:getTop( tox , toy ),
        left:getLeft( tox , toy )
    },200);
        
}

function updateScore(score){
    $("#score").html(score+'');
    
    }

support.js

// JavaScript Document

documentWidth = window.screen.availWidth;
gridContainerWidth = 0.92 * documentWidth;
cellSideLength = 0.18 * documentWidth;
cellSpace = 0.04*documentWidth;

function getTop(i,j){
     return cellSpace + i*( cellSpace + cellSideLength );
    }
    
function getLeft(i,j){
    return cellSpace + j*( cellSpace + cellSideLength );
    }
    
function getNumberBackgroundColor( number ){
    switch( number ){
        case 2:return "#eee4da";break;
        case 4:return "#ede0c8";break;
        case 8:return "#f2b179";break;
        case 16:return "#f59563";break;
        case 32:return "#f67c5f";break;
        case 64:return "#f65e3b";break;
        case 128:return "#edcf72";break;
        case 256:return "#edcc61";break;
        case 512:return "#9c0";break;
        case 1024:return "#33b5e5";break;
        case 2048:return "#09c";break;
        case 4096:return "#a6c";break;
        case 8192:return "#93c";break;
    }

    return "black";
}

function getNumberColor( number ){
    if( number <= 4 )
        return "#776e65";

    return "white";
}
    

function noBlockH(row,k,j,board){//row行,从k列到j列
        for(var i=k+1;i<j;i++){
            if(board[row][i]!=0){
                return false;
                }
            }
            return true;
    }
    
function noBlockV(col,row1,row2,board){//j列,从k行到i行
    for(var i=row1+1;i<row2;i++){
            if(board[i][col]!=0){
                return false;
                }
            }
            return true;
    }    
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;
    }
    
function canMoveRight(board){
    for(var i=0;i<4;i++){
        for(var j=2;j>=0;j--){
            if(board[i][j]!=0){
                if(board[i][j+1]==0||board[i][j]==board[i][j+1]){
                        return true;
                    }
                }
            }
        }
        return false;
    }
    
function canMoveUp(board){
        for(var j=0;j<4;j++){
            for(var i=1;i<4;i++){
                if(board[i][j]!=0){
                    if(board[i-1][j]==0||board[i][j]==board[i-1][j]){
                        return true;
                        }
                    }
                }
            }
            return false;
    }
    
function canMoveDown(board){
        for(var j=0;j<4;j++){
            for(var i=2;i>=0;i--){
                if(board[i][j]!=0){
                    if(board[i+1][j]==0||board[i][j]==board[i+1][j]){
                            return true;
                        }
                    }
                }
            }
            return false;
    }

    
function noMove(board){
    if( canMoveLeft(board)|| canMoveRight(board)|| canMoveUp(board)||canMoveDown(board)){
        return false;
        }
        alert(112);
        return true;
    }
    
function noSpace(board){//没空间,是返回true,否返回false
    for( var i = 0 ; i < 4 ; i ++ ){
        for( var j = 0 ; j < 4 ; j ++ ){
            if(board[i][j]==0){
                return false;
                }
            }
        }
        //循环终止于return 不能放在上面的if判断语句
        return true;
    }
原文地址:https://www.cnblogs.com/lichenwei/p/3871402.html