JS实现2048小游戏

本文介绍了如何使用JavaScript实现经典游戏2048。游戏界面包括开始时的页面和游戏结束后的得分展示,支持在PC和移动端运行。内容涵盖HTML结构、CSS样式和JavaScript逻辑实现。
摘要由CSDN通过智能技术生成

js实现2048小游戏

开始时的页面
在这里插入图片描述
当游戏结束时会显示得分情况并可以再试一次
在这里插入图片描述
HTML部分

<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title>2048小游戏</title>
		<link rel="stylesheet" href="style.css" />
		<meta name="viewport" content="withd=device-width,initial-scale=0.8,user-scalable=no"/>
	</head>
	<body>
		<p class="header">SCORE:<span id="score01">0</span></p>
		<div class="all">
			<!--第一行-->
			<div class="cell n2" id="c00">2</div>
			<div class="cell n4" id="c01">4</div>
			<div class="cell n8" id="c02">8</div>
			<div class="cell n16" id="c03">16</div>
			<!--第二行-->
			<div class="cell n32" id="c10">32</div>
			<div class="cell n64" id="c11">64</div>
			<div class="cell n1024" id="c12">1024</div>
			<div class="cell n2048" id="c13">2048</div>
			<!--第三行-->
			<div class="cell n4096" id="c20">4096</div>
			<div class="cell n8192" id="c21">8192</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="gameover" id="gameover">
				<p>
					GAME OVER!
					<br />
					SCORE: <span id="score02">0</span>
					<br />
					<a href="javascript:game.start()">TRY AGAIN</a>
				</p>
		</div>	
		<script src="index.js"></script>
	</body>
</html>

CSS样式部分

*{
	margin: 0;
	padding: 0;
	user-select: none;
	font-family: Arial;
}
.header{
	font-size: 50px;
	font-weight: bold;
	width: 480px;
	margin: 0 auto;
}
.header span{
	color: #f00;
}
.all{
	background-color: #bbada0;
	width: 480px;
	height: 480px;
	margin: 0 auto;
	border-radius: 10px;
}
.cell{
	width: 100px;
	height: 100px;
	background-color: #ccc0b3;
	border-radius: 5px;
	float: left;
	margin: 16px 0 0 16px;
	
	
	line-height: 100px;
	text-align: center;
	font-size: 50px;
	color: #fff;
}
.n2{background-color:#eee3da;color:#776e65}
.n4{background-color:#ede0c8;color:#776e65}
.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;font-size:40px}
.n2048{background-color:#09c;font-size:40px}
.n4096{background-color:#a6c;font-size:40px}
.n8192{background-color:#93c;font-size:40px}

.gameover{
	position: absolute;
	top: 0;
	bottom: 0;
	left: 0;
	right: 0;
	background-color: rgba(0,0,0,.3);
	display: none;
}
.gameover p{
	width: 300px;
	height: 200px;
	text-align: center;
	font-size: 40px;
	font-weight: bold;
	background-color: #fff;
	border: 1px solid #000;
	border-radius: 10px;
	line-height: 66.66px;
	position: absolute;
	top: 50%;
	left: 50%;
	margin-left: -150px;
	margin-top: -100px;
}
.gameover p a{
	text-decoration: none;
	color: #fff;
	background-color: #9f8d77;
	padding: 10px;
	border-radius: 10px;	
}

js部分

//[
//	[2,4,8,16],
//	00 01 02 03
//	[32,64,128,0],
//	10  11  12 13
//	[0,16,32,64],
//	20  21 22 23
//	[0,0,2,0]
//	30 31 32 33
//]
//面向对象编程     设计模式-单例模式
//创建一个对象,里面存储所有的游戏数据及游戏方法
var game = {
	data : [],   //定义一个数组,用来存所有的游戏的数据
	score : 0,   //定义一个分数的属性
	gamerunning : 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.3 ? 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;
var startY;
var endX;
var endY;
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;
	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()
	}
})

这个既可以在PC端使用,也可以打包成APP在手机端使用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值