原生js写一个2048游戏

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了原生js写一个2048游戏相关的知识,希望对你有一定的参考价值。

本例逻辑
1,一个二维数组,记录数字方块的数值与对应dom对象
2, 一个一维数组,记录空白方块的坐标(行与列)
3,左移,最左边一列不做移动测试,从左边倒数第二列开始依次向左边做移动测试,若可合并,则向左移,数字不变或乘2.其他方向同逻辑
4, 判断输赢,若某个方块的值达到2048,即赢,游戏可以继续。当空白坐标数组的长度为0是,依次检测每个方块在四个方向可否移动,若都不能,即游戏结束。

→ → → → 预览 ← ← ← ←

js代码:

/*game 2048*/
//事件处理对象
var EventUtil={
  //添加事件
  addHandler:function(element,type,handler){
    if(element.addEventListener){
      element.addEventListener(type,handler,false);
    }else if(element.attachEvent){
      element.attachEvent("on"+type,handler);
    }else{
      element["on"+type]=handler;
    }
  },
  //获取事件对象
  getEvent:function(event){
    return event?event:window.event;//兼容ie
  }
}
function Game(tileContainer,scoreEle,bestScoreEle){
  this.tileContainer=tileContainer;
  this.scoreEle=scoreEle;
  this.bestScoreEle=bestScoreEle;
  this.tiles=new Array(4);//创建存方块数值与dom对象的数组
}
Game.prototype={
  //初始化游戏
  init:function(){
    this.posArray=[];//创建存空白方块坐标的数组
    for(var i=0,len=this.tiles.length;i<len;i++){
      this.tiles[i]=[];
      for(var j=0;j<len;j++){
        this.tiles[i][j]={num:0}; //初始化存方块数值与dom对象的数组
        this.posArray.push({"x":i,"y":j});//初始化存方块坐标的数组
      }
    }
    this.deleteTile(true);//清空全部方块
    this.score=0;//初始化分数
    this.bestScore=this.bestScore||0;//初始化最佳分数,第一次为0
    this.newTile();//随机创建一个方块
    this.newTile();
  },
  //创建一个方块
  newTile:function(){
    var tile=document.createElement("div"),
        pos=this.randomPos(),//随机新方块位置
        num=Math.random()<0.9?2:4;//随机新方块数值2或4
    this.tiles[pos.x][pos.y]={num:num,tile:tile};//将新方块的数值与dom对象存入数组
    this.setTile(tile,num,pos.x,pos.y);//设置方块属性产生移动与淡入效果
    this.tileContainer.appendChild(tile);
  },
  //设置方块class和显示的数字,
  setTile:function(element,num,x,y){
    element.innerhtml=num;
    element.className="tile tile-"+num+" tile-pos-"+x+"-"+y;
  },
  //随机一方块的位置
  randomPos:function(){
    var index=Math.floor(Math.random()*this.posArray.length);
    var pos=this.posArray[index];
    this.posArray.splice(index,1);//将新方块的位置从存空白坐标的数组中删除
    return pos;
  },
  //方块移动处理
  moveTile:function(keyCode){
    var len=this.tiles.length,
        merge;//存合并状态
    switch(keyCode){
      //左移
      case 37:
        for(var i=1;i<len;i++){
          for(var j=0;j<len;j++){
            if(this.tiles[i][j].num!=0&&this.leftMove(i,j)){//值不为0且可移动
              merge=this.merge(i,j);//合并
            }
          }
        }
        break;
      //右移
      case 39:
        for(var i=len-2;i>=0;i--){
          for(var j=0;j<len;j++){
            if(this.tiles[i][j].num!=0&&this.rightMove(i,j)){
              merge=this.merge(i,j);
            }
          }
        }
        break;
      //上移
      case 38:
        for(var i=0;i<len;i++){
          for(var j=1;j<len;j++){
            if(this.tiles[i][j].num!=0&&this.upMove(i,j)){
              merge=this.merge(i,j);
            }
          }
        }
        break;
      //下移
      case 40:
        for(var i=0;i<len;i++){
          for(var j=len-2;j>=0;j--){
            if(this.tiles[i][j].num!=0&&this.downMove(i,j)){
              merge=this.merge(i,j);
            }
          }
        }
        break;
    }
    if(merge){
      this.newTile();//合并之后创建一个方块  
    }else if(this.posArray.length==0&&this.gameOverTest()){//当存空白位置的数组为空且没有一个方向可移动,游戏结束
      this.gameOver();
    }
  },
  //方块左移动
  leftMove:function(i,j){
    this.num=this.tiles[i][j].num;
    this.moveI=undefined;
    this.moveJ=undefined;
    for(var n=i-1;n>=0;n--){
      if(this.tiles[n][j].num==0){
        this.moveI=n;
      }else if(this.tiles[n][j].num==this.num){
        this.num*=2;
        this.moveI=n;
        if(this.num==2048){
          this.gameWin();
        }
        this.getScore(this.num);
        break;
      }else{
        break;
      }
    }
    this.moveJ=j;
    if(!(this.moveI+1)||!(this.moveJ+1)){
      return;
    }
    return true;
  },
  //方块右移动
  rightMove:function(i,j){
    var len=this.tiles.length;
    this.num=this.tiles[i][j].num;
    this.moveI=undefined;
    this.moveJ=undefined;
    for(var n=i+1;n<len;n++){
      if(this.tiles[n][j].num==0){
        this.moveI=n;
      }else if(this.tiles[n][j].num==this.num){
        this.num*=2;
        this.moveI=n;
        if(this.num==2048){
          this.gameWin();
        }
        this.getScore(this.num);
        break;
      }else{
        break;
      }
    }
    this.moveJ=j;
    if(!(this.moveI+1)||!(this.moveJ+1)){
      return;
    }
    return true;
  },
  //方块上移动
  upMove:function(i,j){
    this.num=this.tiles[i][j].num;
    this.moveI=undefined;
    this.moveJ=undefined;
    for(var n=j-1;n>=0;n--){
      if(this.tiles[i][n].num==0){
        this.moveJ=n;
      }else if(this.tiles[i][n].num==this.num){
        this.moveJ=n;
        this.num*=2;
        if(this.num==2048){
          this.gameWin();
        }
        this.getScore(this.num);
        break;
      }else{
        break;
      }
    }
    this.moveI=i;
    if(!(this.moveI+1)||!(this.moveJ+1)){
      return;
    }
    return true;
  },
  //方块下移动
  downMove:function(i,j){
    var len=this.tiles.length;
    this.num=this.tiles[i][j].num;
    this.moveI=undefined;
    this.moveJ=undefined;
    for(var n=j+1;n<len;n++){
      if(this.tiles[i][n].num==0){
        this.moveJ=n;
      }else if(this.tiles[i][n].num==this.num){
        this.moveJ=n;
        this.num*=2;
        if(this.num==2048){
          this.gameWin();
        }
        this.getScore(this.num);
        break;
      }else{
        break;
      }
    }
    this.moveI=i;
    if(!(this.moveI+1)||!(this.moveJ+1)){
      return;
    }
    return true;
  },
  //合并方块
  merge:function(i,j){
    var me=this;
    if(this.num>this.tiles[i][j].num){
      //this.num的值变化,即遇到相同值的方块,可移动到其位置,只需删除被覆盖的方块
      this.deleteTile(false,this.tiles[this.moveI][this.moveJ].tile);
      //将移到相同值的方块的位置上的方块的原始位置添加到存空白坐标的数组中
      this.posArray.push({x:i,y:j});
    }else if(this.num==this.tiles[i][j].num){
      //值未变化,即遇到空白方块。只需将空白数组中该空白方块的坐标改为移动的方块的原始坐标
      this.posArray.forEach(function(item){
        if(item.x==me.moveI&&item.y==me.moveJ){
          item.x=i;
          item.y=j;
        }
      });
    }
    //设置将移动的方块的属性,产生移动效果
    this.setTile(this.tiles[i][j].tile,this.num,this.moveI,this.moveJ);
    //在存方块数值与dom对象的数组中将移动的方块的值设为空白值(即num:0),被覆盖的方块的值设为将移动的方块的值
    this.tiles[this.moveI][this.moveJ]={num:this.num,tile:this.tiles[i][j].tile};
    this.tiles[i][j]={num:0};
    return true;
  },
  //删除dom节点
  deleteTile:function(all,tile){
    if(all){
      this.tileContainer.innerHTML="";//清空所有
    }else{
      this.tileContainer.removeChild(tile);//删除单个
    }
  },
  //得分计算
  getScore:function(score){
    this.score+=score;
    this.scoreEle.innerHTML=this.score;
    if(this.score>this.bestScore){
      this.bestScore=this.score//当前分数大于最佳分数,覆盖最佳分数
      this.bestScoreEle.innerHTML=this.bestScore;
    }
  },
  //当出现2048即win,可继续挑战
  gameWin:function(){
    var me=this;
        win=document.createElement("div"),
        continueBtn=document.createElement("button");
    continueBtn.className="game-win-again";
    win.className="game-win";
    win.appendChild(continueBtn);
    this.tileContainer.appendChild(win);
    EventUtil.addHandler(continueBtn,"click",function(){
      me.deleteTile(false,win);
    });
  },
  //游戏结束测试
  gameOverTest:function(){
    var len=this.tiles.length;
    for(var i=0;i<len;i++){
      for(var j=0;j<len;j++){
        if(this.leftMove(i,j)||this.rightMove(i,j)||this.upMove(i,j)||this.downMove(i,j)){
          return;//只要有一个方向可移动即退出
        }
      }
    }
    return true;//没有一个方向可移动即游戏结束
  },
  //游戏结束消息
  gameOver:function(){
    var message=document.createElement("div");
    message.className="game-over";
    this.tileContainer.appendChild(message);
  },
  //添加事件处理程序
  initEvent:function(){
    var me=this;
    //添加键盘弹起事件,限制一直按下重复触发
    EventUtil.addHandler(window,"keyup",function(event){
      me.moveTile(EventUtil.getEvent(event).keyCode);
    });
  },
  //用于移动端,判断toustart的开始坐标是否在游戏区域gameContainer内
  touchPosTest:function(startX,startY){
    var container=document.getElementById("container"),
    gameContainer=document.getElementById("game-container");
    //container与gameContainer宽度一致,即gameContainer的offsetLeft是其已定位父元素container的offsetLeft
    var gameContainerStartX=container.offsetLeft,
        gameContainerStartY=container.offsetTop+gameContainer.offsetTop,
        gameContainerEndX=gameContainerStartX+gameContainer.offsetWidth,
        gameContainerEndY=gameContainerStartY+gameContainer.offsetHeight;
    return (startX>=gameContainerStartX&&startX<=gameContainerEndX)&&(startY>=gameContainerStartY&&startY<=gameContainerEndY)?true:false;
  },
  //移动端滑动
  slidMove:function(startX,startY,endX,endY){
    var dx=endX-startX,
        dy=endY-startY;
    var deg=Math.atan2(dy,dx)*180/Math.PI;//反正切值求滑动角度
    if(deg>=-45&&deg<=45){//
      this.moveTile(39);
    }else if(deg<135&&deg>45){//
      this.moveTile(40);
    }else if((deg>=135&&deg<=180)||(deg<=-135&&deg>=-180)){//
      this.moveTile(37);
    }else if(deg>-135&&deg<-45){//
      this.moveTile(38);
    }
  },
};
window.onload=function(){
  var btn=document.getElementById("newGame"),
      tileContainer=document.getElementById("tile-container"),
      scoreEle=document.getElementById("game-score"),
      bestScoreEle=document.getElementById("game-best-score"),
      startX,startY,endX,endY;
  var game=game||new Game(tileContainer,scoreEle,bestScoreEle);
  game.initEvent();//初始化事件处理
  game.init();//初始化游戏
  EventUtil.addHandler(btn,"click",function(){
    game.init();//newgame按钮被点击,初始化游戏,最佳分数保留直至刷新页面
  });
 //移动端触摸开始事件 EventUtil.addHandler(document,
"touchstart",function(event){ event.preventDefault(); startX=event.touches[0].clientX; startY=event.touches[0].clientY; });
//移动端触摸滑动事件 EventUtil.addHandler(document,
"touchend",function(event){ event.preventDefault(); endX=event.changedTouches[0].clientX; endY=event.changedTouches[0].clientY; //只有toustart的开始坐标在游戏区域gameContainer内才出发方块四个方向滑动 if(game.touchPosTest(startX,startY)){ game.slidMove(startX,startY,endX,endY); } }); }

 

html代码:

 1 <!DOCTYPE html>
 2 <html lang="en">
 3 <head>
 4   <meta charset="UTF-8">
 5   <meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=0">
 6   <link rel="stylesheet" type="text/css" href="style/style.css">
 7   <title>2048</title>
 8 </head>
 9 <body>
10   <div class="container" id="container">
11     <div class="header">
12       <h1 class="game-title">2048</h1>
13       <div class="game-info">
14         <span id="game-best-score">0</span>
15         <span id="game-score">0</span>
16         <button id="newGame" type="button">New Game</button>
17       </div>
18     </div>
19     <div class="game-container" id="game-container">
20       <div class="game-result">
21         <p></p>
22       </div>
23       <div class="gird-container">
24         <div class="gird-row">
25           <div class="gird-col"></div>
26           <div class="gird-col"></div>
27           <div class="gird-col"></div>
28           <div class="gird-col"></div>
29         </div>
30         <div class="gird-row">
31           <div class="gird-col"></div>
32           <div class="gird-col"></div>
33           <div class="gird-col"></div>
34           <div class="gird-col"></div>
35         </div>
36         <div class="gird-row">
37           <div class="gird-col"></div>
38           <div class="gird-col"></div>
39           <div class="gird-col"></div>
40           <div class="gird-col"></div>
41         </div>
42         <div class="gird-row">
43           <div class="gird-col"></div>
44           <div class="gird-col"></div>
45           <div class="gird-col"></div>
46           <div class="gird-col"></div>
47         </div>
48       </div>
49       <div class="tile-container" id="tile-container">
50        
51       </div>
52     </div>
53   </div>
54   <script type="text/javascript" src="js/main.js"></script>
55 </body>
56 </html>

css代码:

技术分享
  1 * {
  2   margin: 0;
  3   padding: 0;
  4 }
  5 .container {
  6   width: 500px;
  7   height: 640px;
  8   position: absolute;
  9   top: 0;
 10   left: 0;
 11   right: 0;
 12   bottom: 0;
 13   margin: auto;
 14   font-family: "微软雅黑";
 15 }
 16 .header {
 17   height: 120px;
 18   margin-bottom: 20px;
 19 }
 20 .game-title {
 21   font-size: 50px;
 22   color: #776e65;
 23   text-align: center;
 24   margin-bottom: 10px;
 25 }
 26 .game-info {
 27   height: 40px;
 28 }
 29 #game-score,
 30 #game-best-score {
 31   height: 100%;
 32   float: left;
 33   min-width: 65px;
 34   background-color: #bbada0;
 35   color: #fff;
 36   font-size: 18px;
 37   border-radius: 5px;
 38   text-align: center;
 39   line-height: 58px;
 40   position: relative;
 41 }
 42 #game-score:after {
 43   content: "Score";
 44   position: absolute;
 45   width: 100%;
 46   left: 0;
 47   top: -21px;
 48   text-align: center;
 49   color: #e9dfd4;
 50   font-size: 13px;
 51 }
 52 #game-best-score {
 53   margin-right: 15px;
 54 }
 55 #game-best-score:after {
 56   content: "Best";
 57   position: absolute;
 58   width: 100%;
 59   left: 0;
 60   top: -21px;
 61   text-align: center;
 62   color: #e9dfd4;
 63   font-size: 13px;
 64 }
 65 #newGame {
 66   height: 100%;
 67   width: 100px;
 68   float: right;
 69   border-radius: 5px;
 70   background-color: #8f7a66;
 71   border: none;
 72   box-shadow: none;
 73   color: #fff;
 74   font-size: 16px;
 75   cursor: pointer;
 76 }
 77 #newGame:focus {
 78   outline: none;
 79 }
 80 .game-container {
 81   width: 500px;
 82   height: 500px;
 83   position: relative;
 84   background-color: #bbada0;
 85   padding: 15px;
 86   border-radius: 5px;
 87   box-sizing: border-box;
 88   -moz-box-sizing: border-box;
 89   /* Firefox */
 90   -webkit-box-sizing: border-box;
 91   /* Safari */
 92 }
 93 .gird-container {
 94   width: 470px;
 95   height: 470px;
 96 }
 97 .gird-row {
 98   width: 470px;
 99   height: 106.25px;
100   margin-bottom: 15px;
101   clear: both;
102 }
103 .gird-row:last-child {
104   margin-bottom: 0;
105 }
106 .gird-col {
107   width: 106.25px;
108   height: 106.25px;
109   margin-right: 15px;
110   background-color: #cdc1b4;
111   float: left;
112 }
113 .gird-col:last-child {
114   margin-right: 0;
115 }
116 .tile-container {
117   color: #f9f6f2;
118   width: 470px;
119   height: 470px;
120   position: absolute;
121   top: 15px;
122 }
123 .game-over {
124   position: absolute;
125   top: 0;
126   bottom: 0;
127   left: 0;
128   right: 0;
129   z-index: 10;
130   background-color: rgba(204, 204, 204, 0.5);
131 }
132 .game-over:after {
133   content: "Game Over";
134   font-size: 60px;
135   color: #fff;
136   position: absolute;
137   top: 0;
138   bottom: 0;
139   left: 0;
140   right: 0;
141   height: 70px;
142   margin: auto;
143   text-align: center;
144 }
145 .game-win {
146   position: absolute;
147   top: 0;
148   bottom: 0;
149   left: 0;
150   right: 0;
151   z-index: 10;
152   background-color: rgba(204, 204, 204, 0.5);
153 }
154 .game-win:after {
155   content: "You Win";
156   font-size: 60px;
157   color: #fff;
158   position: absolute;
159   top: 0;
160   bottom: 0;
161   left: 0;
162   right: 0;
163   height: 70px;
164   margin: auto;
165   text-align: center;
166 }
167 .game-win-again {
168   width: 160px;
169   height: 50px;
170   border-radius: 5px;
171   background-color: #8f7a66;
172   border: none;
173   box-shadow: none;
174   color: #fff;
175   cursor: pointer;
176   position: absolute;
177   bottom: 120px;
178   left: 0;
179   right: 0;
180   margin: auto;
181   font-size: 30px;
182 }
183 .game-win-again:after {
184   content: "Continue";
185 }
186 .tile {
187   position: absolute;
188   width: 106.25px;
189   height: 106.25px;
190   text-align: center;
191   line-height: 106.25px;
192   font-size: 50px;
193   top: 0;
194   transition: transform 150ms ease-out;
195   -moz-transition: transform 150ms ease-out;
196   /* Firefox 4 */
197   -webkit-transition: transform 150ms ease-out;
198   /* Safari 和 Chrome */
199   -o-transition: transform 150ms ease-out;
200   /* Opera */
201   animation: tiledisplay 300ms 1;
202   -webkit-animation: tiledisplay 300ms 1;
203   /* Safari 和 Chrome */
204 }
205 @keyframes tiledisplay {
206   0% {
207     opacity: 0;
208     filter: alpha(opacity=0);
209   }
210   50% {
211     opacity: 0;
212     filter: alpha(opacity=0);
213   }
214   100% {
215     opacity: 1;
216     filter: alpha(opacity=100);
217   }
218 }
219 @-webkit-keyframes tiledisplay
220 /* Safari and Chrome */
221 
222 {
223   0% {
224     opacity: 0;
225     filter: alpha(opacity=0);
226   }
227   50% {
228     opacity: 0;
229     filter: alpha(opacity=0);
230   }
231   100% {
232     opacity: 1;
233     filter: alpha(opacity=100);
234   }
235 }
236 
237 .tile-container .tile-2 {
238   color: #776e65;
239   background: #eee4da;
240 }
241 .tile-container .tile-4 {
242   color: #776e65;
243   background: #ede0c8;
244 }
245 .tile-container .tile-8 {
246   background: #f2b179;
247 }
248 .tile-container .tile-16 {
249   background: #f59563;
250 }
251 .tile-container .tile-32 {
252   background: #f67c5f;
253 }
254 .tile-container .tile-64 {
255   background: #f65e3b;
256 }
257 .tile-container .tile-128 {
258   background: #edcf72;
259 }
260 .tile-container .tile-256 {
261   background: #edcc61;
262 }
263 .tile-container .tile-512 {
264   background: #edc850;
265 }
266 .tile-container .tile-1024 {
267   background: #edc53f;
268 }
269 .tile-container .tile-2048 {
270   background: #edc22e;
271 }
272 .tile-container .tile-pos-0-0 {
273   -webkit-transform: translate(0, 0);
274   -ms-transform: translate(0, 0);
275   -o-transform: translate(0, 0);
276   transform: translate(0, 0);
277 }
278 
279 .tile-container .tile-pos-0-1 {
280   -webkit-transform: translate(0, 121.25px);
281   -ms-transform: translate(0, 121.25px);
282   -o-transform: translate(0, 121.25px);
283   transform: translate(0, 121.25px);
284 }
285 
286 .tile-container .tile-pos-0-2 {
287   -webkit-transform: translate(0, 242.5px);
288   -ms-transform: translate(0, 242.5px);
289   -o-transform: translate(0, 242.5px);
290   transform: translate(0, 242.5px);
291 }
292 
293 .tile-container .tile-pos-0-3 {
294   -webkit-transform: translate(0, 363.75px);
295   -ms-transform: translate(0, 363.75px);
296   -o-transform: translate(0, 363.75px);
297   transform: translate(0, 363.75px);
298 }
299 
300 .tile-container .tile-pos-1-0 {
301   -webkit-transform: translate(121.25px, 0);
302   -ms-transform: translate(121.25px, 0);
303   -o-transform: translate(121.25px, 0);
304   transform: translate(121.25px, 0);
305 }
306 
307 .tile-container .tile-pos-1-1 {
308   -webkit-transform: translate(121.25px, 121.25px);
309   -ms-transform: translate(121.25px, 121.25px);
310   -o-transform: translate(121.25px, 121.25px);
311   transform: translate(121.25px, 121.25px);
312 }
313 
314 .tile-container .tile-pos-1-2 {
315   -webkit-transform: translate(121.25px, 242.5px);
316   -ms-transform: translate(121.25px, 242.5px);
317   -o-transform: translate(121.25px, 242.5px);
318   transform: translate(121.25px, 242.5px);
319 }
320 
321 .tile-container .tile-pos-1-3 {
322   -webkit-transform: translate(121.25px, 363.75px);
323   -ms-transform: translate(121.25px, 363.75px);
324   -o-transform: translate(121.25px, 363.75px);
325   transform: translate(121.25px, 363.75px);
326 }
327 
328 .tile-container .tile-pos-2-0 {
329   -webkit-transform: translate(242.5px, 0);
330   -ms-transform: translate(242.5px, 0);
331   -o-transform: translate(242.5px, 0);
332   transform: translate(242.5px, 0);
333 }
334 
335 .tile-container .tile-pos-2-1 {
336   -webkit-transform: translate(242.5px, 121.25px);
337   -ms-transform: translate(242.5px, 121.25px);
338   -o-transform: translate(242.5px, 121.25px);
339   transform: translate(242.5px, 121.25px);
340 }
341 
342 .tile-container .tile-pos-2-2 {
343   -webkit-transform: translate(242.5px, 242.5px);
344   -ms-transform: translate(242.5px, 242.5px);
345   -o-transform: translate(242.5px, 242.5px);
346   transform: translate(242.5px, 242.5px);
347 }
348 
349 .tile-container .tile-pos-2-3 {
350   -webkit-transform: translate(242.5px, 363.75px);
351   -ms-transform: translate(242.5px, 363.75px);
352   -o-transform: translate(242.5px, 363.75px);
353   transform: translate(242.5px, 363.75px);
354 }
355 
356 .tile-container .tile-pos-3-0 {
357   -webkit-transform: translate(363.75px, 0);
358   -ms-transform: translate(363.75px, 0);
359   -o-transform: translate(363.75px, 0);
360   transform: translate(363.75px, 0);
361 }
362 
363 .tile-container .tile-pos-3-1 {
364   -webkit-transform: translate(363.75px, 121.25px);
365   -ms-transform: translate(363.75px, 121.25px);
366   -o-transform: translate(363.75px, 121.25px);
367   transform: translate(363.75px, 121.25px);
368 }
369 
370 .tile-container .tile-pos-3-2 {
371   -webkit-transform: translate(363.75px, 242.5px);
372   -ms-transform: translate(363.75px, 242.5px);
373   -o-transform: translate(363.75px, 242.5px);
374   transform: translate(363.75px, 242.5px);
375 }
376 
377 .tile-container .tile-pos-3-3 {
378   -webkit-transform: translate(363.75px, 363.75px);
379   -ms-transform: translate(363.75px, 363.75px);
380   -o-transform: translate(363.75px, 363.75px);
381   transform: translate(363.75px, 363.75px);
382 }
383 @media screen and (max-width: 525px) {
384 .container {
385   width: 280px;
386   height: 405px;
387 }
388 .header {
389   height: 110px;
390   margin-bottom: 15px;
391 }
392 .game-info {
393   height: 40px;
394 }
395 .game-title {
396   font-size: 50px;
397 }
398 .game-container {
399   width: 280px;
400   height: 280px;
401   padding: 7px;
402 }
403 .gird-container {
404   width: 266px;
405   height: 266px;
406 }
407 .gird-row {
408   width: 266px;
409   height: 61.25px;
410   margin-bottom: 7px;
411 }
412 .gird-col {
413   width: 61.25px;
414   height: 61.25px;
415   margin-right: 7px;
416 }
417 .tile-container {
418   width: 266px;
419   height: 266px;
420   top: 7px;
421 }
422 .game-over:after {
423   font-size:40px;
424   height: 70px;
425 }
426 .game-win:after {
427   font-size: 45px;
428   height: 60px;
429 }
430 .game-win-again {
431   width: 130px;
432   height: 40px;
433   bottom: 60px;
434   font-size: 25px;
435 }
436 .game-win-again:after {
437   content: "Continue";
438 }
439 .tile {
440   width: 61.25px;
441   height: 61.25px;
442   line-height: 61.25px;
443   font-size: 35px;
444 }
445 .tile-container .tile-pos-0-1 {
446   -webkit-transform: translate(0, 68.25px);
447   -ms-transform: translate(0, 68.25px);
448   -o-transform: translate(0, 68.25px);
449   transform: translate(0, 68.25px);
450 }
451 
452 .tile-container .tile-pos-0-2 {
453   -webkit-transform: translate(0, 136.5px);
454   -ms-transform: translate(0, 136.5px);
455   -o-transform: translate(0, 136.5px);
456   transform: translate(0, 136.5px);
457 }
458 
459 .tile-container .tile-pos-0-3 {
460   -webkit-transform: translate(0, 204.75px);
461   -ms-transform: translate(0, 204.75px);
462   -o-transform: translate(0, 204.75px);
463   transform: translate(0, 204.75px);
464 }
465 
466 .tile-container .tile-pos-1-0 {
467   -webkit-transform: translate(68.25px, 0);
468   -ms-transform: translate(68.25px, 0);
469   -o-transform: translate(68.25px, 0);
470   transform: translate(68.25px, 0);
471 }
472 
473 .tile-container .tile-pos-1-1 {
474   -webkit-transform: translate(68.25px, 68.25px);
475   -ms-transform: translate(68.25px, 68.25px);
476   -o-transform: translate(68.25px, 68.25px);
477   transform: translate(68.25px, 68.25px);
478 }
479 
480 .tile-container .tile-pos-1-2 {
481   -webkit-transform: translate(68.25px, 136.5px);
482   -ms-transform: translate(68.25px, 136.5px);
483   -o-transform: translate(68.25px, 136.5px);
484   transform: translate(68.25px, 136.5px);
485 }
486 
487 .tile-container .tile-pos-1-3 {
488   -webkit-transform: translate(68.25px, 204.75px);
489   -ms-transform: translate(68.25px, 204.75px);
490   -o-transform: translate(68.25px, 204.75px);
491   transform: translate(68.25px, 204.75px);
492 }
493 
494 .tile-container .tile-pos-2-0 {
495   -webkit-transform: translate(136.5px, 0);
496   -ms-transform: translate(136.5px, 0);
497   -o-transform: translate(136.5px, 0);
498   transform: translate(136.5px, 0);
499 }
500 
501 .tile-container .tile-pos-2-1 {
502   -webkit-transform: translate(136.5px, 68.25px);
503   -ms-transform: translate(136.5px, 68.25px);
504   -o-transform: translate(136.5px, 68.25px);
505   transform: translate(136.5px, 68.25px);
506 }
507 
508 .tile-container .tile-pos-2-2 {
509   -webkit-transform: translate(136.5px, 136.5px);
510   -ms-transform: translate(136.5px, 136.5px);
511   -o-transform: translate(136.5px, 136.5px);
512   transform: translate(136.5px, 136.5px);
513 }
514 
515 .tile-container .tile-pos-2-3 {
516   -webkit-transform: translate(136.5px, 204.75px);
517   -ms-transform: translate(136.5px, 204.75px);
518   -o-transform: translate(136.5px, 204.75px);
519   transform: translate(136.5px, 204.75px);
520 }
521 
522 .tile-container .tile-pos-3-0 {
523   -webkit-transform: translate(204.75px, 0);
524   -ms-transform: translate(204.75px, 0);
525   -o-transform: translate(204.75px, 0);
526   transform: translate(204.75px, 0);
527 }
528 
529 .tile-container .tile-pos-3-1 {
530   -webkit-transform: translate(204.75px, 68.25px);
531   -ms-transform: translate(204.75px, 68.25px);
532   -o-transform: translate(204.75px, 68.25px);
533   transform: translate(204.75px, 68.25px);
534 }
535 
536 .tile-container .tile-pos-3-2 {
537   -webkit-transform: translate(204.75px, 136.5px);
538   -ms-transform: translate(204.75px, 136.5px);
539   -o-transform: translate(204.75px, 136.5px);
540   transform: translate(204.75px, 136.5px);
541 }
542 
543 .tile-container .tile-pos-3-3 {
544   -webkit-transform: translate(204.75px, 204.75px);
545   -ms-transform: translate(204.75px, 204.75px);
546   -o-transform: translate(204.75px, 204.75px);
547   transform: translate(204.75px, 204.75px);
548 }
549 }
View Code

 







以上是关于原生js写一个2048游戏的主要内容,如果未能解决你的问题,请参考以下文章

用原生js写2048小游戏

用原生js写2048小游戏

js写2048游戏代码

2048小游戏——CSS/原生js爬坑之纯CSS模态对话框&游戏结束

纯JS写的2048游戏,分享之

原生js的2048的制作过程