javascript写的2048游戏

9 篇文章 0 订阅
5 篇文章 0 订阅

原生JS写的2048游戏,后又对js代码进行了精简,写了左移逻辑,其他方向采用转置矩阵后左移代码复用。代码如下:

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title>2048小游戏</title>
    <link rel="stylesheet" href="2048.css">

</head>
<body>
<p>
    <!--TOP:<span id="top">0</span><br>-->
    SCORE:<span id="score">0</span>
</p>
<div id="playground">
    <div id="c00" class="cell"></div>
    <div id="c01" class="cell"></div>
    <div id="c02" class="cell"></div>
    <div id="c03" class="cell"></div>
    <div id="c10" class="cell"></div>
    <div id="c11" class="cell"></div>
    <div id="c12" class="cell"></div>
    <div id="c13" class="cell"></div>
    <div id="c20" class="cell"></div>
    <div id="c21" class="cell"></div>
    <div id="c22" class="cell"></div>
    <div id="c23" class="cell"></div>
    <div id="c30" class="cell"></div>
    <div id="c31" class="cell"></div>
    <div id="c32" class="cell"></div>
    <div id="c33" class="cell"></div>
</div>
<div id="gameOver"><!-- 半透明遮罩 -->
    <p>
        GAME OVER!<br>
        SCORE: <span id="final"></span><br>
        <a class="btn" οnclick="game.start()">Try again!</a>
    </p>
</div>

<script src = "2048.js">


</script>
</body>
</html>


CSS:
#playground{
    width: 480px; height:480px;
    margin:0 auto;
    background:#bbada0;
    border-radius:10px;
    position:relative;
}
.cell{
    width:100px;
    height:100px;
    border-radius:6px;
    background: #ccc0b3;
    position:absolute;
    line-height:100px;
    font-size:60px;
    text-align:center;
    color:#fff;
}
[id^="c0"]{top:16px;}
[id^="c1"]{top:132px;}
[id^="c2"]{top:248px;}
[id^="c3"]{top:364px;}

[id$="0"]{left:16px;}
[id$="1"]{left:132px;}
[id$="2"]{left:248px;}
[id$="3"]{left:364px;}

.n2{background-color:#eee3da}
.n4{background-color:#ede0c8}
.n8{background-color:#f2b179}
.n16{background-color:#f59563}
.n32{background-color:#f67c5f}
.n64{background-color:#f65e3b}
.n128{background-color:#edcf72}
.n256{background-color:#edcc61}
.n512{background-color:#9c0}
.n1024{background-color:#33b5e5}
.n2048{background-color:#09c}
.n4096{background-color:#a6c}
.n8192{background-color:#93c}
.n2,.n4{color:#776e65}
.n1024,.n2048,.n4096,.n8192{font-size:40px}

p{
    width:480px;
    margin:0 auto;
    font-size:40px;
    font-family:Arial;
    font-weight:bold;
    padding-top:15px;
}
#gameOver{
    position:absolute;
    left:0;right:0;top:0;bottom:0;
    background:rgba(55,55,55,.5);
}
#gameOver>p{
    width:300px;
    height:200px;
    background:#fff;
    position:absolute;
    top:50%;left:50%;
    margin-top:-100px;
    margin-left:-150px;
    text-align:center;
    line-height:1.5em;
    border-radius:10px;
    border:1px solid #edcf72;
}
#gameOver .btn{
    padding:10px;
    color:#fff;
    background-color:#9f8d77;
    border-radius:6px;
    cursor:pointer;
}


JS:

/**
 * Created by viyo on 2016/12/7.
 */
var game={
    RN:4,CN:4,
    data:null,
    score:0,
    state:1,
    GAMEOVER:0,
    RUNNING:1,
    start:function(){
                this.state=this.RUNNING;
                this.score=0;
                this.data=[];
                for(var r=0;r<this.RN;r++){
                    this.data[r]=new Array(this.CN);//this.data.push([]);
                    for(var c=0;c<this.CN;c++){
                        this.data[r][c]=0;
                    }
                }
                this.randomNum();
                this.randomNum();
                this.updateView();
                document.onkeydown = function(e){
                    switch(e.keyCode){
                        case 37: this.moveLeft();break;
                        case 38: this.moveTop();break;
                        case 39: this.moveRight();break;
                        case 40: this.moveDown();break;
                    }
                }.bind(this);           //用onkeydown外的this替换内部的this
                console.log(this.data.join("\n"));
          },
    randomNum:function()                //在一个随机位置生成2或4
        {
            while (true) {
                var r = Math.floor(Math.random() * this.RN);
                var c = Math.floor(Math.random() * this.CN);
                if (this.data[r][c] === 0) {
                    this.data[r][c] = Math.random() < 0.5 ? 2 : 4;
                    break;
                }
            }
     },
    updateView:function(){              //更新数据
        for(var r=0;r<this.RN;r++){
            for(var c=0;c<this.CN;c++){
                var div=document.getElementById("c"+r+c);
                if(this.data[r][c]!=0){
                    div.innerHTML=this.data[r][c];
                    div.className="cell n"+this.data[r][c];
                }else{
                    div.innerHTML="";
                    div.className="cell";
                }
            }
        }
        document.getElementById("score").innerHTML=this.score;
        document.getElementById("gameOver").style.display=this.state===this.GAMEOVER?"block":"none";
                    this.state===this.GAMEOVER&&(
                        document.getElementById("final").innerHTML=this.score
                    );
    },
    moveLeft:function(){
        var before=String(this.data);
        for(var r=0;r<this.RN;r++){
            this.moveLeftInRow(r);
        }
        var after=String(this.data);
        if(after!=before){
            this.randomNum();
            this.isGameOver()&&(this.state=this.GAMEOVER);
            this.updateView();
        }
    },
    moveLeftInRow:function(r){                           //左移1行
        for(var c=0;c<this.CN-1;c++){                    //c从0开始,遍历data中r行,到<CN-1结束
            var nextc=this.getNextInRow(r,c);            //找data中r行c列右侧下一个不为0的位置nextc
            if(nextc==-1){break;}                        //如果nextc是-1,就退出循环
            else{                                        //否则
                if(this.data[r][c]==0){                  //如果r行c列为0
                    this.data[r][c]=this.data[r][nextc]; //将r行nextc列的值赋值给r行c列
                    this.data[r][nextc]=0;               //将r行nextc列的值置为0
                    c--;                                 //c留在原地
                }else if(this.data[r][c]==this.data[r][nextc]){     //否则,如果r行c列等于r行nextc列
                    this.data[r][c]*=2;                             //将r行c列的值*2
                    this.score+=this.data[r][c];                    //将r行c列的新值累加到score属性上
                    this.data[r][nextc]=0;                          //将r行nextc列的值置为0
                }
            }
        }
    },
    getNextInRow:function(r,c){
        for(var i=c+1;i<this.CN;i++){
            if(this.data[r][i]!=0)
                return i;
        }
        return -1;
    },
    moveRight:function(){
        this.xExchangge();
        this.moveLeft();
        this.xExchangge();
        this.updateView();
    },
    moveTop:function(){
        this.middleExchange();
        this.moveLeft();
        this.middleExchange();
        this.updateView();
    },
    moveDown:function(){
        this.middleExchange();
        this.moveRight();
        this.middleExchange();
        this.updateView();
    },
    xExchangge:function(){
        for(var i=0;i<4;i++){
            for(var j=0;j<2;j++){
                this.data[i][j]^=this.data[i][3-j];
                this.data[i][3-j]^=this.data[i][j];
                this.data[i][j]^=this.data[i][3-j];
            }
        }
    },
    middleExchange:function(){
        for(var i=0;i<4;i++){
            for(var j=i+1;j<4;j++){
                this.data[i][j]^=this.data[j][i];
                this.data[j][i]^=this.data[i][j];
                this.data[i][j]^=this.data[j][i];
            }
        }
    },
    isGameOver:function(){
        for(var r=0;r<this.RN;r++){
            for(var c=0;c<this.CN;c++){
//如果当前元素是0或c<this.CN-1且当前元素等于右侧元素或r<this.RN-1且当前元素等于下方元素
                if(this.data[r][c]==0||
                    c<this.CN-1
                    &&this.data[r][c]==this.data[r][c+1]||
                    r<this.RN-1
                    &&this.data[r][c]==this.data[r+1][c]){
                    return false;
                }
            }
        }
        return true;
    }
};
game.start();





  • 1
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值