新手写的,可能不是很完善,欢迎修改及探讨
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>2048游戏</title> 6 <style> 7 .container{ 8 width: 600px; 9 height: 600px; 10 border: 2px solid #000; 11 background-color: white; 12 margin: auto; 13 } 14 15 .header{ 16 font: bold 40px arial; 17 margin-left: 80px; 18 } 19 .header span, #gameOver span{ 20 color: red; 21 } 22 23 #gameBody{ 24 width: 450px; 25 height: 450px; 26 margin-left: 80px; 27 padding: 5px 0 0 5px; 28 border-radius: 10px; 29 background-color: #bbada0; 30 } 31 32 .cell{ 33 width: 100px; 34 height: 100px; 35 margin: 5px; 36 background-color: #ccc0b3; 37 border-radius: 5px; 38 float: left; 39 font: 50px/100px arial; 40 text-align: center; 41 } 42 43 .n2{background-color: #eee3da} 44 .n4{background-color: #ede0c8} 45 .n8{background-color: #f2b179} 46 .n16{background-color: #f59563} 47 .n32{background-color: #f67c5f} 48 .n64{background-color: #f65e3b} 49 .n128{background-color: #edcf72} 50 .n256{background-color: #edcc61} 51 .n512{background-color: #9c0} 52 .n1024{background-color: #33b5e5} 53 .n2048{background-color: #09c} 54 .n4096{background-color: #a6c} 55 .n8192{background-color: #93c} 56 .n2,.n4{color: #776e65} 57 .n1024,.n2048,.n4096,.n8192{font-size: 40px} 58 59 60 #gameOver{ 61 display: none; 62 position: absolute; 63 top: 0; 64 left: 0; 65 right: 0; 66 bottom: 0; 67 background:rgba(55,55,55,0.5); 68 } 69 70 #gameOver p{ 71 width: 300px; 72 height: 200px; 73 position: absolute; 74 top: 50%; 75 left: 50%; 76 margin: -100px 0 0 -150px; 77 text-align: center; 78 border-radius: 10px; 79 border: 1px solid #edcf72; 80 font: bold 40px/65px arial; 81 background: #fff; 82 } 83 84 #gameOver .btn{ 85 padding: 10px; 86 color:#fff; 87 background: #9f8d77; 88 border-radius: 6px; 89 text-decoration: none; 90 } 91 </style> 92 </head> 93 <body> 94 <div class="container"> 95 <p class="header">SCORE:<span id="score">0</span></p> 96 <div id="gameBody"> 97 <div class="cell" id="cell-00"></div> 98 <div class="cell" id="cell-01"></div> 99 <div class="cell" id="cell-02"></div>100 <div class="cell" id="cell-03"></div>101 <div class="cell" id="cell-10"></div>102 <div class="cell" id="cell-11"></div>103 <div class="cell" id="cell-12"></div>104 <div class="cell" id="cell-13"></div>105 <div class="cell" id="cell-20"></div>106 <div class="cell" id="cell-21"></div>107 <div class="cell" id="cell-22"></div>108 <div class="cell" id="cell-23"></div>109 <div class="cell" id="cell-30"></div>110 <div class="cell" id="cell-31"></div>111 <div class="cell" id="cell-32"></div>112 <div class="cell" id="cell-33"></div>113 </div>114 <div id="gameOver">115 <p>116 GAME OVER<br>117 SCORE:<span id="final">0</span><br>118 <a href="javascript:game.start();" class="btn">TRY AGAIN!</a>119 </p>120 </div>121 </div>122 123 <script>124 //创建对象:属性+方法125 var game = {126 //数组,保存数据127 data:[],128 //游戏得分:0129 score:0,130 //设置游戏状态:1-开始,0-结束131 state:1,132 //游戏状态:开始133 RUNNING:1,134 //游戏状态:结束135 GAMEOVER:0,136 137 //游戏开始start()方法138 start:function(){139 //设置游戏状态为开始140 this.state=this.RUNNING;141 //初始化游戏得分为0142 this.score=0;143 //创建一个二维数组144 for(var r = 0; r < 4; r++){145 //创建一个一维数组,146 var datacell = [];147 //将一维数组值初始化为0148 for(var c = 0;c < 4; c++){149 datacell[c] = 0;150 }151 //将一维数组的值循环赋给数组data[],成功创建一个二维数组152 this.data[r] = datacell;153 }154 155 //调用函数随机生成两个数156 this.randomNum();157 this.randomNum();158 //刷新页面,显示div的值159 this.updateView();160 },161 162 //随机生成两个数4或2163 randomNum:function(){164 while(true){165 var r=Math.floor(Math.random()*this.data.length);166 var c=Math.floor(Math.random()*this.data.length);167 if(this.data[r][c]==0){168 //随机生成2和4的概率相等169 this.data[r][c]=Math.random()<0.5?2:4;170 break;171 }172 }173 },174 175 updateView:function(){176 for(var r=0;r<this.data.length;r++){177 for(var c=0;c<this.data.length;c++){178 //判断数组中的数据,为0则不做任何操作,保持原来数据和类名不变179 //动态获取标签的id:要求取id名时与数组下角标相对应180 if(this.data[r][c]==0){181 document.getElementById("cell-"+r+c).innerHTML="";182 document.getElementById("cell-"+r+c).className="cell";183 }else{184 //不为0,则将数组中数据显示在对应的div格子中185 document.getElementById("cell-"+r+c).innerHTML= this.data[r][c];186 //保持原来类名不变,并追加对应div类名(动态)187 document.getElementById("cell-"+r+c).className="cell n" + this.data[r][c];188 189 }190 }191 }192 //将分数显示在界面上方193 document.getElementById("score").innerHTML=this.score;194 var gameOver=document.getElementById("gameOver");195 if(this.state==this.GAMEOVER){196 //如果状态为GAMEOVER(即0,表示游戏结束,显示结束界面,并将最后分数显示在结束界面197 gameOver.style.display="block";198 document.getElementById("final").innerHTML=this.score;199 }else{200 //如果状态为1,表示游戏还未结束,隐藏结束界面201 gameOver.style.display="none";202 }203 },204 205 //向左移动所有行206 moveLeft:function(){207 //判断字符串是否移动208 //做移动操作前先将数组转换为字符串保存209 var before=String(this.data);210 //遍历行211 for(var r=0;r<this.data.length;r++){212 this.moveLeftRow(r);213 }214 //做移动操作后先将数组转换为字符串保存215 var after=String(this.data);216 //将移动操作前后的数组(字符串)作比较,如果不相等,即发生改变,则随机生成一个数217 if(before!=after){218 this.randomNum();219 //随机生成一个数后,判断游戏是否结束,设置游戏状态220 if(this.isGameOver()){221 this.state=this.GAMEOVER;222 }223 //游戏未结束刷新页面,再显示随机生成数224 this.updateView();225 }226 },227 228 //判断并向左移动指定行中的每个元素229 moveLeftRow:function(r){230 //0开始,遍历r行中每一个元素231 for(var c=0;c<this.data.length-1;c++){232 //获得当前元素下一个不为0的元素的下标nextc233 var nextc=this.getNextRow(r,c)234 //如果nextc=-1,说明右侧没有元素了,退出循环235 if(nextc==-1) {236 break;237 }else if(this.data[r][c]==0){ //如果自己==0 则将下一个位置放入当前位置,下一个位置设置为零238 this.data[r][c]=this.data[r][nextc];239 this.data[r][nextc]=0;240 //重新检查241 c--;242 }else if(this.data[r][c]==this.data[r][nextc]){// 如果当前位置的值==nextc的位置的值,将当前位置*=2;下一个位置设置为0243 this.data[r][c]*=2;244 //将当前值累加到score属性上245 this.score+=this.data[r][c];246 this.data[r][nextc]=0;247 }248 }249 },250 251 //找当前位置右侧,下一个不为0的数252 getNextRow:function(r,c){253 //从c+1 遍历row行中剩余元素,254 for(var i=c+1;i<this.data.length;i++){255 //如果出现不为0的值,返回它的列数256 if(this.data[r][i]!=0) {257 return i;258 }259 }260 //循环退出返回-1261 return -1;262 },263 264 265 //向右移动所有行 266 moveRight:function(){267 var before=String(this.data);268 for(var r=0;r<this.data.length;r++){269 this.moveRightRow(r);270 }271 var after=String(this.data);272 if(before!=after){273 this.randomNum();274 if(this.isGameOver()){275 this.state=this.GAMEOVER;276 }277 this.updateView();278 }279 },280 281 moveRightRow:function(r){282 for(var c=this.data.length-1;c>0;c--){283 var prec=this.getPreRow(r,c)284 if(prec==-1){285 break;286 }else if(this.data[r][c]==0){287 this.data[r][c]=this.data[r][prec];288 this.data[r][prec]=0;289 c++;290 }else if(this.data[r][c]==this.data[r][prec]){291 this.data[r][c]*=2;292 this.score+=this.data[r][c];293 this.data[r][prec]=0;294 }295 }296 },297 298 getPreRow:function(r,c){299 for(var i=c-1;i>=0;i--){300 if(this.data[r][i]!=0) return i; 301 }302 return -1;303 },304 305 moveUp:function(){306 var before=String(this.data);307 for(var c=0;c<this.data.length;c++){308 this.moveUpCol(c);309 }310 var after=String(this.data);311 if(before!=after){312 this.randomNum();313 if(this.isGameOver()){314 this.state=this.GAMEOVER;315 }316 this.updateView();317 }318 },319 320 //向上移动所有列321 moveUpCol:function(c){322 for(var r=0;r<this.data.length-1;r++){323 var nextr=this.getNextCol(r,c)324 if(nextr==-1) {break;325 }else if(this.data[r][c]==0){326 this.data[r][c]=this.data[nextr][c];327 this.data[nextr][c]=0;328 r--;329 }else if(this.data[r][c]==this.data[nextr][c]){330 this.data[r][c]*=2;331 this.score+=this.data[r][c];332 this.data[nextr][c]=0;333 }334 }335 },336 337 getNextCol:function(r,c){338 for(var i=r+1;i<this.data.length;i++){339 if(this.data[i][c]!=0) return i; 340 }341 return -1;342 },343 344 //向下移动所有列345 moveDown:function(){346 var before=String(this.data);347 for(var c=0;c<this.data.length;c++){348 this.moveDownCol(c);349 }350 var after=String(this.data);351 if(before!=after){352 this.randomNum();353 if(this.isGameOver()){354 this.state=this.GAMEOVER;355 }356 this.updateView();357 }358 },359 360 moveDownCol:function(c){361 for(var r=this.data.length-1;r>0;r--){362 var prer=this.getPreCol(r,c)363 if(prer==-1) {364 break;365 }366 else if(this.data[r][c]==0){367 this.data[r][c]=this.data[prer][c];368 this.data[prer][c]=0;369 r++;370 }else if(this.data[r][c]==this.data[prer][c]){371 this.data[r][c]*=2;372 this.score+=this.data[r][c];373 this.data[prer][c]=0;374 }375 }376 },377 378 getPreCol:function(r,c){379 for(var i=r-1;i>=0;i--){380 if(this.data[i][c]!=0) return i; 381 }382 return -1;383 },384 385 isGameOver:function(){386 //游戏结束条件:387 //1.数组中所有数据均不为0;388 //2.数组中每一行数据相邻位置值不相等389 //3.数组中每一列数据相邻位置值不相等390 for(var c=0;c<this.data.length;c++){391 for(var r=0;r<this.data.length;r++){392 //判断所有不为0393 if(this.data[r][c]==0){394 return false;395 }396 if(c<3){397 if(this.data[r][c]==this.data[r][c+1]){398 return false;399 }400 }401 if(r<3){402 if(this.data[r][c]==this.data[r+1][c]){403 return false;404 }405 }406 }407 }408 return true;409 }410 }411 412 //调用函数开始游戏413 game.start();414 document.onkeydown=function(event){415 //按下左键或者字母键a,向左移动416 if(event.keyCode==37 || event.keyCode==65 ){417 game.moveLeft();418 }419 //按下向上键或者字母键w,向上移动420 if(event.keyCode==38 || event.keyCode==87 ){421 game.moveUp();422 }423 //按下右键或者字母键d,向右移动424 if(event.keyCode==39 || event.keyCode==68 ){425 game.moveRight();426 }427 //按下向下键或者字母键s,向下移动428 if(event.keyCode==40 || event.keyCode==83 ){429 game.moveDown(); 430 }431 //按下空格键重新开始游戏432 if(event.keyCode==32 ){433 game.start();434 }435 436 }437 438 </script>439 </body>440 </html>!