2048的制作

1、html部分

 1 <!doctype html>
 2 <html>
 3  <head>
 4   <meta charset="UTF-8">
 5   <title>Document</title>
 6   <link rel="stylesheet" href="2048.css"/>
 7   <script src="2048.js"></script>
 8  </head>
 9  <body>
10   <p>
11     Top:<span id="top">0</span><br>
12     Score:<span id="score">0</span>
13   </p>
14 <div id="gridPanel">
15   <!--背景格-->
16   <!--第一行-->
17     <div id="g00" class="grid"></div>
18     <div id="g01" class="grid"></div>
19     <div id="g02" class="grid"></div>
20     <div id="g03" class="grid"></div>
21   <!--第二行-->
22     <div id="g10" class="grid"></div>
23     <div id="g11" class="grid"></div>
24     <div id="g12" class="grid"></div>
25     <div id="g13" class="grid"></div>
26   <!--第三行-->
27     <div id="g20" class="grid"></div>
28     <div id="g21" class="grid"></div>
29     <div id="g22" class="grid"></div>
30     <div id="g23" class="grid"></div>
31   <!--第四行-->
32     <div id="g30" class="grid"></div>
33     <div id="g31" class="grid"></div>
34     <div id="g32" class="grid"></div>
35     <div id="g33" class="grid"></div>
36   <!--前景格-->
37   <!--第一行-->
38     <div id="c00" class="cell"></div>
39     <div id="c01" class="cell"></div>
40     <div id="c02" class="cell"></div>
41     <div id="c03" class="cell"></div>
42 
43     <div id="c10" class="cell"></div>
44     <div id="c11" class="cell"></div>
45     <div id="c12" class="cell"></div>
46     <div id="c13" class="cell"></div>
47 
48     <div id="c20" class="cell"></div>
49     <div id="c21" class="cell"></div>
50     <div id="c22" class="cell"></div>
51     <div id="c23" class="cell"></div>
52 
53     <div id="c30" class="cell"></div>
54     <div id="c31" class="cell"></div>
55     <div id="c32" class="cell"></div>
56     <div id="c33" class="cell"></div>
57 </div>
58   <div id="gameOver">
59     <div><!--半透明背景--></div>
60     <p><!--前景对话框-->
61       Game Over!<br>
62       Score:<span id="final">0</span><br>
63       <a class="btn" onclick="game.start()">Try again!</a>
64     </p>
65   </div>
66  </body>
67 </html>

2、css部分

 1 #gridPanel{
 2   width:480px; height:480px;
 3   margin:0 auto;
 4   background-color:#bbada0;
 5   border-radius:10px;
 6   position:relative;
 7 }
 8 .grid,.cell{
 9   width:100px; height:100px; border-radius:6px;
10 }
11 .grid{
12   background-color:#ccc0b3;
13   float:left;
14   margin-left:16px;
15   margin-top:16px;
16 }
17 .cell{ 
18   position:absolute; 
19   font-size:60px;
20     text-align:center;
21     line-height:100px;
22     color:#fff;
23 }
24 [id^="c0"]{top:16px;}
25 [id^="c1"]{top:132px;}
26 [id^="c2"]{top:248px;}
27 [id^="c3"]{top:364px;}
28 
29 .cell[id$="0"]{left:16px;}
30 .cell[id$="1"]{left:132px;}
31 .cell[id$="2"]{left:248px;}
32 .cell[id$="3"]{left:364px;}
33 
34 .n2{background-color:#eee3da}
35 .n4{background-color:#ede0c8}
36 .n8{background-color:#f2b179}
37 .n16{background-color:#f59563}
38 .n32{background-color:#f67c5f}
39 .n64{background-color:#f65e3b}
40 .n128{background-color:#edcf72}
41 .n256{background-color:#edcc61}
42 .n512{background-color:#9c0}
43 .n1024{background-color:#33b5e5}
44 .n2048{background-color:#09c}
45 .n4096{background-color:#a6c}
46 .n8192{background-color:#93c}
47 .n2,.n4{color:#776e65}
48 .n1024,.n2048,.n4096,.n8192{font-size:40px}
49 
50 p{
51   width:480px; margin:0 auto;
52   font-size:40px; font-family:Arial; font-weight:bold;
53   padding-top:15px;
54 }
55 #gameOver{display:none;
56   width:100%; height:100%;
57   position:absolute;
58   top:0; left:0;
59 }
60 #gameOver>div{
61   width:100%; height:100%;
62   background-color:#555; opacity:0.5;
63 }
64 #gameOver>p{
65   width:300px; height:200px;
67   position:absolute;
68   top:50%; left:50%;
69   margin-left:-150px; margin-top:-100px;
70 
71   background-color:#fff;
72   text-align:center;
73   line-height:1.5em;
74   border-radius:10px;
75   border:1px solid #edcf72;
76 }
77 .btn{
78   color:#fff; background-color:#9f8d77;
79   border-radius:6px; 
80   cursor:pointer;
81   padding:10px;
82 }

 

3、js部分

  1     function getCookie(cookieName){
  2         var str=document.cookie;
  3         var i=-1;
  4         if((i=str.indexOf(cookieName+"="))!=-1){
  5             var start=i+cookieName.length+1;
  6             var end=str.indexOf(";",start);
  7             return str.slice(start,end==-1?str.length:end);
  8         }else{
  9             return null;
 10         }
 11     }
 12     function setCookie(cookieName,value){
 13         var date=new Date();
 14         date.setFullYear(date.getFullYear()+1);
 15         document.cookie="="+value+";expires"+date.toGMTString();
 16     }
 17 
 18 var game={
 19   data:null,//保存一个二维数组
 20   RN:4,//总行数
 21   CN:4,//总列数
 22   score:0,//游戏得分
 23   state:1,//游戏状态: 1是运行中,0是结束
 24   RUNNING:1,//运行中
 25   GAMEOVER:0,//结束
 26   //强调: 对象自己的方法要使用自己的属性,必须加this
 27   start:function(){//启动游戏
 28     this.state=this.RUNNING;//初始化游戏状态为运行中
 29     this.score=0;
 30     this.data=[];//初始化当前对象的data属性为空数组
 31     for(var r=0;r<this.RN;r++){//r从0开始,到<RN结束,每次增1
 32       this.data.push([ ]);//向data中压入一个空数组
 33       //c从0开始,到<CN结束,每次增1
 34       for(var c=0;c<this.CN;c++){
 35         this.data[r][c]=0;//在data中r行c列的位置保存一个0
 36       }
 37     }//(遍历结束)
 38     this.randomNum();//调用randomNum方法
 39     this.randomNum();//再调用randomNum方法
 40     this.updateView();//更新页面
 41     var me=this;//留住this
 42     //为当前页面绑定键盘事件: 
 43     document.onkeydown=function(e){//e: 事件对象
 44       if(me.state==me.RUNNING){
 45         switch(e.keyCode){
 46           case 37: me.moveLeft();break;
 47           case 38: me.moveUp();break;
 48           case 39: me.moveRight();break;
 49           case 40: me.moveDown();break;
 50         }
 51       }
 52     }//document.onkeydown();//this->document
 53   },//强调: 每个方法之间必须用逗号分隔
 54   isGameOver:function(){//判断游戏是否结束
 55     //遍历data中每个元素
 56     for(var r=0;r<this.RN;r++){
 57       for(var c=0;c<this.CN;c++){
 58         if(this.data[r][c]==0){//如果当前元素等于0
 59           return false;//返回false
 60         }
 61         //如果c<CN-1而且当前元素等于右侧元素
 62         if(c<this.CN-1
 63           &&this.data[r][c]==this.data[r][c+1]){
 64           return false;//返回false
 65         }
 66         //如果r<RN-1而且当前元素等于下方元素
 67         if(r<this.RN-1
 68           &&this.data[r][c]==this.data[r+1][c]){
 69           return false;//返回false
 70         }
 71       }
 72     }//(遍历结束)返回true
 73     return true;
 74   },
 75   move:function(fun){//定义所有移动中相同的代码
 76     //为data拍照,保存在before中
 77     var before=String(this.data);
 78     fun.call(this);
 79     //为data拍照,保存在after中
 80     var after=String(this.data);
 81     //如果before不等于after,就随机生成数,更新页面
 82     if(before!=after){
 83       this.randomNum();
 84       //如果调用isGameOver返回true
 85       if(this.isGameOver()){
 86         this.state=this.GAMEOVER;//修改游戏状态为GAMEOVER
 87       }
 88       this.updateView();
 89     }
 90   },
 91   moveDown:function(){//下移所有列
 92     this.move(function(){
 93       for(var c=0;c<this.CN;c++){//遍历data中每一列
 94         //调用moveUpInCol,传入c作为参数
 95         this.moveDownInCol(c);
 96       }//(遍历结束)
 97     });    
 98   },
 99   moveDownInCol:function(c){
100     for(var r=this.RN-1;r>0;r--){
101       var prevr=this.getPrevInCol(r,c);
102       if(prevr==-1){break;}
103       else{
104         if(this.data[r][c]==0){
105           this.data[r][c]=this.data[prevr][c];
106           this.data[prevr][c]=0;
107           r++;
108         }else if(this.data[r][c]==this.data[prevr][c]){
109           this.data[r][c]*=2;
110           this.score+=this.data[r][c];
111           this.data[prevr][c]=0;
112         }
113       }
114     }
115   },
116   getPrevInCol:function(r,c){
117     for(var prevr=r-1;prevr>=0;prevr--){
118       if(this.data[prevr][c]!=0){return prevr}
119     }
120     return -1;
121   },
122   moveUp:function(){//上移所有列
123     this.move(function(){
124       for(var c=0;c<this.CN;c++){//遍历data中每一列
125         //调用moveUpInCol,传入c作为参数
126         this.moveUpInCol(c);
127       }//(遍历结束)
128     });
129   },
130   moveUpInCol:function(c){//上移第c列
131     for(var r=0;r<this.RN-1;r++){//从上到下遍历每一行
132       //调用getNextInCol,传入参数r,c,返回值保存在nextr
133       var nextr=this.getNextInCol(r,c);
134       //如果nextr等于-1,就退出循环
135       if(nextr==-1){break;}
136       else{//否则
137         if(this.data[r][c]==0){//如果r行c列等于0
138           //将nextr行c列赋值给r行c列
139           this.data[r][c]=this.data[nextr][c];
140           this.data[nextr][c]=0;//将nextr行c列置为0
141           r--;
142         }else if(this.data[r][c]==this.data[nextr][c]){
143         //否则 如果r行c列等于nextr行c列
144           this.data[r][c]*=2;//将r行c列*2
145           this.score+=this.data[r][c];
146           this.data[nextr][c]=0;//将nextr行c列置为0
147         }
148       }
149     }
150   },
151   //查找r行c列下方下一个不等于0的位置
152   getNextInCol:function(r,c){
153     //nextr从r+1开始,到<RN结束,每次增1
154     for(var nextr=r+1;nextr<this.RN;nextr++){
155       //如果nextr行c列不等于0,就返回nextr
156       if(this.data[nextr][c]!=0){return nextr}
157     }//(遍历结束)就返回-1]
158     return -1;
159   },
160   moveRight:function(){//右移所有行
161     this.move(function(){
162       for(var r=0;r<this.RN;r++){//遍历data中每一行
163         //调用moveRightInRow,传入r作为参数
164         this.moveRightInRow(r);
165       }//(遍历结束)
166     });
167   },
168   moveRightInRow:function(r){//右移第r行
169     //从右向左遍历r行中每个元素,到>0结束
170     for(var c=this.CN-1;c>0;c--){
171       //调用getPrevInRow,传入r,c作为参数,返回值保存在prevc中
172       var prevc=this.getPrevInRow(r,c);
173       //如果prevc为-1,就退出循环
174       if(prevc==-1){break;}
175       else{//否则
176         //如果data中r行c位置等于0
177         if(this.data[r][c]==0){
178           //将data中r行prevc位置的值赋值给data中r行c位置
179           this.data[r][c]=this.data[r][prevc];
180           //将data中r行prevc位置置为0
181           this.data[r][prevc]=0;
182           c++;
183         }else if(this.data[r][c]==this.data[r][prevc]){
184         //否则,如果data中r行c位置等于data中r行prevc位置
185           this.data[r][c]*=2;//将data中r行c位置*2
186           this.score+=this.data[r][c];
187           //将data中r行prevc位置置为0
188           this.data[r][prevc]=0;
189         }
190       }
191     }
192   },
193   //查找r行c列左侧前一个不为0的位置s
194   getPrevInRow:function(r,c){
195     //prevc从c-1开始,到>=0结束,每次减1
196     for(var prevc=c-1;prevc>=0;prevc--){
197       //如果data中r行prevc位置不等于0
198       if(this.data[r][prevc]!=0){
199         return prevc;//返回prevc
200       }
201     }//(遍历结束)就返回-1
202     return -1;
203   },
204   moveLeft:function(){//左移所有行
205     this.move(function(){
206       for(var r=0;r<this.RN;r++){
207         //调用moveLeftInRow(r)左移第r行
208         this.moveLeftInRow(r);
209       }//(遍历结束)
210     });
211   },
212   moveLeftInRow:function(r){//左移第r行
213     //c从0开始,到<CN-1结束,每次增1
214     for(var c=0;c<this.CN-1;c++){
215       //查找c位置后,下一个不为0的位置,保存在nextc中
216       var nextc=this.getNextInRow(r,c);
217       //如果nextc是-1,就退出循环
218       if(nextc==-1){break;}
219       else{//否则
220         if(this.data[r][c]==0){//如果data中r行c位置等于0
221           //将data中r行nextc位置的值赋值给data中r行c位置
222           this.data[r][c]=this.data[r][nextc];
223           //将data中r行nextc位置置为0
224           this.data[r][nextc]=0;
225           c--;//下次还在当前位置开始
226         }else if(this.data[r][c]==this.data[r][nextc]){
227         //否则 如果data中r行c位置等于data中r行nextc位置
228           this.data[r][c]*=2;//将data中r行c位置*2
229           this.score+=this.data[r][c];//累加得分
230           //将data中r行nextc位置置为0
231           this.data[r][nextc]=0;
232         }
233       }
234     }
235   },
236   //查找r行c列右侧下一个不为0的位置
237   getNextInRow:function(r,c){
238     //nextc从c+1开始,到<CN结束,nextc每次增1
239     for(var nextc=c+1;nextc<this.CN;nextc++){
240       //如果data中r行nextc位置的值!=0
241       if(this.data[r][nextc]!=0){
242         return nextc;//返回nextc
243       }
244     }//(遍历结束)就返回-1
245     return -1;
246   },
247   //将data中的元素,更新到页面的格子div中
248   updateView:function(){
249     //r从0开始,到<RN结束,每次增1
250     for(var r=0;r<this.RN;r++){
251       //c从0开始,到<CN结束,每次增1
252       for(var c=0;c<this.CN;c++){
253         //查找id为c+r+c的div元素,保存在变量div中
254         var div=document.getElementById("c"+r+c);
255         //如果data中r行c列的等于0
256         if(this.data[r][c]==0){
257           div.innerHTML="";//设置div的内容为空字符串
258           div.className="cell";//设置div的className为"cell"
259         }else{//否则
260           //设置div的内容为data中r行c列的值
261           div.innerHTML=this.data[r][c];
262           //设置div的className为"cell n"+data中r行c列的值
263           div.className="cell n"+this.data[r][c];
264         }
265       }
266     }
267     //找到id为score的span,直接设置其内容为score属性值
268     score.innerHTML=this.score;
269     //设置id为gameOver的元素的display属性为:
270       //如果state为GAMEOVER,就设置为"block",否则为"none"
271     this.state==this.GAMEOVER
272       &&(final.innerHTML=this.score);
273     gameOver.style.display=
274       this.state==this.GAMEOVER?"block":"none";
275   },
276   randomNum:function(){//在随机位置生成一个数字
277     while(true){//反复生成数字(死循环)
278       //在0~RN-1之间生成一个随机的行号,保存在r中
279       var r=Math.floor(Math.random()*this.RN);
280       //在0~CN-1之间生成一个随机的列号,保存在c中
281       var c=Math.floor(Math.random()*this.CN);
282       if(this.data[r][c]==0){//如果data中r行c列为0
283         //随机生成一个数字保存在变量num中
284         var num=Math.random();
285         //设置data中r行c列的元素值为:
286           //如果num<0.5,就设置2为,否则就设置为4
287         this.data[r][c]=num<0.5?2:4;
288         break;//退出循环
289       }
290     }
291   },
292 }
293 //当页面加载后,自动启动
294 window.onload=function(){game.start();}
原文地址:https://www.cnblogs.com/chenzeyongjsj/p/5517587.html