使用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 相关文章推荐
Angularjs中controller的三种写法分享
Sep 21 Javascript
常用JS图片滚动(无缝、平滑、上下左右滚动)代码大全(推荐)
Dec 20 Javascript
js 轮播效果实例分享
Dec 28 Javascript
基于JavaScript实现带缩略图的轮播效果
Jan 12 Javascript
JavaScript中英文字符长度统计方法示例【按照中文占2个字符】
Jan 17 Javascript
JS跨域请求外部服务器的资源
Feb 06 Javascript
JS简单判断滚动条的滚动方向实现方法
Apr 28 Javascript
浅谈js闭包理解
Mar 28 Javascript
理理Vue细节(推荐)
Apr 16 Javascript
使用 webpack 插件自动生成 vue 路由文件的方法
Aug 20 Javascript
JavaScript用document.write()输出换行的示例代码
Nov 26 Javascript
详解实现vue的数据响应式原理
Jan 20 Vue.js
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代码重构工具推荐
2014/10/14 PHP
php实现的通用图片处理类
2015/03/24 PHP
整理php防注入和XSS攻击通用过滤
2015/09/13 PHP
php查看一个变量的占用内存的实例代码
2020/03/29 PHP
JQGrid的用法解析(列编辑,添加行,删除行)
2013/11/08 Javascript
用js格式化金额可设置保留的小数位数
2014/05/09 Javascript
在JavaScript里防止事件函数高频触发和高频调用的方法
2014/09/06 Javascript
jQuery中val()方法用法实例
2014/12/25 Javascript
JSON相关知识汇总
2015/07/03 Javascript
使用requestAnimationFrame实现js动画性能好
2015/08/06 Javascript
深入分析jQuery的ready函数是如何工作的(工作原理)
2015/12/17 Javascript
浅谈javascript中的数据类型转换
2016/12/27 Javascript
微信小程序组件之srcoll-view的详解
2017/10/19 Javascript
简述Angular 5 快速入门
2017/11/04 Javascript
使用Angular9和TypeScript开发RPG游戏的方法
2020/03/25 Javascript
python读取word文档的方法
2015/05/09 Python
Python操作csv文件实例详解
2017/07/31 Python
Python基于回溯法子集树模板解决0-1背包问题实例
2017/09/02 Python
Python如何实现MySQL实例初始化详解
2017/11/06 Python
Python通过len函数返回对象长度
2020/10/22 Python
PyCharm Ctrl+Shift+F 失灵的简单有效解决操作
2021/01/15 Python
Python3自带工具2to3.py 转换 Python2.x 代码到Python3的操作
2021/03/03 Python
Lookfantastic德国官网:英国知名美妆购物网站
2017/06/11 全球购物
凯蒂·佩里个人女鞋品牌:Katy Perry Collections
2019/04/04 全球购物
巴黎欧莱雅法国官网:L’Oreal Paris
2019/04/30 全球购物
北京一家公司的.net开发工程师笔试题
2012/04/17 面试题
应聘护理专业毕业自荐书范文
2014/02/12 职场文书
12岁生日演讲稿
2014/05/14 职场文书
手术室护士节演讲稿
2014/08/27 职场文书
企业挂职心得体会
2014/09/10 职场文书
乡镇党员干部四风对照检查材料思想汇报
2014/09/27 职场文书
交通运输局四风问题对照检查材料思想汇报
2014/10/09 职场文书
JavaScript canvas实现流星特效
2021/05/20 Javascript
使用Nginx搭载rtmp直播服务器的方法
2021/10/16 Servers
俄罗斯十大城市人口排名,第三首都仅排第六,第二是北方首都
2022/03/20 杂记
Java中的Kafka为什么性能这么快及4大核心详析
2022/09/23 Java/Android