使用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 相关文章推荐
检测是否已安装 .NET Framework 3.5的js脚本
Feb 14 Javascript
深入认识javascript中的eval函数
Nov 02 Javascript
使用JQuery进行跨域请求
Jan 25 Javascript
JavaScript高级程序设计(第3版)学习笔记12 js正则表达式
Oct 11 Javascript
ExtJs纵坐标值重复问题的解决方法
Feb 27 Javascript
基于jQuery实现下拉框
Nov 24 Javascript
使用jquery制作弹出框效果
Apr 03 Javascript
vue添加axios,并且指定baseurl的方法
Sep 19 Javascript
vue实现双向绑定和依赖收集遇到的坑
Nov 29 Javascript
vue实现手机端省市区区域选择
Sep 27 Javascript
jQuery实现全选、反选和不选功能的方法详解
Dec 04 jQuery
JavaScript中的this原理及6种常见使用场景详解
Feb 14 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 preg_match_all结合str_replace替换内容中所有img
2008/10/11 PHP
PHP如何解决网站大流量与高并发的问题
2011/06/25 PHP
PHP常用技巧总结(附函数代码)
2012/02/04 PHP
PDO防注入原理分析以及注意事项
2015/02/25 PHP
PHP实现过滤掉非汉字字符只保留中文字符
2015/06/04 PHP
PHP Redis扩展无法加载的问题解决方法
2019/08/22 PHP
javascript URL编码和解码使用说明
2010/04/12 Javascript
javascript针对DOM的应用分析(四)
2012/04/15 Javascript
关于页面嵌入swf覆盖div层的问题的解决方法
2014/02/11 Javascript
JavaScript整除运算函数ceil和floor的区别分析
2015/04/14 Javascript
浅谈NodeJS中require路径问题
2015/05/07 NodeJs
详解javascript实现瀑布流列式布局
2016/01/29 Javascript
怎么限制input的text里输入的值只能是数字(正则、js)
2016/05/16 Javascript
微信小程序 location API接口详解及实例代码
2016/10/12 Javascript
浅谈jquery拼接字符串效率比较高的方法
2017/02/22 Javascript
Vue Ajax跨域请求实例详解
2017/06/20 Javascript
angularjs2 ng2 密码隐藏显示的实例代码
2017/08/01 Javascript
详解基于node的前端项目编译时内存溢出问题
2017/08/01 Javascript
React Native 通告消息竖向轮播组件的封装
2020/08/25 Javascript
vue 属性拦截实现双向绑定的实例代码
2018/10/24 Javascript
浅析Proxy可以优化vue的数据监听机制问题及实现思路
2018/11/29 Javascript
jQuery内容过滤选择器与子元素过滤选择器用法实例分析
2019/02/20 jQuery
vue实现todolist功能、todolist组件拆分及todolist的删除功能
2019/04/11 Javascript
javascript中的闭包概念与用法实践分析
2019/07/26 Javascript
python获取目录下所有文件的方法
2015/06/01 Python
Scrapy的简单使用教程
2017/10/24 Python
使用Django和Python创建Json response的方法
2018/03/26 Python
浅析Python 实现一个自动化翻译和替换的工具
2019/04/14 Python
python使用paramiko模块通过ssh2协议对交换机进行配置的方法
2019/07/25 Python
完美解决keras保存好的model不能成功加载问题
2020/06/11 Python
使用HTML5进行SVG矢量图形绘制的入门教程
2016/02/19 HTML / CSS
全球酒店比价网:HotelsCombined
2017/06/20 全球购物
Java程序开发中如何应用线程
2016/03/03 面试题
工程质量承诺书
2014/03/27 职场文书
2016年质量月活动总结报告
2016/04/05 职场文书
Python编解码问题及文本文件处理方法详解
2021/06/20 Python