<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>2048</title>
<style>
#gridPanel{
width: 480px;
height: 480px;
margin:0 auto;
position: relative;
background: #bbada0;
border-radius: 10px;
}
.cell{
width: 100px;
height: 100px;
position: absolute;
background: #D2BEBA;
border-radius: 6px;
font-size: 48px;
text-align: center;
color: #fff;
line-height: 100px;
}
[id^="c0"]{top:16px;}
[id^="c1"]{top:132px;}
[id^="c2"]{top:248px;}
[id^="c3"]{top:364px;}
[id$="0"]{left:16px;}
[id$="1"]{left:132px;}
[id$="2"]{left:248px;}
[id$="3"]{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}
.n2,.n4{color: #776e65}
.n1024,.n2048,.n4096,.n8192{font-size: 40px}
p{
width: 480px;
margin: 0 auto;
font-size: 40px;
font-family: Arial;
font-weight: bold;
padding-top:15px;
}
#gameOver{
display: none;
position: absolute;;
top: 0;
left: 0;
right: 0;
bottom: 0;
background:rgba(55,55,55,.5);
}
#gameOver>p{
width: 300px;
height: 200px;
background: #fff;
position: absolute;
top: 50%;
left: 50%;
margin-top: -100px;
margin-left: -150px;
text-align: center;
line-height: 1.5em;
border-radius: 10px;
border: 1px solid #edcf72;
}
#gameOver .btn{
padding: 10px;
color:#fff;
background: #9f8d77;
border-radius: 6px;
text-decoration: none;
}
</style>
</head>
<body>
<p>SCORE:<span id="score">0</span></p>
<div id="gridPanel">
<div id="c00" class="cell"></div>
<div id="c01" class="cell"></div>
<div id="c02" class="cell"></div>
<div id="c03" class="cell"></div>
<div id="c10" class="cell"></div>
<div id="c11" class="cell"></div>
<div id="c12" class="cell"></div>
<div id="c13" class="cell"></div>
<div id="c20" class="cell"></div>
<div id="c21" class="cell"></div>
<div id="c22" class="cell"></div>
<div id="c23" class="cell"></div>
<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">
<p>
GAME OVER<br>
SCORE:<span id="final">0</span><br>
<a href="javascript:game.start();" class="btn">TRY AGAIN!</a>
</p>
</div>
<script>
var game={
data:null,RN:4,CN:4,
score:0,
state:1,
RUNNING:1,
GAMEOVER:0,
start(){
this.state=this.RUNNING;
this.score=0;
this.data=[];
for(var r=0;r<this.RN;r++){
this.data[r]=[];
for(var c=0;c<this.CN;c++){
this.data[r][c]=0;
}
}
this.randomNum();
this.randomNum();
this.updateView();
document.onkeydown=function(e){
switch(e.keyCode){
case 37://左移
this.moveLeft();
break;
case 38://上移
this.moveUp();
break;
case 39://右移
this.moveRight();
break;
case 40://下移
this.moveDown();
break;
}
}.bind(this);
},
moveLeft(){
var before=String(this.data);
for(var r=0;r<this.RN;r++){
this.moveLeftInRow(r);
}
var after=String(this.data);
if(before!=after){
this.randomNum();
if(this.isGameOver()){
this.state=this.GAMEOVER;
}
this.updateView();
}
},
moveLeftInRow(r){
for(var c=0;c<this.CN-1;c++){
var nextc=this.getNextInRow(r,c)
if(nextc==-1) break;
else
if(this.data[r][c]==0){
this.data[r][c]=this.data[r][nextc];
this.data[r][nextc]=0;
c--;
}else if(this.data[r][c]==this.data[r][nextc]){
this.data[r][c]*=2;
this.score+=this.data[r][c];
this.data[r][nextc]=0;
}
}
},
getNextInRow(r,c){
for(var i=c+1;i<this.CN;i++){
if(this.data[r][i]!=0) return i;
}
return -1;
},
moveRight(){
var before=String(this.data);
for(var r=0;r<this.RN;r++){
this.moveRightInRow(r);
}
var after=String(this.data);
if(before!=after){
this.randomNum();
this.updateView();
}
},
moveRightInRow(r){
for(var c=this.CN-1;c>0;c--){
var prevc=this.getPrevInRow(r,c)
if(prevc==-1) break;
else
if(this.data[r][c]==0){
this.data[r][c]=this.data[r][prevc];
this.data[r][prevc]=0;
c++;
}else if(this.data[r][c]==this.data[r][prevc]){
this.data[r][c]*=2;
this.score+=this.data[r][c];
this.data[r][prevc]=0;
}
}
},
getPrevInRow(r,c){
for(var i=c-1;i>=0;i--){
if(this.data[r][i]!=0) return i;
}
return -1;
},
moveUp:function(){
var before=String(this.data);
for(var c=0;c<this.CN;c++){
this.moveUpInCol(c);
}
var after=String(this.data);
if(before!=after){
this.randomNum();
this.updateView();
}
},
moveUpInCol:function(c){
for(var r=0;r<this.RN-1;r++){
var nextr=this.getNextInCol(r,c)
if(nextr==-1) break;
else
if(this.data[r][c]==0){
this.data[r][c]=this.data[nextr][c];
this.data[nextr][c]=0;
r--;
}else if(this.data[r][c]==this.data[nextr][c]){
this.data[r][c]*=2;
this.score+=this.data[r][c];
this.data[nextr][c]=0;
}
}
},
getNextInCol:function(r,c){
for(var i=r+1;i<this.RN;i++){
if(this.data[i][c]!=0) return i;
}
return -1;
},
moveDown:function(){
var before=String(this.data);
for(var c=0;c<this.CN;c++){
this.moveDownInCol(c);
}
var after=String(this.data);
if(before!=after){
this.randomNum();
this.updateView();
}
},
moveDownInCol:function(c){
for(var r=this.RN-1;r>0;r--){
var prevr=this.getPrevInCol(r,c)
if(prevr==-1) break;
else
if(this.data[r][c]==0){
this.data[r][c]=this.data[prevr][c];
this.data[prevr][c]=0;
r++;
}else if(this.data[r][c]==this.data[prevr][c]){
this.data[r][c]*=2;
this.score+=this.data[r][c];
this.data[prevr][c]=0;
}
}
},
getPrevInCol:function(r,c){
for(var i=r-1;i>=0;i--){
if(this.data[i][c]!=0) return i;
}
return -1;
},
isGameOver(){
for(var c=0;c<this.CN-1;c++){
for(var r=0;r<this.RN-1;r++){
if(this.data[r][c]==0) return false;
else
if(this.data[r][c]==this.data[r][c+1]){
return false;
}else if(this.data[r][c]==this.data[r+1][c]){
return false;
}
}
}
for(var c=3,r=0;r<this.RN-1;r++){
if(this.data[r][c]==0) return false;
else
if(this.data[r][c]==this.data[r+1][c]){
return false;
}
}
for(var r=3,c=0;c<this.CN-1;c++){
if(this.data[r][c]==0) return false;
else
if(this.data[r][c]==this.data[r][c+1]){
return false;
}
}
return true;
},
updateView(){
for(var r=0;r<this.RN;r++){
for(var c=0;c<this.CN;c++){
var n=this.data[r][c];
var div=document.getElementById("c"+r+c);
if(n!=0){
div.innerHTML=n;
div.className="cell n"+n;
}else{
div.innerHTML=""
div.className="cell"
}
}
}
document.getElementById("score").innerHTML=this.score;
var div=document.getElementById("gameOver");
if(this.state==this.GAMEOVER){
div.style.display="block";
document.getElementById("final").innerHTML=this.score;
}else{
div.style.display="none";
}
},
randomNum(){
while(true){
var r=Math.floor(Math.random()*this.RN);
var c=Math.floor(Math.random()*this.CN);
if(this.data[r][c]==0){
this.data[r][c]=Math.random()<0.5?2:4;
break;
}
}
},
}
game.start();
</script>
</body>
</html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>2048</title>
<style>
#gridPanel{
width: 480px;
height: 480px;
margin:0 auto;
position: relative;
background: #bbada0;
border-radius: 10px;
}
.cell{
width: 100px;
height: 100px;
position: absolute;
background: #D2BEBA;
border-radius: 6px;
font-size: 48px;
text-align: center;
color: #fff;
line-height: 100px;
}
[id^="c0"]{top:16px;}
[id^="c1"]{top:132px;}
[id^="c2"]{top:248px;}
[id^="c3"]{top:364px;}
[id$="0"]{left:16px;}
[id$="1"]{left:132px;}
[id$="2"]{left:248px;}
[id$="3"]{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}
.n2,.n4{color: #776e65}
.n1024,.n2048,.n4096,.n8192{font-size: 40px}
p{
width: 480px;
margin: 0 auto;
font-size: 40px;
font-family: Arial;
font-weight: bold;
padding-top:15px;
}
#gameOver{
display: none;
position: absolute;;
top: 0;
left: 0;
right: 0;
bottom: 0;
background:rgba(55,55,55,.5);
}
#gameOver>p{
width: 300px;
height: 200px;
background: #fff;
position: absolute;
top: 50%;
left: 50%;
margin-top: -100px;
margin-left: -150px;
text-align: center;
line-height: 1.5em;
border-radius: 10px;
border: 1px solid #edcf72;
}
#gameOver .btn{
padding: 10px;
color:#fff;
background: #9f8d77;
border-radius: 6px;
text-decoration: none;
}
</style>
</head>
<body>
<p>SCORE:<span id="score">0</span></p>
<div id="gridPanel">
<div id="c00" class="cell"></div>
<div id="c01" class="cell"></div>
<div id="c02" class="cell"></div>
<div id="c03" class="cell"></div>
<div id="c10" class="cell"></div>
<div id="c11" class="cell"></div>
<div id="c12" class="cell"></div>
<div id="c13" class="cell"></div>
<div id="c20" class="cell"></div>
<div id="c21" class="cell"></div>
<div id="c22" class="cell"></div>
<div id="c23" class="cell"></div>
<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">
<p>
GAME OVER<br>
SCORE:<span id="final">0</span><br>
<a href="javascript:game.start();" class="btn">TRY AGAIN!</a>
</p>
</div>
<script>
var game={
data:null,RN:4,CN:4,
score:0,
state:1,
RUNNING:1,
GAMEOVER:0,
start(){
this.state=this.RUNNING;
this.score=0;
this.data=[];
for(var r=0;r<this.RN;r++){
this.data[r]=[];
for(var c=0;c<this.CN;c++){
this.data[r][c]=0;
}
}
this.randomNum();
this.randomNum();
this.updateView();
document.onkeydown=function(e){
switch(e.keyCode){
case 37://左移
this.moveLeft();
break;
case 38://上移
this.moveUp();
break;
case 39://右移
this.moveRight();
break;
case 40://下移
this.moveDown();
break;
}
}.bind(this);
},
moveLeft(){
var before=String(this.data);
for(var r=0;r<this.RN;r++){
this.moveLeftInRow(r);
}
var after=String(this.data);
if(before!=after){
this.randomNum();
if(this.isGameOver()){
this.state=this.GAMEOVER;
}
this.updateView();
}
},
moveLeftInRow(r){
for(var c=0;c<this.CN-1;c++){
var nextc=this.getNextInRow(r,c)
if(nextc==-1) break;
else
if(this.data[r][c]==0){
this.data[r][c]=this.data[r][nextc];
this.data[r][nextc]=0;
c--;
}else if(this.data[r][c]==this.data[r][nextc]){
this.data[r][c]*=2;
this.score+=this.data[r][c];
this.data[r][nextc]=0;
}
}
},
getNextInRow(r,c){
for(var i=c+1;i<this.CN;i++){
if(this.data[r][i]!=0) return i;
}
return -1;
},
moveRight(){
var before=String(this.data);
for(var r=0;r<this.RN;r++){
this.moveRightInRow(r);
}
var after=String(this.data);
if(before!=after){
this.randomNum();
this.updateView();
}
},
moveRightInRow(r){
for(var c=this.CN-1;c>0;c--){
var prevc=this.getPrevInRow(r,c)
if(prevc==-1) break;
else
if(this.data[r][c]==0){
this.data[r][c]=this.data[r][prevc];
this.data[r][prevc]=0;
c++;
}else if(this.data[r][c]==this.data[r][prevc]){
this.data[r][c]*=2;
this.score+=this.data[r][c];
this.data[r][prevc]=0;
}
}
},
getPrevInRow(r,c){
for(var i=c-1;i>=0;i--){
if(this.data[r][i]!=0) return i;
}
return -1;
},
moveUp:function(){
var before=String(this.data);
for(var c=0;c<this.CN;c++){
this.moveUpInCol(c);
}
var after=String(this.data);
if(before!=after){
this.randomNum();
this.updateView();
}
},
moveUpInCol:function(c){
for(var r=0;r<this.RN-1;r++){
var nextr=this.getNextInCol(r,c)
if(nextr==-1) break;
else
if(this.data[r][c]==0){
this.data[r][c]=this.data[nextr][c];
this.data[nextr][c]=0;
r--;
}else if(this.data[r][c]==this.data[nextr][c]){
this.data[r][c]*=2;
this.score+=this.data[r][c];
this.data[nextr][c]=0;
}
}
},
getNextInCol:function(r,c){
for(var i=r+1;i<this.RN;i++){
if(this.data[i][c]!=0) return i;
}
return -1;
},
moveDown:function(){
var before=String(this.data);
for(var c=0;c<this.CN;c++){
this.moveDownInCol(c);
}
var after=String(this.data);
if(before!=after){
this.randomNum();
this.updateView();
}
},
moveDownInCol:function(c){
for(var r=this.RN-1;r>0;r--){
var prevr=this.getPrevInCol(r,c)
if(prevr==-1) break;
else
if(this.data[r][c]==0){
this.data[r][c]=this.data[prevr][c];
this.data[prevr][c]=0;
r++;
}else if(this.data[r][c]==this.data[prevr][c]){
this.data[r][c]*=2;
this.score+=this.data[r][c];
this.data[prevr][c]=0;
}
}
},
getPrevInCol:function(r,c){
for(var i=r-1;i>=0;i--){
if(this.data[i][c]!=0) return i;
}
return -1;
},
isGameOver(){
for(var c=0;c<this.CN-1;c++){
for(var r=0;r<this.RN-1;r++){
if(this.data[r][c]==0) return false;
else
if(this.data[r][c]==this.data[r][c+1]){
return false;
}else if(this.data[r][c]==this.data[r+1][c]){
return false;
}
}
}
for(var c=3,r=0;r<this.RN-1;r++){
if(this.data[r][c]==0) return false;
else
if(this.data[r][c]==this.data[r+1][c]){
return false;
}
}
for(var r=3,c=0;c<this.CN-1;c++){
if(this.data[r][c]==0) return false;
else
if(this.data[r][c]==this.data[r][c+1]){
return false;
}
}
return true;
},
updateView(){
for(var r=0;r<this.RN;r++){
for(var c=0;c<this.CN;c++){
var n=this.data[r][c];
var div=document.getElementById("c"+r+c);
if(n!=0){
div.innerHTML=n;
div.className="cell n"+n;
}else{
div.innerHTML=""
div.className="cell"
}
}
}
document.getElementById("score").innerHTML=this.score;
var div=document.getElementById("gameOver");
if(this.state==this.GAMEOVER){
div.style.display="block";
document.getElementById("final").innerHTML=this.score;
}else{
div.style.display="none";
}
},
randomNum(){
while(true){
var r=Math.floor(Math.random()*this.RN);
var c=Math.floor(Math.random()*this.CN);
if(this.data[r][c]==0){
this.data[r][c]=Math.random()<0.5?2:4;
break;
}
}
},
}
game.start();
</script>
</body>
</html>