JavaScript实现2048

HTML部分

<div class="shell">
		<div class="score">SCORE:<span id="score1">0</span></div>
		<div class="wrapper" id="wrapper">
			<div class="cell" id="n00"></div>
			<div class="cell" id="n01"></div>
			<div class="cell" id="n02"></div>
			<div class="cell" id="n03"></div>
			<div class="cell" id="n10"></div>
			<div class="cell" id="n11"></div>
			<div class="cell" id="n12"></div>
			<div class="cell" id="n13"></div>
			<div class="cell" id="n20"></div>
			<div class="cell" id="n21"></div>
			<div class="cell" id="n22"></div>
			<div class="cell" id="n23"></div>
			<div class="cell" id="n30"></div>
			<div class="cell" id="n31"></div>
			<div class="cell" id="n32"></div>
			<div class="cell" id="n33"></div>
		</div>
	</div>
	<div class="game_over">
		<div>
			<span>GAME</span>
			<span>OVER</span>
			<br>
			<span class='sc_span'>SCORE:</span>
			<span id="score2">0</span>
			<br>
			<a href="javascript:game.start()">try again!</a>
		</div>
	</div>

CSS部分

body{
	margin: 0;
	padding: 0;
}
div,a{
	text-decoration: none;
	box-sizing: border-box;
	border-radius: 10px;
}
.shell{
	width: 500px;
	margin:100px auto;
	/*position: relative;*/
}
/*大格子*/
.wrapper{
	width: 435px;
	height: 435px;
	margin: auto; 
	background-color: #bbada0;
}
/*小格子*/
.wrapper>div{
	width: 90px;
	height: 90px;
	float: left;
	margin-left: 15px;
	margin-top: 15px;
	border-radius: 5px;
	background-color: #ccc0b3;
	color: white;
	font-weight: bold;
	line-height: 90px;
	text-align: center; 
	font-size: 40px;
}
/*分数*/
.score,#score1{
	font-size: 50px;
	font-weight: bold;
	font-family: 'Arial';
	margin-left: 30px;
}
#score1{
	color: red;
}
/*游戏结束后的弹出框*/
.game_over{
	position: absolute;
	top: 0;
	left: 0;
	right: 0;
	bottom: 0;
	background-color: rgba(33,33,33,0.3);
	display: none;
}
/*弹出框内的文字*/
.game_over>div{
	width: 365px;
	height: 150px;
	font-size: 30px;
	font-weight: bold;
	position: absolute;
	top: 50%;
	left: 50%;
	margin-top: -75px;
	margin-left: -182px;
	text-align: center;
	background-color: white;
	border: 1px solid black;
}
/*弹出框内的按钮*/
.game_over a{
	display: inline-block;
	width: 150px;
	height: 45px;
	background-color: #bbada0;
	text-align: center;
	line-height: 39px;
	color: white;
	font-weight: bold;
	font-size: 27px;
	margin-top: 10px;
	border-radius: 5px;
}
/*数字样式*/
.wrapper>.n2{
	background-color:#eee3da;
	color:#776e65;
}
.wrapper>.n4{
	background-color:#ede0c8;
	color:#776e65
}
.wrapper>.n8{background-color:#f2b179}
.wrapper>.n16{background-color:#f59563}
.wrapper>.n32{background-color:#f67c5f}
.wrapper>.n64{background-color:#f65e3b}
.wrapper>.n128{background-color:#edcf72}
.wrapper>.n256{background-color:#edcc61}
.wrapper>.n512{background-color:#9c0}
.wrapper>.n1024{background-color:#33b5e5;font-size:30px}
.wrapper>.n2048{background-color:#09c;font-size:30px}
.wrapper>.n4096{background-color:#a6c;font-size:30px}
.wrapper>.n8192{background-color:#93c;font-size:30px}

JS代码部分

var game = {
	// 创建data属性来存放数据
	data : [],
	// 存放分数,并赋初始值为0
	score : 0,
	// 游戏结束状态
	gameover : 0,
	// 游戏进行状态
	gamerunning : 1,
	// 游戏状态
	status : 1,
	// 游戏开始
	start : function(){
		this.status = this.gamerunning;
		this.data = [];
		this.score = 0;
		// 遍历行
		for(var r=0;r<4;r++){
			// 为每一行创建数组以便存放数据
			this.data[r] = [];
			// 遍历列
			for(var c=0;c<4;c++){
				// 为二维数组中的数据都赋初始值为0
				this.data[r][c] = 0;
			}
		}
		// 调用生成随机数的函数
		this.randNum();
		// 再次调用生成随机数的函数,为了使页面中同时出现两个数字
		this.randNum();
		// 调用时数据在页面中显示的函数
		this.displyNum();
		// console.log(this.data)
	},
	// 创建生成随机数的函数
	randNum : function(){
		while(true){
			// 随机行
			var r = Math.floor(Math.random() * 4);
			// 随机列
			var c = Math.floor(Math.random() * 4);
			// 如果任意下标的格子中没有数据
			if(this.data[r][c] == 0){
				// 随机生成2或4
				var num = Math.random() > 0.2 ? 2 : 4;
				// 将随机生成的2或4存放到之前的空格子中
				this.data[r][c] = num;
				break;
			}
		}
	},
	// 使数据在页面中显示的函数
	displyNum : function(){
		// 遍历二维数组
		for(var r = 0;r<4;r++){
			for(var c=0;c<4;c++){
				// 获取页面中id为n[r][c]的格子
				var div = document.getElementById('n' + r + c);
				// 如果下标为r和c的格子中没有数据,
				if(this.data[r][c] == 0){
					// 页面中不显示任何数据,并且样式不会改变
					div.innerHTML = '';
					div.className = 'cell';
				}else{//如果格子中有数据
					// 将数据在页面中显示且样式随之改变
					div.innerHTML = this.data[r][c];
					div.className = 'cell n' + this.data[r][c];
				}
			}
		}
		// 找到分数栏并将最后分数显示在页面中
		document.getElementById('score1').innerHTML = this.score;
		// 如果游戏状态为结束状态
		if(this.status == this.gameover){
			// 将最后分数显示在弹框中的分数栏
			document.getElementById('score2').innerHTML = this.score;
			// 游戏结束时的弹框在页面中显示
			document.getElementsByClassName('game_over')[0].style.display = 'block';
		}else{//否则就依旧隐藏弹框
			document.getElementsByClassName('game_over')[0].style.display = 'none';
		}
	},
	// 判断游戏是否结束
	isend : function(){
		// 遍历二维数组
		for(var r=0;r<4;r++){
			for(var c=0;c<4;c++){
				// 如果还有格子中没有数据
				if(this.data[r][c] == 0){
					// 则游戏状态为未结束
					return false;
				}
				// 如果行下标小于3
				if(r<3){
					// 判断前一个格子中的数据和后一个格子中的数据是否相等,如果相等,则游戏状态为未结束
					 if(this.data[r][c] == this.data[r+1][c]){
					 	return false;
					 }
				}
				// 如果列下标小于3
				if(c<3){
					// 判断上一个格子和下一个格子中的数据是否相等,如果相等,则游戏状态为未结束
					if(this.data[r][c] == this.data[r][c+1]){
						return false;
					}
				}
			}
		}
		// 若以上判断都不符合,则游戏状态为结束
		return true;
	},
	// 左移动
	moveLeft : function(){
		// 因为两个数组比较结果一定为false,所以将二维数字转换为字符串再进行比较
		var before = String(this.data);
		// console.log(this.data)
		// console.log(before)
		// 遍历行
		for(var r=0;r<4;r++){
			// 调用变动一行中每个数据的函数
			this.getLeftIn(r)
		}
		var after = String(this.data)
		// console.log(after)
		// console.log(this.data)
		if(before != after){
			this.randNum();
			if(this.isend()){
				this.status = this.gameover;
			}
			this.displyNum();
		}
	},
	// 变动一行中每个数据
	getLeftIn : function(r){
		// 遍历一行中的每个格子
		for(var c=0;c<3;c++){
			// 创建nextc变量接收getLeftnextIn函数的返回值
			var nextc = this.getLeftnextIn(r,c);
			// 如果nextc不等于-1
			if(nextc != -1){
				// 如果上一个格子中没有数据
				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.data[r][nextc] = 0;
					// 计算总分数
					this.score += this.data[r][c];
				}
			}else{
				break;
			}
		}
	},
	// 得到一行中下一个格子的下标
	getLeftnextIn : function(r,c){
		// 遍历列,i从下标为c的下一个开始,即c+1
		for(var i=c+1;i<4;i++){
			// 如果下标为r和i的格子中数据不为0;
			if(this.data[r][i] != 0){
				// 将下标i返回
				return i;
			}
		}
		// 如果下标i不存在,返回-1
		return -1;
	},
	// 右移动
	moveRight : function(){
		var before = String(this.data);
		for(var r=0;r<4;r++){
			this.getRightIn(r);
		}
		var after = String(this.data);
		if(before != after){
			this.randNum();
			if(this.isend()){
				this.status = this.gameover;
			}
			this.displyNum();
		}
	},
	getRightIn : function(r){
		for(var c=3;c>=0;c--){
			var lastc = this.getRightlastIn(r,c);
			if(lastc != -1){
				if(this.data[r][c] == 0){
					this.data[r][c] = this.data[r][lastc];
					this.data[r][lastc] = 0;
					c++;
				}else if(this.data[r][c] == this.data[r][lastc]){
					this.data[r][c] *= 2;
					this.data[r][lastc] = 0;
					this.score += this.data[r][c];
				}
			}else{
				break;
			}
		}
	},
	getRightlastIn : 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);
		// console.log(this.data)
		// console.log(before)
		for(var c=0;c<4;c++){
			this.getUpIn(c)
		}
		var after = String(this.data)
		// console.log(after)
		// console.log(this.data)
		if(before != after){
			this.randNum();
			if(this.isend()){
				this.status = this.gameover;
			}
			this.displyNum();
		}
	},
	getUpIn : function(c){
		for(var r=0;r<3;r++){
			var nextr = this.getUpnextIn(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;
			}
		}
	},
	getUpnextIn : 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.getDownIn(c);
		}
		var after = String(this.data);
		if(before != after){
			this.randNum();
			if(this.isend()){
				this.status = this.gameover;
			}
			this.displyNum();
		}
	},
	getDownIn : function(c){
		for(var r=3;r>=0;r--){
			var lastr = this.getDownlastIn(r,c);
			if(lastr != -1){
				if(this.data[r][c] == 0){
					this.data[r][c] = this.data[lastr][c];
					this.data[lastr][c] = 0;
					r++;
				}else if(this.data[r][c] == this.data[lastr][c]){
					this.data[r][c] *= 2;
					this.data[lastr][c] = 0;
					this.score += this.data[r][c];
				}
			}else{
				break;
			}
		}
	},
	getDownlastIn : function(r,c){
		for(var i=r-1;i>=0;i--){
			if(this.data[i][c] != 0){
				return i;
			}
		}
		return -1;
	}

}
game.start()
// 键盘上下左右
document.onkeydown = function(event){
	var event = event || e || arguments[0];
	if(event.keyCode == 37){
		game.moveLeft();
	}else if(event.keyCode == 39){
		game.moveRight();
	}else if(event.keyCode == 38){
		game.moveUp();
	}else if(event.keyCode == 40){
		game.moveDown();
	}

}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值