使用Javascript写的2048小游戏


Posted in Javascript onNovember 25, 2015

最近心血来潮,项目结束了,使用javascript写个小游戏,练练收吧,写的不好还请各位大侠给出批评建议。

HTML代码如下

<!DOCTYPE html>
<html>
 <head>
 <title></title>
 <meta charset="utf-8" />
 <link rel="stylesheet" href="2048.css"/>
 <script src="2048.js"></script>
 <script>
 </script>
 </head>
 <body>
 <p>Score:<span id="score"></span></p>
 <div id="gridPanel">
 <!--背景格-->
 <!--第1行-->
 <div id="g00" class="grid"></div>
 <div id="g01" class="grid"></div>
 <div id="g02" class="grid"></div>
 <div id="g03" class="grid"></div>
 <!--第2行-->
 <div id="g10" class="grid"></div>
 <div id="g11" class="grid"></div>
 <div id="g12" class="grid"></div>
 <div id="g13" class="grid"></div>
 <!--第3行-->
 <div id="g20" class="grid"></div>
 <div id="g21" class="grid"></div>
 <div id="g22" class="grid"></div>
 <div id="g23" class="grid"></div>
 <!--第4行-->
 <div id="g30" class="grid"></div>
 <div id="g31" class="grid"></div>
 <div id="g32" class="grid"></div>
 <div id="g33" class="grid"></div>
 <!--前景格-->
 <!--第1行-->
 <div id="c00" class="cell"></div>
 <div id="c01" class="cell"></div>
 <div id="c02" class="cell"></div>
 <div id="c03" class="cell"></div>
 <!--第2行-->
 <div id="c10" class="cell"></div>
 <div id="c11" class="cell"></div>
 <div id="c12" class="cell"></div>
 <div id="c13" class="cell"></div>
 <!--第3行-->
 <div id="c20" class="cell"></div>
 <div id="c21" class="cell"></div>
 <div id="c22" class="cell"></div>
 <div id="c23" class="cell"></div>
 <!--第4行-->
 <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"><!--同时包含前景和背景的容器-->
 <div><!--半透明灰色背景--></div>
 <p><!--居中小窗口-->
  Game Over!<br>
  Score:<span id="finalScore"></span><br>
  <a class="button" onclick="game.start()">Try again!</a>
 </p>
 </div>
 </body>
</html>

CSS代码如下

@charset "utf-8";
#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;
 margin:16px 0 0 16px;
 float:left;
}
.cell{
 /*margin:16px 0 0 16px;
 float:left;
 position:relative;
 z-index:10;
 top:-464px;
 left:0;*/
 position:absolute;
 text-align:center;
 line-height:100px;
 font-size:60px;
}
#c00,#c01,#c02,#c03{top:16px;}
#c10,#c11,#c12,#c13{top:132px;}
#c20,#c21,#c22,#c23{top:248px;}
#c30,#c31,#c32,#c33{top:364px;}
#c00,#c10,#c20,#c30{left:16px;}
#c01,#c11,#c21,#c31{left:132px;}
#c02,#c12,#c22,#c32{left:248px;}
#c03,#c13,#c23,#c33{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}
.n8,.n16,.n32,.n64,
.n128,.n256,.n512,
.n1024,.n2048,.n4096,.n8192{color:#fff}
.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;
}
/*Game Over*/
#gameOver{width:100%; height:100%;
 position:absolute; top:0; left:0;
 display:none;
}
#gameOver>div{width:100%; height:100%;
 background-color:#555; opacity:.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:-135px; margin-left:-150px;
}
.button{padding:10px; border-radius:6px;
 background-color:#9f8b77; color:#fff;
 cursor:pointer;
}

javascript代码如下

var game={
 data:[],//保存所有数字的二维数组
 rn:4, //总行数
 cn:4, //总列数
 state: 0, //游戏当前状态:Running|GameOver
 RUNNING:1,
 GAMEOVER:0,
 score:0, //分数
 isGameOver:function(){//判断游戏状态为结束
  //如果没有满,则返回false
  if(!this.isFull()){
   return false;
  }else{//否则
   //从左上角第一个元素开始,遍历二维数组
   for(var row=0;row<this.rn;row++){
    for(var col=0;col<this.cn;col++){
     //如果当前元素不是最右侧元素
     if(col<this.cn-1){
     // 如果当前元素==右侧元素
      if(this.data[row][col]==
       this.data[row][col+1]){
       return false;
      }
     }
     //如果当前元素不是最下方元素
     if(row<this.rn-1){
     // 如果当前元素==下方元素
      if(this.data[row][col]==
       this.data[row+1][col]){
       return false;
      }
     }
    }
   }return true;
  }
 },
 start:function(){//游戏开始
  this.state=this.RUNNING;
  //找到游戏结束界面,隐藏
  var div=document.getElementById("gameOver");
  div.style.display="none";
  this.data=[//初始化二维数组
   [0,0,0,0],
   [0,0,0,0],
   [0,0,0,0],
   [0,0,0,0]
  ];
  this.score=0; //重置分数为0
  /*for(var r=0;r<this.rn;r++){
   this.data[r]=[];//向空数组中添加每一行数组
   for(var c=0;c<this.cn;c++){
    //向当前空行数组中加默认元素0
    this.data[r][c]=0;
   }
  }*/
  //在两个随机位置生成2或4
  this.randomNum();
  this.randomNum();
  //将数据更新到页面
  this.updateView();
 },
 isFull:function(){//判断当前数组是否已满
for(var row=0;row<this.rn;row++){//遍历二维数组
 for(var col=0;col<this.cn;col++){
  // 只要发现当前元素==0
  if(this.data[row][col]==0){
   return false;
  }
 }
}
  //(如果循环正常退出)
  return true;
 },
 randomNum:function(){//在随机空位置生成一个数
  if(!this.isFull()){//如果*不*满,才{
   while(true){//循环true
    //0-3随机生成一个行号row
    var row=parseInt(Math.random()*this.rn);
    //0-3随机生成一个列号col
    var col=parseInt(Math.random()*this.cn);
    //如果data[row][col]==0
    if(this.data[row][col]==0){
    // Math.random():<0.5 >=0.5
    //     2  4
    // 随机生成一个数<0.5?2:4,
    // 放入data[row][col]
     this.data[row][col]=
        Math.random()<0.5?2:4;
     break;//退出循环 
    }
   }
  }
 },
 updateView:function(){
//将二维数组中每个格的数字放入前景格中
//遍历二维数组中每个元素,比如:row=2,col=3, 16
for(var row=0;row<this.rn;row++){
 for(var col=0;col<this.cn;col++){
  /*网页中一切元素,属性,文字都是对象*/
  var div=document.getElementById("c"+row+col);
           //"c23"
  var curr=this.data[row][col]; //当前元素值
  //修改div开始标签和结束标签之间的内容
  div.innerHTML=curr!=0?curr:"";
  //修改div的class属性
  div.className=curr!=0?"cell n"+curr:"cell"
  // class
 }
}
 var span=document.getElementById("score");
 span.innerHTML=this.score;
 //判断并修改游戏状态为GAMEOVER
 if(this.isGameOver()){
  this.state=this.GAMEOVER;
  var div=document.getElementById("gameOver");
  var span=document.getElementById("finalScore");
  span.innerHTML=this.score;
 //修改div的style属性下的display子属性为"block"
  div.style.display="block";
 }
 },//updateView方法的结束
 /*实现左移*/
 /*找当前位置右侧,*下一个*不为0的数*/
 getRightNext:function(row,col){
  //循环变量:nextc——>指下一个元素的列下标
  //从col+1开始,遍历row行中剩余元素,<cn结束
  for(var nextc=col+1;nextc<this.cn;nextc++){
  // 如果遍历到的元素!=0
   if(this.data[row][nextc]!=0){
  //  就返回nextc
    return nextc;
   }
  }return -1;//(循环正常退出,就)返回-1
 },
 /*判断并左移*指定行*中的每个元素*/
 moveLeftInRow:function(row){
  //col从0开始,遍历row行中的每个元素,<cn-1结束
  for(var col=0;col<this.cn-1;col++){
  // 获得当前元素下一个不为0的元素的下标nextc
   var nextc=this.getRightNext(row,col);
  // 如果nextc==-1,(说明后边没有!=0的元素了)
   if(nextc==-1){
    break;
   }else{// 否则
  //  如果当前位置==0,
    if(this.data[row][col]==0){
  //   将下一个位置的值,当入当前位置
     this.data[row][col]=
      this.data[row][nextc];
  //   下一个位置设置为0
     this.data[row][nextc]=0;
     col--;//让col退一格,重复检查一次
    }else if(this.data[row][col]==
       this.data[row][nextc]){
  //  否则,如果当前位置==nextc的位置
  //   将当前位置*=2;
     this.data[row][col]*=2;
  //   下一个位置设置为0;
     this.data[row][nextc]=0;
  //   将当前位置的值,累加到score上
     this.score+=this.data[row][col];
    }
   }
  }
 },
 /*移动所有行*/
 moveLeft:function(){
  var oldStr=this.data.toString();
  //循环遍历每一行
  for(var row=0;row<this.rn;row++){
  // 调用moveLeftInRow方法,传入当前行号row
   this.moveLeftInRow(row);
  }//(循环结束后)
  var newStr=this.data.toString();
  if(oldStr!=newStr){
   //调用randomNum(),随机生成一个数
   this.randomNum();
   //调用updateView(),更行页面
   this.updateView();
  }
 },
 moveRight:function(){
  var oldStr=this.data.toString();
  for(var row=0;row<this.rn;row++){
   this.moveRightInRow(row);
  }
  var newStr=this.data.toString();
  if(oldStr!=newStr){
   this.randomNum();
   this.updateView();
  }
 },
 /*判断并右移*指定行*中的每个元素*/
 moveRightInRow:function(row){
  //col从cn-1开始,到>0结束
  for(var col=this.cn-1;col>0;col--){
   var nextc=this.getLeftNext(row,col);
   if(nextc==-1){
    break;
   }else{
    if(this.data[row][col]==0){
     this.data[row][col]=
      this.data[row][nextc];
     this.data[row][nextc]=0;
     col++;
    }else if(this.data[row][col]==
       this.data[row][nextc]){
     this.data[row][col]*=2;
     this.data[row][nextc]=0;
     this.score+=this.data[row][col];
    }
   }
  }
 },
 /*找当前位置左侧,下一个不为0的数*/
 getLeftNext:function(row,col){
  //nextc从col-1开始,遍历row行中剩余元素,>=0结束
  for(var nextc=col-1;nextc>=0;nextc--){
   // 遍历过程中,同getRightNext
   if(this.data[row][nextc]!=0){
    return nextc;
   }
  }return -1;
 },
 /*获得任意位置下方不为0的位置*/
 getDownNext:function(row,col){
  //nextr从row+1开始,到<this.rn结束
  for(var nextr=row+1;nextr<this.rn;nextr++){
   if(this.data[nextr][col]!=0){
    return nextr;
   }
  }return -1;
 },
 /*判断并上移*指定列*中的每个元素*/
 moveUpInCol:function(col){
  //row从0开始,到<rn-1,遍历每行元素
  for(var row=0;row<this.rn-1;row++){
  // 先获得当前位置下方不为0的行nextr
   var nextr=this.getDownNext(row,col);
   if(nextr==-1){ break; // 如果nextr==-1
   }else{// 否则
  //  如果当前位置等于0
    if(this.data[row][col]==0){
  //   将当前位置替换为nextr位置的元素
     this.data[row][col]=
       this.data[nextr][col];
  //   将nextr位置设置为0
     this.data[nextr][col]=0;
     row--;//退一行,再循环时保持原位
    }else if(this.data[row][col]==
       this.data[nextr][col]){
    //  否则,如果当前位置等于nextr位置
  //   将当前位置*=2
     this.data[row][col]*=2;
  //   将nextr位置设置为0
     this.data[nextr][col]=0;
  //   将当前位置的值累加到score属性上
     this.score+=this.data[row][col];
    }
   }
  }
 },
 /*上移所有列*/
 moveUp:function(){
  var oldStr=this.data.toString();
  //遍历所有列
for(var col=0;col<this.cn;this.moveUpInCol(col++));
  var newStr=this.data.toString();
  if(oldStr!=newStr){
   this.randomNum();
   this.updateView();
  }
 },
 /*下移所有列*/
 moveDown:function(){
  var oldStr=this.data.toString();
for(var col=0;col<this.cn;this.moveDownInCol(col++));
  var newStr=this.data.toString();
  if(oldStr!=newStr){
   this.randomNum();
   this.updateView();
  }
 },
 moveDownInCol:function(col){
  //row从this.rn-1,到>0结束,row--
  for(var row=this.rn-1;row>0;row--){
   var nextr=this.getUpNext(row,col);
   if(nextr==-1){
    break;
   }else{
    if(this.data[row][col]==0){
     this.data[row][col]=
       this.data[nextr][col];
     this.data[nextr][col]=0;
     row++;
    }else if(this.data[row][col]==
       this.data[nextr][col]){
     this.data[row][col]*=2;
     this.data[nextr][col]=0;
     this.score+=this.data[row][col];
    }
   }
  }
 },
 /*获得任意位置上方不为0的位置*/
 getUpNext:function(row,col){
  for(var nextr=row-1;nextr>=0;nextr--){
   if(this.data[nextr][col]!=0){
    return nextr;
   }
  }return -1;
 }
}
//onload事件:当页面加载*后*自动执行
window.onload=function(){
 game.start();//页面加载后,自动启动游戏
 //当按键盘按键时,触发移动:
 document.onkeydown=function(){
  //获得事件对象中键盘号:2步
  //事件对象:在事件发生时自动创建
  //   封装了事件的信息
  if(game.state==game.RUNNING){
   //Step1: 获得事件对象
   var e=window.event||arguments[0];
     //IE   DOM标准
   //Step2: 获得键盘号:e.keyCode
   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();
   }
   //如果按左键,调用moveLeft
   //否则如果按右键,调用moveRight
  }
 }
}

以上代码就是使用javascript写的2048小游戏,代码简单易懂并附有注释,希望大家喜欢。

Javascript 相关文章推荐
7个Javascript地图脚本整理
Oct 20 Javascript
jQuery中使用了document和window哪些属性和方法小结
Sep 13 Javascript
Javascript判断对象是否相等实现代码
Mar 18 Javascript
js关于字符长度限制的问题示例探讨
Jan 24 Javascript
JavaScript及jquey实现多个数组的合并操作
Sep 06 Javascript
jquery操作 iframe的方法
Dec 03 Javascript
第四篇Bootstrap网格系统偏移列和嵌套列
Jun 21 Javascript
jQuery EasyUI 获取tabs的实例解析
Dec 06 Javascript
为你的微信小程序体积瘦身详解
May 20 Javascript
深入掌握 react的 setState的工作机制
Sep 27 Javascript
es6基础学习之解构赋值
Dec 10 Javascript
微信小程序实现页面左右滑动
Nov 16 Javascript
Jquery-1.9.1源码分析系列(十一)之DOM操作
Nov 25 #Javascript
Bootstrap每天必学之栅格系统(布局)
Nov 25 #Javascript
jQuery实现宽屏图片轮播实例教程
Nov 24 #Javascript
jquery利用拖拽方式在图片上添加热链接
Nov 24 #Javascript
jquery中checkbox使用方法简单实例演示
Nov 24 #Javascript
基于Jquery和CSS3制作数字时钟附源码下载(CSS3篇)
Nov 24 #Javascript
基于jQuery和CSS3制作数字时钟附源码下载(jquery篇)
Nov 24 #Javascript
You might like
php+ajax 实现输入读取数据库显示匹配信息
2015/10/08 PHP
使用PHP similar text计算两个字符串相似度
2015/11/06 PHP
PHP基于openssl实现非对称加密代码实例
2020/06/19 PHP
javascript确认框的三种使用方法
2013/12/17 Javascript
简介JavaScript中getUTCMonth()方法的使用
2015/06/10 Javascript
javascript每日必学之多态
2016/02/23 Javascript
Javascript基础学习笔记(菜鸟必看篇)
2016/07/22 Javascript
微信小程序中使用Promise进行异步流程处理的实例详解
2017/08/17 Javascript
Angular项目从新建、打包到nginx部署全过程记录
2017/12/09 Javascript
elementui的默认样式修改方法
2018/02/23 Javascript
Angular实现模版驱动表单的自定义校验功能(密码确认为例)
2018/05/17 Javascript
vue中vee validate表单校验的几种基本使用
2018/06/25 Javascript
浅谈Vue.js组件(二)
2019/04/09 Javascript
记录vue做微信自定义分享的一些问题
2019/09/12 Javascript
浅谈v-for 和 v-if 并用时筛选条件方法
2019/11/07 Javascript
Python使用sorted排序的方法小结
2017/07/28 Python
python进阶_浅谈面向对象进阶
2017/08/17 Python
Sanic框架应用部署方法详解
2018/07/18 Python
Pyqt5实现英文学习词典
2019/06/24 Python
python 使用plt画图,去除图片四周的白边方法
2019/07/09 Python
Python字节单位转换实例
2019/12/05 Python
python使用turtle库绘制奥运五环
2020/02/24 Python
Python函数递归调用实现原理实例解析
2020/08/11 Python
CSS3实现的炫酷菜单代码分享
2015/03/12 HTML / CSS
Html5写一个简单的俄罗斯方块小游戏
2019/12/03 HTML / CSS
美国最大的团购网站:Groupon
2016/07/23 全球购物
受外贸欢迎的美国主机:BlueHost
2017/05/16 全球购物
结婚邀请函范文
2014/01/14 职场文书
委托书范本
2014/04/02 职场文书
保护黄河倡议书
2014/05/16 职场文书
协商一致解除劳动合同协议书
2014/09/14 职场文书
2014学习十八届四中全会精神思想汇报范文
2014/10/23 职场文书
五好家庭申报材料
2014/12/20 职场文书
PL350与SW11的比较
2021/04/22 无线电
聊聊基于pytorch实现Resnet对本地数据集的训练问题
2022/03/25 Python
git中cherry-pick命令的使用教程
2022/06/25 Servers