HTML + CSS + JS 写出简单2048游戏
HTML + CSS + JS 写出简单2048游戏
在这里插入代码片
/*html 代码:*/
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>2048游戏</title>
<style>
.container{
width: 600px;
height: 600px;
border: 2px solid #000;
background-color: white;
margin: auto;
}
.header{
font: bold 40px arial;
margin-left: 80px;
}
.header span, #gameOver span{
color: red;
}
#gameBody{
width: 450px;
height: 450px;
margin-left: 80px;
padding: 5px 0 0 5px;
border-radius: 10px;
background-color: #bbada0;
}
.cell{
width: 100px;
height: 100px;
margin: 5px;
background-color: #ccc0b3;
border-radius: 5px;
float: left;
font: 50px/100px arial;
text-align: center;
}
.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}
#gameOver{
display: none;
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background:rgba(55,55,55,0.5);
}
#gameOver p{
width: 300px;
height: 200px;
position: absolute;
top: 50%;
left: 50%;
margin: -100px 0 0 -150px;
text-align: center;
border-radius: 10px;
border: 1px solid #edcf72;
font: bold 40px/65px arial;
background: #fff;
}
#gameOver .btn{
padding: 10px;
color:#fff;
background: #9f8d77;
border-radius: 6px;
text-decoration: none;
}
</style>
</head>
<body>
<div class="container">
<p class="header">SCORE:<span id="score">0</span></p>
<div id="gameBody">
<div class="cell" id="cell-00"></div>
<div class="cell" id="cell-01"></div>
<div class="cell" id="cell-02"></div>
<div class="cell" id="cell-03"></div>
<div class="cell" id="cell-10"></div>
<div class="cell" id="cell-11"></div>
<div class="cell" id="cell-12"></div>
<div class="cell" id="cell-13"></div>
<div class="cell" id="cell-20"></div>
<div class="cell" id="cell-21"></div>
<div class="cell" id="cell-22"></div>
<div class="cell" id="cell-23"></div>
<div class="cell" id="cell-30"></div>
<div class="cell" id="cell-31"></div>
<div class="cell" id="cell-32"></div>
<div class="cell" id="cell-33"></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>
</div>
<script>
//创建对象:属性+方法
var game = {
//数组,保存数据
data:[],
//游戏得分:0
score:0,
//设置游戏状态:1-开始,0-结束
state:1,
//游戏状态:开始
RUNNING:1,
//游戏状态:结束
GAMEOVER:0,
//游戏开始start()方法
start:function(){
//设置游戏状态为开始
this.state=this.RUNNING;
//初始化游戏得分为0
this.score=0;
//创建一个二维数组
for(var r = 0; r < 4; r++){
//创建一个一维数组,
var datacell = [];
//将一维数组值初始化为0
for(var c = 0;c < 4; c++){
datacell[c] = 0;
}
//将一维数组的值循环赋给数组data[],成功创建一个二维数组
this.data[r] = datacell;
}
//调用函数随机生成两个数
this.randomNum();
this.randomNum();
//刷新页面,显示div的值
this.updateView();
},
//随机生成两个数4或2
randomNum:function(){
while(true){
var r=Math.floor(Math.random()*this.data.length);
var c=Math.floor(Math.random()*this.data.length);
if(this.data[r][c]==0){
//随机生成2和4的概率相等
this.data[r][c]=Math.random()<0.5?2:4;
break;
}
}
},
updateView:function(){
for(var r=0;r<this.data.length;r++){
for(var c=0;c<this.data.length;c++){
//判断数组中的数据,为0则不做任何操作,保持原来数据和类名不变
//动态获取标签的id:要求取id名时与数组下角标相对应
if(this.data[r][c]==0){
document.getElementById("cell-"+r+c).innerHTML="";
document.getElementById("cell-"+r+c).className="cell";
}else{
//不为0,则将数组中数据显示在对应的div格子中
document.getElementById("cell-"+r+c).innerHTML= this.data[r][c];
//保持原来类名不变,并追加对应div类名(动态)
document.getElementById("cell-"+r+c).className="cell n" + this.data[r][c];
}
}
}
//将分数显示在界面上方
document.getElementById("score").innerHTML=this.score;
var gameOver=document.getElementById("gameOver");
if(this.state==this.GAMEOVER){
//如果状态为GAMEOVER(即0,表示游戏结束,显示结束界面,并将最后分数显示在结束界面
gameOver.style.display="block";
document.getElementById("final").innerHTML=this.score;
}else{
//如果状态为1,表示游戏还未结束,隐藏结束界面
gameOver.style.display="none";
}
},
//向左移动所有行
moveLeft:function(){
//判断字符串是否移动
//做移动操作前先将数组转换为字符串保存
var before=String(this.data);
//遍历行
for(var r=0;r<this.data.length;r++){
this.moveLeftRow(r);
}
//做移动操作后先将数组转换为字符串保存
var after=String(this.data);
//将移动操作前后的数组(字符串)作比较,如果不相等,即发生改变,则随机生成一个数
if(before!=after){
this.randomNum();
//随机生成一个数后,判断游戏是否结束,设置游戏状态
if(this.isGameOver()){
this.state=this.GAMEOVER;
}
//游戏未结束刷新页面,再显示随机生成数
this.updateView();
}
},
//判断并向左移动指定行中的每个元素
moveLeftRow:function(r){
//0开始,遍历r行中每一个元素
for(var c=0;c<this.data.length-1;c++){
//获得当前元素下一个不为0的元素的下标nextc
var nextc=this.getNextRow(r,c)
//如果nextc=-1,说明右侧没有元素了,退出循环
if(nextc==-1) {
break;
}else if(this.data[r][c]==0){ //如果自己==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]){// 如果当前位置的值==nextc的位置的值,将当前位置*=2;下一个位置设置为0
this.data[r][c]*=2;
//将当前值累加到score属性上
this.score+=this.data[r][c];
this.data[r][nextc]=0;
}
}
},
//找当前位置右侧,下一个不为0的数
getNextRow:function(r,c){
//从c+1 遍历row行中剩余元素,
for(var i=c+1;i<this.data.length;i++){
//如果出现不为0的值,返回它的列数
if(this.data[r][i]!=0) {
return i;
}
}
//循环退出返回-1
return -1;
},
//向右移动所有行
moveRight:function(){
var before=String(this.data);
for(var r=0;r<this.data.length;r++){
this.moveRightRow(r);
}
var after=String(this.data);
if(before!=after){
this.randomNum();
if(this.isGameOver()){
this.state=this.GAMEOVER;
}
this.updateView();
}
},
moveRightRow:function(r){
for(var c=this.data.length-1;c>0;c--){
var prec=this.getPreRow(r,c)
if(prec==-1){
break;
}else if(this.data[r][c]==0){
this.data[r][c]=this.data[r][prec];
this.data[r][prec]=0;
c++;
}else if(this.data[r][c]==this.data[r][prec]){
this.data[r][c]*=2;
this.score+=this.data[r][c];
this.data[r][prec]=0;
}
}
},
getPreRow:function(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.data.length;c++){
this.moveUpCol(c);
}
var after=String(this.data);
if(before!=after){
this.randomNum();
if(this.isGameOver()){
this.state=this.GAMEOVER;
}
this.updateView();
}
},
//向上移动所有列
moveUpCol:function(c){
for(var r=0;r<this.data.length-1;r++){
var nextr=this.getNextCol(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;
}
}
},
getNextCol:function(r,c){
for(var i=r+1;i<this.data.length;i++){
if(this.data[i][c]!=0) return i;
}
return -1;
},
//向下移动所有列
moveDown:function(){
var before=String(this.data);
for(var c=0;c<this.data.length;c++){
this.moveDownCol(c);
}
var after=String(this.data);
if(before!=after){
this.randomNum();
if(this.isGameOver()){
this.state=this.GAMEOVER;
}
this.updateView();
}
},
moveDownCol:function(c){
for(var r=this.data.length-1;r>0;r--){
var prer=this.getPreCol(r,c)
if(prer==-1) {
break;
}
else if(this.data[r][c]==0){
this.data[r][c]=this.data[prer][c];
this.data[prer][c]=0;
r++;
}else if(this.data[r][c]==this.data[prer][c]){
this.data[r][c]*=2;
this.score+=this.data[r][c];
this.data[prer][c]=0;
}
}
},
getPreCol:function(r,c){
for(var i=r-1;i>=0;i--){
if(this.data[i][c]!=0) return i;
}
return -1;
},
isGameOver:function(){
//游戏结束条件:
//1.数组中所有数据均不为0;
//2.数组中每一行数据相邻位置值不相等
//3.数组中每一列数据相邻位置值不相等
for(var c=0;c<this.data.length;c++){
for(var r=0;r<this.data.length;r++){
//判断所有不为0
if(this.data[r][c]==0){
return false;
}
if(c<3){
if(this.data[r][c]==this.data[r][c+1]){
return false;
}
}
if(r<3){
if(this.data[r][c]==this.data[r+1][c]){
return false;
}
}
}
}
return true;
}
}
//调用函数开始游戏
game.start();
document.onkeydown=function(event){
//按下左键或者字母键a,向左移动
if(event.keyCode==37 || event.keyCode==65 ){
game.moveLeft();
}
//按下向上键或者字母键w,向上移动
if(event.keyCode==38 || event.keyCode==87 ){
game.moveUp();
}
//按下右键或者字母键d,向右移动
if(event.keyCode==39 || event.keyCode==68 ){
game.moveRight();
}
//按下向下键或者字母键s,向下移动
if(event.keyCode==40 || event.keyCode==83 ){
game.moveDown();
}
//按下空格键重新开始游戏
if(event.keyCode==32 ){
game.start();
}
}
</script>
</body>
</html>!