使用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 相关文章推荐
List Information About the Binary Files Used by an Application
Jun 11 Javascript
5款JavaScript代码压缩工具推荐
Jul 07 Javascript
jQuery实现仿路边灯箱广告图片轮播效果
Apr 15 Javascript
jQuery实现的小图列表,大图展示效果幻灯片示例
Oct 25 Javascript
JS实现滑动门效果的方法详解
Dec 19 Javascript
基于JavaScript 性能优化技巧心得(分享)
Dec 11 Javascript
jQuery实现定时隐藏对话框的方法分析
Feb 12 jQuery
使用svg实现动态时钟效果
Jul 17 Javascript
Angular6 用户自定义标签开发的实现方法
Jan 08 Javascript
小程序如何获取多个formId实现详解
Sep 20 Javascript
如何使用JavaScript检测空闲的浏览器选项卡
May 28 Javascript
openlayers4实现点动态扩散
Aug 17 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
整理的9个实用的PHP库简介和下载
2010/11/09 PHP
php获取系统变量方法小结
2015/05/29 PHP
在Ubuntu 18.04上安装PHP 7.3 7.2和7.0的方法
2019/04/09 PHP
js 页面刷新location.reload和location.replace的区别小结
2009/12/24 Javascript
jquery获取特定name所有选中的checkbox,支持IE9标准模式
2013/03/18 Javascript
jquery showModelDialog的使用方法示例详解
2013/11/19 Javascript
JS控件ASP.NET的treeview控件全选或者取消(示例代码)
2013/12/16 Javascript
用js正确判断用户名cookie是否存在的方法
2014/01/28 Javascript
jQuery获取单选按钮radio选中值与去除所有radio选中状态的方法
2017/05/20 jQuery
js编写选项卡效果
2017/05/23 Javascript
Vue精简版风格指南(推荐)
2018/01/30 Javascript
Vue press 支持图片放大功能的实例代码
2018/11/09 Javascript
使用jQuery实现购物车
2020/10/29 jQuery
vue $router和$route的区别详解
2020/12/02 Vue.js
对于Python的Django框架使用的一些实用建议
2015/04/03 Python
Python自动化运维之IP地址处理模块详解
2017/12/10 Python
python matplotlib 注释文本箭头简单代码示例
2018/01/08 Python
python使用pandas实现数据分割实例代码
2018/01/25 Python
python实现五子棋小程序
2019/06/18 Python
Python测试模块doctest使用解析
2019/08/10 Python
Python3简单爬虫抓取网页图片代码实例
2019/08/26 Python
如何使用Python破解ZIP或RAR压缩文件密码
2020/01/09 Python
在Windows上安装和配置 Jupyter Lab 作为桌面级应用程序教程
2020/04/22 Python
ITK 实现多张图像转成单个nii.gz或mha文件案例
2020/07/01 Python
python小技巧——将变量保存在本地及读取
2020/11/13 Python
浅谈Html5多线程开发之WebWorkers
2018/05/02 HTML / CSS
汇集了世界上最好的天然和有机美容产品:LoveLula
2018/02/05 全球购物
英国计算机商店:Technextday
2019/12/28 全球购物
校友会欢迎辞
2014/01/13 职场文书
信息科学与技术专业求职信范文
2014/02/20 职场文书
党的群众路线教育实践活动领导班子整改措施
2014/09/30 职场文书
结婚保证书(三从四德)
2015/02/26 职场文书
2015秋学期开学寄语
2015/05/28 职场文书
职场新人刚入职工作总结该怎么写?
2019/05/15 职场文书
创业计划书之家教中心
2019/09/25 职场文书
C站最全Python标准库总结,你想要的都在这里
2021/07/03 Python