html5之小游戏2048的实现

一直以来对h5游戏这一块很感兴趣,但苦于现在技术渣渣,也没有合适的项目可以给我练练手,机缘巧合之下看到了2048这款游戏,作为风靡一时的小游戏,当初也是觉得这个很有意思。今天就分享一下如何实现2048这个游戏。

话不多说,直接上代码:


<html>
 <head>
  <title>2048title>
  <meta charset="utf-8" />
  <link rel="stylesheet" href="2048.css"/>
  <script src="2048.js">script>
 head>
 <body>
  <p>Score:<span id="score">span>p>
  <div id="gridPanel">
  div>
  
  <div id="gameover">
    <div>div>
    <p>
        Game Over!<br>
        Score:<span id="finalScore">span><br>
        <a class="btn" id="restart" onclick="game.start()">Try again!a>
    p>
  div>
 body>
html>

2048.css

#gridPanel{
    width:480px; height:480px;
    margin:0 auto;
    background-color:#bbada0;
    border-radius:10px;
    position:relative;
}
.grid,.cell{
    width:100px; height:100px;
    border-radius:6px;
}
.grid{
    background-color:#ccc0b3;
    float:left;
    margin: 16px 0 0 16px;
}
.cell{
    position:absolute;
    text-align:center;
    line-height:100px;
    font-size:60px;
    color:#fff;
}
/*同一行拥有统一的top*/
#c00,#c01,#c02,#c03,#c04,#c05{top:16px}
#c10,#c11,#c12,#c13,#c14,#c15{top:132px}
#c20,#c21,#c22,#c23,#c24,#c25{top:248px}
#c30,#c31,#c32,#c33,#c34,#c35{top:364px}
#c40,#c41,#c42,#c43,#c44,#c45{top:480px}
#c50,#c51,#c52,#c53,#c54,#c55{top:596px}
/*同一列拥有统一的left*/
#c00,#c10,#c20,#c30,#c40,#c50{left:16px}
#c01,#c11,#c21,#c31,#c41,#c51{left:132px}
#c02,#c12,#c22,#c32,#c42,#c52{left:248px}
#c03,#c13,#c23,#c33,#c43,#c53{left:364px}
#c04,#c14,#c24,#c34,#c44,#c54{left:480px}
#c05,#c15,#c25,#c35,#c45,#c55{left:596px}

.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-family:Arial; font-weight:bold;
    font-size:40px; padding-top:15px;
}

/*设置游戏结束界面*/
#gameover{width:100%; height:100%;
    position:absolute; top:0; left:0;
    display:none;
}
#gameover div{width:100%; height:100%;
    background-color:#555; opacity:0.5;
}
#gameover p{width:300px; height:200px;
    border:1px solid #edcf72;
    line-height:1.6em;
    text-align:center;
    background-color:#fff;
    border-radius:10px;
    position:absolute;
    top:50%; left:50%;
    margin-top:-100px;
    margin-left:-150px;
}
.btn{padding:10px; border-radius:6px;
    background-color:#9f8b77; color:#fff; cursor:pointer;
}

2048.js

var game={
    data:[],//启动后是一个二维数组,存储每个格的数字
    RN:4, //总行数
    CN:4, //总列数
    score:0, //保存游戏分数
    state:0, //保存游戏的状态
    RUNNING:1, //专门表示游戏正在运行
    GAMEOVER:0, //专门表示游戏结束
    getGridsHtml:function(){//生成所有背景格的html代码
    //r从0开始,到
        for(var r=0,arr=[];r<this.RN;r++){
    //  c从0开始,到
            for(var c=0;c<this.CN;arr.push(""+r+c++));
        }
        return '
'" class="grid">
'" class="grid">
'
; }, getCellsHtml:function(){//生成所有前景格的html代码 for(var r=0,arr=[];r<this.RN;r++){ for(var c=0;c<this.CN;arr.push(""+r+c++)); } return '
'" class="cell">
'" class="cell">
'
; }, init:function(){//生成所有背景和前景格,并加入到页面 var gp=document.getElementById("gridPanel"); gp.style.width=116*this.CN+16+"px"; gp.style.height=116*this.RN+16+"px"; gp.innerHTML=this.getGridsHtml() +this.getCellsHtml(); }, start:function(){//游戏启动方法,启动游戏时调用 this.init(); this.state=this.RUNNING; //游戏状态改为启动 //初始化数组为RN行,CN列的二维数组,所有元素为0 //初始化空数组 for(var r=0;r<this.RN;r++){ this.data[r]=[];//初始化每一行为空数组 for(var c=0;c<this.CN;c++){ this.data[r][c]=0;//初始化每个格为0 } } this.score=0;//初始化游戏分数为0 //随机生成2个2或4 this.randomNum(); this.randomNum(); this.updateView();//将data的数据,更行到页面div }, isGameOver:function(){//判断当前游戏是否结束 //遍历data中所有元素 for(var r=0;r<this.data.length;r++){ for(var c=0;c<this.data[r].length;c++){ // 如果当前元素值==0,就返回false if(this.data[r][c]==0){return false;} else{//否则 如果当前列不是最右侧列, // 且当前元素等于右侧元素 if(c!=this.data[r].length-1 &&this.data[r][c]==this.data[r][c+1]){ return false;//返回false }else if(r!=this.data.length-1 &&this.data[r][c]==this.data[r+1][c]){ //否则 如果当前行不是最后一行 // 且当前元素等于下方元素 return false;//返回false } } } }//(遍历结束)将游戏状态改为GAMEOVER this.state=this.GAMEOVER; return true;//返回true }, randomNum:function(){//随机挑选一个位置,生成2或4 if(!this.isFull()){//只有不满,才执行以下所有代码 while(true){//反复执行 // 随机生成一个行下标,保存在r中 var r=parseInt(Math.random()*(this.RN)); // 随机生成一个列下标,保存在c中 var c=parseInt(Math.random()*(this.CN)); // 如果data中r行c列位置的值==0 if(this.data[r][c]==0){ // 随机生成2或4,放入r行c列的元素中 // 如果生成一个随机数<0.5,就放入2,否则放4 this.data[r][c]=Math.random()<0.5?2:4; break;//退出循环 } } } }, isFull:function(){//专门用来判断数组是否已满 //遍历data中每个元素 for(var r=0;r<this.data.length;r++){ for(var c=0;c<this.data[r].length;c++){ // 只要发现当前元素==0 if(this.data[r][c]==0){ return false;//返回false } } }//(遍历结束)返回true; return true; }, //负责将data中每个元素刷到页面中 //并修改页面每个div的class属性 updateView:function(){ //遍历data中每个元素 for(var r=0;r<this.data.length;r++){ for(var c=0;c<this.data[r].length;c++){ //找到页面中和当前元素对应位置的div var div=document.getElementById("c"+r+c); //只有当前元素指不等于0 if(this.data[r][c]!=0){ //将当前元素值放入div的内容中 div.innerHTML=this.data[r][c]; //给div的class穿上和数值对应的衣服 div.className= "cell n"+this.data[r][c]; }else{ //否则,重置div的样式为cell,并清空内容 div.className="cell"; div.innerHTML=""; } } } /*将分数写到页面*/ var span=document.getElementById("score"); span.innerHTML=this.score; //找到#gameover, var gameover=document.getElementById("gameover"); if(this.state==this.GAMEOVER){//如果游戏结束 var span=document.getElementById("finalScore"); span.innerHTML=this.score; //修改display为block gameover.style.display="block"; }else{//否则,修改display为none gameover.style.display="none"; } }, moveLeft:function(){//左移所有行 var before=this.data.toString(); for(var r=0;r<this.data.length;r++){ this.moveLeftInRow(r); } var after=this.data.toString(); if(before!=after){ this.randomNum();//随机生成一个新数 this.isGameOver();//判断游戏是否结束 this.updateView(); //更新界面 } }, moveLeftInRow:function(r){//左移第r行 for(var c=0;c<this.data[r].length-1;c++){ //从c开始,找下一个不为0的位置下标next var next=this.getRightNext(r,c); //如果next==-1,说明都是0了 if(next==-1){break;}//退出循环 else{ if(this.data[r][c]==0){ this.data[r][c]=this.data[r][next]; this.data[r][next]=0; c--; }else if(this.data[r][c] ==this.data[r][next]){ this.data[r][c]*=2; this.data[r][next]=0; this.score+=this.data[r][c]; } } } }, getRightNext:function(r,c){//专门找当前位置右侧下一个 //从c+1开始遍历之后所有元素 for(var next=c+1;next<this.data[r].length;next++){ if(this.data[r][next]!=0){//如果找到!=0的 return next;//返回next } }//(遍历结束)返回-1 return -1; }, moveRight:function(){ var before=this.data.toString(); for(var r=0;r<this.data.length;r++){ this.moveRightInRow(r); } var after=this.data.toString(); if(before!=after){ this.randomNum(); this.isGameOver();//判断游戏是否结束 this.updateView(); } }, moveRightInRow:function(r){ /*遍历当前行中每个元素, c从length-1开始,到1结束,每次递减1*/ for(var c=this.data[r].length-1;c>0;c--){ // 找左侧下一个不为0的数的下标,保存在prev中 var prev=this.getLeftPrev(r,c); // 如果prev等于-1,就退出循环 if(prev==-1){break;} else{// 否则 if(this.data[r][c]==0){//如果当前元素是0 // 用prev位置的元素,替换当前元素 this.data[r][c]=this.data[r][prev]; // 将prev位置的元素设置为0 this.data[r][prev]=0; c++;//c右移一位 }else if(this.data[r][c] ==this.data[r][prev]){ // 否则,如果当前元素和prev位置的元素相等 // 将当前位置的元素乘2 this.data[r][c]*=2; // 将prev位置的元素设置为0 this.data[r][prev]=0; this.score+=this.data[r][c]; } } } }, getLeftPrev:function(r,c){ /*遍历c左侧剩余元素, prevC从c-1开始,到0结束,每次递减1*/ for(var prevC=c-1;prevC>=0;prevC--){ // 如果prevC位置的元素不等于0,就返回prevC if(this.data[r][prevC]!=0){return prevC;} } return -1;//(循环退出)返回-1; }, moveUp:function(){//遍历每一列 var before=this.data.toString(); for(var c=0;c<this.CN;c++){ this.moveUpInCol(c); } var after=this.data.toString(); if(before!=after){ this.randomNum(); this.isGameOver();//判断游戏是否结束 this.updateView(); } }, moveUpInCol:function(c){ /*遍历当前列中每个元素, r从0开始,到<整个数组的length-1结束,每次递增1*/ for(var r=0;r<this.data.length-1;r++){ // 找下方下一个不为0的数的下标,保存在down中 var down=this.getDownNext(r,c); // 如果down等于-1,就退出循环 if(down==-1){break;} else{// 否则 if(this.data[r][c]==0){//如果当前元素是0 // 用down位置的元素,替换当前元素 this.data[r][c]=this.data[down][c]; // 将down位置的元素设置为0 this.data[down][c]=0; r--;//r向上退一位 }else if(this.data[r][c] ==this.data[down][c]){ // 否则,如果当前元素和down位置的元素相等 // 将当前位置的元素乘2 this.data[r][c]*=2; // 将down位置的元素设置为0 this.data[down][c]=0; this.score+=this.data[r][c]; } } } }, getDownNext:function(r,c){ /*遍历当前列中下方剩余元素 downR从r+1开始,到<整个数组的length结束,downR递增1*/ for(var downR=r+1;downR<this.data.length;downR++){ // 如果downR位置的元素!=0,就返回downR if(this.data[downR][c]!=0){return downR} } return -1;//(遍历结束)返回-1; }, moveDown:function(){//遍历每一列 var before=this.data.toString(); for(var c=0;c<this.CN;c++){ this.moveDownInCol(c); } var after=this.data.toString(); if(before!=after){ this.randomNum(); this.isGameOver();//判断游戏是否结束 this.updateView(); } }, moveDownInCol:function(c){ /*r从最后一行开始,向上遍历当前列每个元素 到>0结束,每次递减1*/ for(var r=this.data.length-1;r>0;r--){ // 获得当前位置上方不为0的数的位置,保存在up中 var up=this.getUpPrev(r,c); // 如果up==-1,就退出循环 if(up==-1){break;} else{// 否则 // 如果当前位置等于0 if(this.data[r][c]==0){ // 用up位置的值替换当前位置的值 this.data[r][c]=this.data[up][c]; // 将up位置设置为0 this.data[up][c]=0; r++;//r增1 }else if(this.data[r][c] ==this.data[up][c]){ // 否则,如果当前位置等于up位置 // 将当前位置*=2; this.data[r][c]*=2; // 将up位置设置为0 this.data[up][c]=0; this.score+=this.data[r][c]; } } } }, getUpPrev:function(r,c){ //upR从r的上方开始,到0结束,每次递减1 for(var upR=r-1;upR>=0;upR--){ // 如果upR位置的值!=0,就返回upR if(this.data[upR][c]!=0){return upR} } return -1;//(遍历结束)返回-1 } } //当页面加载后,启动游戏 window.οnlοad=function(){ game.start(); //当按键按下时 document.οnkeydοwn=function(){ //只有游戏运行时才响应按键操作 if(game.state==game.RUNNING){ var e=window.event||arguments[0]; if(e.keyCode==37){ game.moveLeft(); }else if(e.keyCode==39){ game.moveRight(); }else if(e.keyCode==38){ game.moveUp(); }else if(e.keyCode==40){ game.moveDown(); } } } }

js这一块都详细备注,希望大家多多支持,共同进步,谢谢!

你可能感兴趣的:(html5)