使用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 相关文章推荐
用javascript实现给出的盒子的序列是否可连为一矩型
Aug 30 Javascript
javascript开发随笔二 动态加载js和文件
Nov 25 Javascript
提交表单时执行func方法实现代码
Mar 17 Javascript
js实现快速分享功能(你的文章分享工具)
Jun 25 Javascript
js利用prototype调用Array的slice方法示例
Jun 09 Javascript
jQuery表单域属性过滤器用法分析
Feb 10 Javascript
jQuery实现表格行和列的动态添加与删除方法【测试可用】
Aug 01 Javascript
AngularJs Injecting Services Into Controllers详解
Sep 02 Javascript
详解vue组件中使用路由方法
Feb 12 Javascript
vue中使用v-model完成组件间的通信
Aug 22 Javascript
vue路由守卫及路由守卫无限循环问题详析
Sep 05 Javascript
JS+HTML实现自定义上传图片按钮并显示图片功能的方法分析
Feb 12 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教程 预定义变量
2009/10/23 PHP
PHP错误Allowed memory size of 67108864 bytes exhausted的3种解决办法
2014/07/28 PHP
利用“多说”制作留言板、评论系统
2015/07/14 PHP
使用图灵api创建微信聊天机器人
2015/07/23 PHP
纯php生成随机密码
2015/10/30 PHP
php抛出异常与捕捉特定类型的异常详解
2016/10/26 PHP
利用PHP获取汉字首字母并且分组排序详解
2017/10/22 PHP
PHP addslashes()函数讲解
2019/02/03 PHP
一些常用的JS功能函数(2009-06-04更新)
2009/06/04 Javascript
新浪微博字数统计 textarea字数统计实现代码
2011/08/28 Javascript
基于mootools插件实现遮罩层新手引导
2012/05/24 Javascript
这些年、我收集的JQuery代码小结
2012/08/01 Javascript
热点新闻滚动特效的js代码
2013/08/17 Javascript
显示今天的日期js代码(阳历和农历)
2014/09/30 Javascript
Javascript中拼接大量字符串的方法
2015/02/05 Javascript
jQuery 3.0十大新特性
2016/07/06 Javascript
两种简单的跨域方法(jsonp、php)
2017/01/02 Javascript
js实现图片放大展示效果
2017/08/30 Javascript
纯js实现画一棵树的示例
2017/09/05 Javascript
vue中的循环对象属性和属性值用法
2020/09/04 Javascript
python统计文本字符串里单词出现频率的方法
2015/05/26 Python
Flask解决跨域的问题示例代码
2018/02/12 Python
python3第三方爬虫库BeautifulSoup4安装教程
2018/06/19 Python
Python+pandas计算数据相关系数的实例
2018/07/03 Python
Python简单爬虫导出CSV文件的实例讲解
2018/07/06 Python
Python实现输入二叉树的先序和中序遍历,再输出后序遍历操作示例
2018/07/27 Python
使用Python来做一个屏幕录制工具的操作代码
2020/01/18 Python
找到不普通的东西:Bonanza
2016/10/20 全球购物
西班牙Polo衫品牌:Polo Club
2020/08/09 全球购物
有abstract方法的类一定要用abstract修饰吗
2016/03/14 面试题
简历中个人求职的自我评价模板
2013/11/29 职场文书
优秀高中生事迹材料
2014/02/11 职场文书
房屋租赁合同补充协议
2014/10/11 职场文书
2014年个人业务工作总结
2014/11/17 职场文书
邀请函模板
2015/02/02 职场文书
用几道面试题来看JavaScript执行机制
2021/04/30 Javascript