简单实现2048小游戏

823 阅读4分钟

想实现2048游戏书写代码时可以分为三个步骤

一、HTML部分

先书写HTML把游戏结构搭建出来

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link rel="stylesheet" href="index.css">
</head>
<body>
<!--最外部的大框-->
<div class="outermost"> //包裹游戏全局的大盒子
    <!--title-->
    <span class="top"><b>SCORE:<span id="score01"></span></b></span>//顶部实时显示的游戏分数
    <!--游戏大框框-->
    <div class="big">//2048游戏为四行四列因此需要16个div盒子
        <div class="cell" id="c00"></div>
        <div class="cell" id="c01"></div>
        <div class="cell" id="c02"></div>
        <div class="cell" id="c03"></div>

        <div class="cell" id="c10"></div>
        <div class="cell" id="c11"></div>
        <div class="cell" id="c12"></div>
        <div class="cell" id="c13"></div>

        <div class="cell" id="c20"></div>
        <div class="cell" id="c21"></div>
        <div class="cell" id="c22"></div>
        <div class="cell" id="c23"></div>

        <div class="cell" id="c30"></div>
        <div class="cell" id="c31"></div>
        <div class="cell" id="c32"></div>
        <div class="cell" id="c33"></div>
    //游戏结束时会弹出的提示框
    </div>
    <!--提示框-->
    <div class="tips" id="gameover">
       <p>GAME OVER!!! <br>
           SCORE: <span id="score02">0</span><br>
           <button class="startbtn">重新开始</button>
       </p>
    </div>
    <!--重玩一遍-->
    <div class="foot">
        <button class="replay"><a>重玩一遍</a></button>
    </div>
</div>
<script type="text/javascript" src="index.js"></script>
</body>
</html>

二、css部分

经过了第一步的搭建游戏框架,第二部就是给游戏添加样式,使它能显示出来

*{
    padding: 0px;
    margin: 0px auto;
    font-family: Arial;

}
/*最外部的大框*/
.outermost{
    width: 480px;
    height: 600px;
    font-size: 40px;
    margin-top: 120px;
}
/*title*/
<!--顶部显示分数的样式-->
.top{
    margin: auto;
}
.top span{
    color: red;
}
/*游戏大框框*/
.big{
    width: 480px;
    height: 480px;
    background:pink;
    border-radius: 8px;
}
<!--给每一个盒子包裹的小框子添加样式-->
.cell{
    list-style: none;
    float: left;
    display: inline-block;
    width: 100px;
    height: 100px;
    line-height: 100px;
    text-align: center;
    background-color: #fbf8cd;
    margin-left: 16px;
    margin-top: 16px;
    border-radius: 6px;
}
<!--提前把出现的数24816等的数所在的格子给添加好样式增加游戏体验感-->
.n2{background-color:#f65e3b;color:#776e65}
.n4{background-color:#33b5e5;color:#776e65}
.n8{background-color:#f2b179;color:#776e65}
.n16{background-color:#f59563;color:#776e65}
.n32{background-color:#f67c5f;color:#776e65}
.n64{background-color:#f65e3b;color:#776e65}
.n128{background-color:#edcf72;color:#776e65}
.n256{background-color:#edcc61;color:#776e65}
.n512{background-color:#9c0;color:#776e65}
.n1024{background-color:#33b5e5;color:#776e65;font-size:40px}
.n2048{background-color:#09c;color:#776e65;font-size:40px}
/*提示框样式*/
.tips{
    border: 1px solid #cccccc;
    background: #FFFFFF;
    width: 400px;
    height: 200px;
    border-radius: 10px;
    color: #ff4456;
    text-align: center;
    line-height: 60px;
    position: absolute;
    top: 50%;
    left: 50%;
    margin-left: -200px;
    margin-top: -100px;
    display: none;
}
.tips .startbtn{
    height: 50px;
    width: 200px;
    color: #FFFFFF;
    font-size: 20px;
    line-height: 50px;
    border-radius: 10px;
    background: cornflowerblue;
    border: none;
}
/*重玩一遍*/
.foot{
    width: 200px;
    height: 50px;
}
.foot>.replay{
    width: 200px;
    height: 50px;
    background: aquamarine;
    margin-top: 60px;
    color: lightpink;
    border:0;
    font-size: 24px;
    font-weight: bold;
    border-radius: 6px;
}

书写好了HTML+CSS部分游戏的模样也就出来了,如下图所示:

三、JS部分

下面就到了最后也是最关键的一步----添加行为,也就是JS部分的书写,给其添加效果

//创建一个对象,里面存储所有的游戏数据及游戏方法
var game = {
	data : [],   //定义一个数组,用来存所有的游戏的数据
	score : 0,   //定义一个分数的属性
	gamerunning : 1,   //定义一个游戏运行的状态,将其设置为1与其他状态区分开
	gameover : 0,     //定义一个游戏结束的状态
	status : 0,      //这个是目前游戏的状态,时刻的跟上面两个状态做比较,确定游戏处于运行或者结束
	start : function(){   //游戏开始时候的方法
//		游戏开始的时候肯定是要把游戏的状态设置成游戏运行的状态
//		this == game
		this.status = this.gamerunning;
//		游戏开始的时候分数清空
		this.score = 0;
//		数组中的所有元素全部设置成0
		this.data = [
			[0,0,0,0],
			[0,0,0,0],
			[0,0,0,0],
			[0,0,0,0]
		];
		this.randomNum();//调用下面自定义的随机函数,可以在移动和开始的时候随机出来一个数
		this.randomNum();//调用两次是因为这是游戏开始时的方法,开局随机出现两个数和位置,因此需要调用两次
		this.dataView();//调用下面所写的更新视图的方法
	},
	
	
//	随机数的函数,开始的时候随机生成,移动的时候随机生成
	randomNum: function(){
		while(true){
			//		随机生成行和列 0 - 3随机整数
			var r = Math.floor( Math.random() * 4 );   //随机生成一个行
			var c = Math.floor( Math.random() * 4 );   //随机生成一个列
			
			if(this.data[r][c] == 0){
				var num = Math.random() > 0.5 ? 2 : 4;//随机出现2或4
				this.data[r][c] = num;
				break;
			}
		}
	},
	
//	更新试图的方法
	dataView: function(){
//		大的循环,然后把所有的元素全部遍历一遍
		for(var r = 0; r < 4; r++){
			for(var c = 0; c < 4; c++){
//				找到对应的div
				var div = document.getElementById("c" + r + c);  //字符串拼接
				if(this.data[r][c] != 0){
//					数组中对应的内容放到格子上面去
					div.innerHTML = this.data[r][c];
//					样式也写成对应的
					div.className = "cell n" + this.data[r][c];
				}else{
					div.innerHTML = "";
					div.className = "cell"
				}
			}
		}
		
//		更新分数
		document.getElementById("score01").innerHTML = this.score;
		//游戏没有结束的时候 弹出层时刻都是隐藏的
		if(this.status == this.gamerunning){
			document.getElementById("gameover").style.display = "none";
		}else{
			document.getElementById("gameover").style.display = "block";
			document.getElementById("score02").innerHTML = this.score;
		}
	},
	
//	判断游戏是否结束的方法
	isgameover: function(){
		for(var r = 0; r < 4; r++){
			for(var c = 0; c < 4; c++){
				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;
	},
	

//移动的方法,左 右 上 下四个部分

	
//	左 右 上 下
//	左移的方法
	moveLeft: function(){
		var before = String(this.data);   //之前做一次转换
//		具体的移动需要处理的逻辑,直接处理好每一行即可
		for(var r = 0;r < 4;r ++){
			this.moveLeftInRow(r);
		}
		var after = String(this.data);  //移动之后再做一次转换
//		如果说移动之前不等于移动之后,肯定是发生了移动
		if(before != after){
			this.randomNum();   //生成随机数
//			生成的随机数可能会造成游戏的gameover
			if(this.isgameover()){
//				改变游戏的状态
				this.status = this.gameover
			}
//			更新视图
			this.dataView();
		}
	},
	moveLeftInRow: function(r){   //只去做处理每一行的逻辑
		for(var c = 0; c < 3; c++){
			var nextc = this.getNextinRow(r,c);
			if(nextc != -1){
				if(this.data[r][c] == 0){
//					如果等于0,直接替换
					this.data[r][c] = this.data[r][nextc];
					this.data[r][nextc] = 0;  //位置恢复成0
					c --;   //要让位置恢复到原地
				}else if(this.data[r][c] == this.data[r][nextc]){
					this.data[r][c] *= 2;   //位置直接翻一倍
					this.data[r][nextc] = 0;
					this.score += this.data[r][c];  //更新分数
				}
			}else{   //没有找到
				break;   //直接退出循环
			}
		}
	},
	getNextinRow: function(r,c){
		for(var i = c + 1; i < 4; i++){
			if(this.data[r][i] != 0){
				return i;    //表示已经找到位置,并且把位置返回出来
			}
		}
		return -1;   //返回一个标识符
	},
//	右移的方法
	moveRight: function(){
		var before = String(this.data);
		for(var r = 0; r < 4; r++){
			this.moveRightInRow(r);
		}
		var after = String(this.data);
		if(before != after){
			this.randomNum();
			if(this.isgameover()){
				this.status = this.gameover;
			}
			this.dataView();
		}
	},
	moveRightInRow: function(r){
		for(var c = 4; c > 0; c--){
			var prevc = this.getPrevInRow(r,c);
			if(prevc != -1){
				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.data[r][prevc] = 0;
					this.score += this.data[r][c];
				}
			}else{
				break;
			}
		}
	},
	getPrevInRow: 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 < 4; c++){
			this.moveUpInCol(c);
		}
		var after = String(this.data);
		if(before != after){
			this.randomNum();
			if(this.isgameover()){
				this.status = this.gameover;
			}
			this.dataView();
		}
	},
	moveUpInCol: function(c){
		for(var r = 0;r < 4; r++){
			var nextr = this.getNextInCol(r,c);
			if(nextr != -1){
				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.data[nextr][c] = 0;
					this.score += this.data[r][c];
				}
			}else{
				break;
			}
		}
	},
	getNextInCol: function(r,c){
		for(var i = r + 1; i < 4; i++){
			if(this.data[i][c] != 0){
				return i;
			}
		}
		return -1;
	},
//	下移的方法
	moveDown: function(){
		var before = String(this.data);
		for(var c = 0;c < 4; c++){
			this.moveDownInCol(c);
		}
		var after = String(this.data);
		if(before != after){
			this.randomNum();
			if(this.isgameover()){
				this.status = this.gameover;
			}
			this.dataView();
		}
	},
	moveDownInCol: function(c){
		for(var r = 3; r > 0; r--){
			var prev = this.getPrevIncol(r,c);
			if(prev != -1){
				if(this.data[r][c] == 0){
					this.data[r][c] = this.data[prev][c];
					this.data[prev][c] = 0;
					r -- ;
				}else if(this.data[r][c] == this.data[prev][c]){
					this.data[r][c] *= 2;
					this.data[prev][c] = 0;
					this.score += this.data[r][c];
				}
			}else{
				break;
			}
		}
	},
	getPrevIncol: function(r,c){
		for(var i = r - 1; i >= 0; i--){
			if(this.data[i][c] != 0){
				return i;
			}
		}
		return -1;
	},
	
	
	
}
game.start();
console.log(game.data)
console.log(game.status);
console.log(game.score);
//键盘事件
document.onkeydown = function(){
	if(event.keyCode == 37){
		//console.log("左")
		game.moveLeft();
	}else if(event.keyCode == 38){
		//console.log("上")
		game.moveUp()
	}else if(event.keyCode == 39){
		//console.log("右")
		game.moveRight()
	}else if(event.keyCode == 40){
		//console.log("下")
		game.moveDown()
	}
}
//touch事件
//手指按下
var startX;//设定开始起始位置的x坐标
var startY;//设定开始起始位置的y坐标
var endX;//设定结束滑动位置的x坐标
var endY;//设定结束滑动位置的y坐标
document.addEventListener('touchstart',function(){
//	console.log("手指按下了屏幕")
	console.log(event);
	startX = event.touches[0].pageX;
	startY = event.touches[0].pageY;
})
//手指移动
//document.addEventListener('touchmove',function(){
//	console.log("手指的移动")
//})
//手指松开
document.addEventListener("touchend",function(){
//	console.log("手指松开")
	console.log(event);
	endX = event.changedTouches[0].pageX;//如何获取结束时的位置x
	endY = event.changedTouches[0].pageY;
	var X = endX - startX;
	var Y = endY - startY
	var absX = Math.abs(X) > Math.abs(Y);
	var absY = Math.abs(Y) > Math.abs(X);
	if(X > 0 && absX){
		console.log("右滑动")
		game.moveRight()
	}else if(X < 0 && absX){
		console.log("左滑动")
		game.moveLeft()
	}if(Y > 0 && absY){
		console.log("下滑动")
		game.moveDown()
	}if(Y < 0 && absY){
		console.log("上滑动")
		game.moveUp()
	}
})

如下为游戏效果图

就这样一个简单的2048游戏就完成啦

关注我,下期讲解如何将这个2048 打包到手机上,变成手机小游戏!!!!