html + css + js使用HBuilder开发工具做2048益智游戏

2048–>html + css + js使用HBuilder开发工具做2048益智游戏

今天使用html + css + js给同学们做了一个简易版的2048益智游戏,希望大家按照步骤勤加练习,在编码的坑里早日踏上康庄大道,祝前程似锦!

效果图:
html + css + js使用HBuilder开发工具做2048益智游戏_第1张图片
附源码github链接:
https://github.com/LittleGreyKing-FriedBlackYoFeed-xoox/2048.git

开发思路:

一、使用HBuilder工具创建空白html项目
html + css + js使用HBuilder开发工具做2048益智游戏_第2张图片
创建项目时路径尽量不要有中文路径
html + css + js使用HBuilder开发工具做2048益智游戏_第3张图片

二、创建js和css文件备用
html + css + js使用HBuilder开发工具做2048益智游戏_第4张图片
html + css + js使用HBuilder开发工具做2048益智游戏_第5张图片
项目目录:
html + css + js使用HBuilder开发工具做2048益智游戏_第6张图片

三、书写html标签
引入css和js文件:
html + css + js使用HBuilder开发工具做2048益智游戏_第7张图片
书写html标签:
html + css + js使用HBuilder开发工具做2048益智游戏_第8张图片
html + css + js使用HBuilder开发工具做2048益智游戏_第9张图片
html + css + js使用HBuilder开发工具做2048益智游戏_第10张图片
html标签的代码,直接放在body标签中即可:

index.html

<header>
			<h1>2048</h1>
		</header>
		<div id="gamePanel">
			<p><a class="button" id="newGame">New Game</a> Score: <span id="score">0</span><span class="writer">小灰灰版</span></p>
			<div id="gridPanel">
				<div class="grid"> </div>
				<div class="grid"> </div>
				<div class="grid"> </div>
				<div class="grid"> </div>

				<div class="grid"> </div>
				<div class="grid"> </div>
				<div class="grid"> </div>
				<div class="grid"> </div>

				<div class="grid"> </div>
				<div class="grid"> </div>
				<div class="grid"> </div>
				<div class="grid"> </div>

				<div class="grid"> </div>
				<div class="grid"> </div>
				<div class="grid"> </div>
				<div class="grid"> </div>

				<div class="cell " id="cell00"> </div>
				<div class="cell " id="cell01"> </div>
				<div class="cell " id="cell02"> </div>
				<div class="cell " id="cell03"> </div>

				<div class="cell " id="cell10"> </div>
				<div class="cell " id="cell11"> </div>
				<div class="cell " id="cell12"> </div>
				<div class="cell " id="cell13"> </div>

				<div class="cell " id="cell20"> </div>
				<div class="cell " id="cell21"> </div>
				<div class="cell " id="cell22"> </div>
				<div class="cell " id="cell23"> </div>

				<div class="cell " id="cell30"> </div>
				<div class="cell " id="cell31"> </div>
				<div class="cell " id="cell32"> </div>
				<div class="cell " id="cell33"> </div>

			</div>
			<div id="gameOver">
				<div>
					<!--背景 -->
				</div>
				<p>
					<!-- 前景 -->
					Game Over!<br>
					Score: <span id="finalScore">0</span><br>
					<a class="button" id="restart">Try Again!</a>
				</p>
			</div>
		</div>

四、绘制css样式表
html + css + js使用HBuilder开发工具做2048益智游戏_第11张图片
2048.css


* {
	padding: 0;
	margin: 0;

}

div,
p,
h1,
h2,
a,
span {
	font-family: Arial;
	font-weight: bold;
}

header {
	padding-top: 16px;
}

h1 {
	font-size: 40px;
	font-weight: bold;
	text-align: center;
}

#gamePanel {
	margin: 0 auto;
	width: 500px;
	position: relative;
}

#gridPanel {
	width: 480px;
	height: 480px;
	background: #BBADA0;
	border-radius: 10px;
	padding: 20px 0 0 20px;
	position: relative;
}

#gamePanel p {
	padding: 8px;
}

/* 按钮样式 */
.button {
	display: inline-block;
	padding: 10px;
	background: #9F8B77;
	border-radius: 6px;
	color: #FFF;
	cursor: pointer;
}

.grid,
.cell {
	width: 100px;
	height: 100px;
	border-radius: 6px;
}

/* 背景网格 */
#gamePanel .grid {
	background-color: #ccc0b3;
	float: left;
	margin: 0 20px 20px 0;
}

/* 格式化前景单元格中位置 */
.cell {
	position: absolute;
	line-height: 100px;
	vertical-align: middle;
	text-align: center;
	font-size: 60px;
	color: #776E65;
}

/* 前景格中的行位置 */
#cell00,
#cell01,
#cell02,
#cell03 {
	top: 20;
}

#cell10,
#cell11,
#cell12,
#cell13 {
	top: 140px;
}

#cell20,
#cell21,
#cell22,
#cell23 {
	top: 260px;
}

#cell30,
#cell31,
#cell32,
#cell33 {
	top: 380px;
}

/* 前景格中的列位置 */
#cell00,
#cell10,
#cell20,
#cell30 {
	left: 20px;
}

#cell01,
#cell11,
#cell21,
#cell31 {
	left: 140px;
}

#cell02,
#cell12,
#cell22,
#cell32 {
	left: 260px;
}

#cell03,
#cell13,
#cell23,
#cell33 {
	left: 380px;
}

/* 数字显示效果 */
.num8,
.num16,
.num32,
.num64,
.num128,
.num256,
.num512,
.num1024,
.num2048,
.num4096,
.num8192 {
	color: #fff;
}

.num1024,
.num2048,
.num4096,
.num8192 {
	font-size: 40px;
}

.num2 {
	background: #eee4da;
}

.num4 {
	background: #ede0c8;
}

.num8 {
	background: #f2b179;
}

.num16 {
	background: #f59563;
}

.num32 {
	background: #f67c5f;
}

.num64 {
	background: #f65e3b;
}

.num128 {
	background: #edcf72;
}

.num256 {
	background: #edcc61;
}

.num512 {
	background: #9c0;
}

.num1024 {
	background: #33b5e5;
}

.num2048 {
	background: #09c;
}

.num4096 {
	background: #a6c;
}

.num8192 {
	background: #93c;
}

/* 格式化Game Over的样式 */
#gameOver {
	display: none;
	position: absolute;
	width: 100%;
	height: 100%;
	top: 0;
	left: 0;
}

#gameOver div {
	width: 100%;
	height: 100%;
	background: #555;
	filter: alpha(Opacity=50);
	-moz-opacity: 0.5;
	opacity: 0.5;
}

#gameOver p {
	position: absolute;
	top: 150px;
	left: 100px;
	border-radius: 10px;
	width: 300px;
	border: 1px solid #EDCF72;
	background: #fff;
	line-height: 1.6em;
	font-size: 30px;
	color: #000;
	text-align: center;
}

.writer {
	width: 80px;
	margin-left: 30%;
}

五、创造JS事件函数

html + css + js使用HBuilder开发工具做2048益智游戏_第12张图片
animation.js

    	//动画效果工具对象
    	var animation = {
    		tasks:[], //动画任务数据
    		timer:null,//动画定时器
			times:10, //定时器次数
			interval:1000/60,//定时器间隔
			add:function(obj, top, left){
				
				//动画已经开始了,不能添加任务了!
				if(this.timer){
					return false;
				}
				if(! obj){
					return false;
				}
				
				//计算移动步伐
				var t = (top - obj.offsetTop)/this.times;
				var l = (left - obj.offsetLeft)/this.times;
				
				//添加动画任务,其中obj是被移动到对象,top, left是移动以后的位置
				var task = {
					topStep:t,
					leftStep:l,
					element:obj,	
					step:function(){
						var t = this.element.offsetTop;
						this.element.style.top = (t+ this.topStep )+"px";
						var l = this.element.offsetLeft;
						this.element.style.left = (l+ this.leftStep )+"px";		
					},
					clear:function(){
						this.element.style.top = "";
						this.element.style.left = "";
					}
				};
				this.tasks[this.tasks.length]=task; 
				return true;
			},
    		start:function(callback){
    			//如果定时器已经启动,就不能再启动定时器了
    			if(this.timer){
    				return false;
    			}

				console.log("STATRING");
				if(this.tasks.length==0){
					if(callback){
						callback();
					}
					return false;	
				}
				
				//如果有callback就交给this.callback
				if(callback){
					this.callback = callback;
				}
				this.timer = setInterval(function(){
					//console.log("timeOut");
					//console.log(animation.times);
					
					for(var i=0; i<animation.tasks.length; i++){
						var task = animation.tasks[i];
						task.step();
					}
					
					animation.times--;
					if(animation.times < 0){
						animation.stop();
					}
				}, this.interval);
				return true;
    		},
    		stop: function(){
    			if(this.timer){
    				window.clearInterval(this.timer);
    				this.timer=null;
    				this.times=10;
    				
    			}
    			
    			//结束以后执行callback()
    			if(this.callback){
    				this.callback();
    			}
				for(var i=0; i<this.tasks.length; i++){
					var task = this.tasks[i];
					task.clear();
				}    			
				this.tasks = [];//清空动画任务
    		},
    		callback:null //动画结束时候执行的方法
    	};

JS的部分还有index.html中包含的:
html + css + js使用HBuilder开发工具做2048益智游戏_第13张图片
index.html 中包含的js部分

<script type="text/javascript">
			//game 封装了2048的数据和核心算法
			var cells = [
				[2, 0, 0, 0],
				[0, 32, 0, 0],
				[0, 4, 0, 0],
				[0, 0, 2048, 0]
			];
			//游戏进行中
			var PLAYING = 0;
			//方块正在移动动画处理中,期间不能响应键盘事件
			var CELL_MOVEING = 1;
			//游戏结束了,结束了就不能响应键盘事件了
			var GAME_OVER = 2;

			var score = 0;

			//当前游戏状态
			var state = PLAYING;

			//动态效果开关,打开后可以绘制方块的移动动画效果
			var effect = true;

			/* 向上的动作, */
			function upAction() {
				if (state == CELL_MOVEING) {
					return false;
				}
				if (!canMoveUp()) {
					return false;
				}
				//每次处理一个列
				for (var col = 0; col < 4; col++) {
					//每一个列中 从放方向判断是否需要移动处理
					upCol(col);
				}
				return true;
			}
			// 处理一个列的移动 
			function upCol(col) {
				//一个列中,按照方方向检查是否需要合并处理。
				for (var row = 0; row < 4;) {
					var current = cells[row][col];
					var nextRow = getNextInCol(col, row + 1, 1);
					//没有下一个,就直接结束了
					if (nextRow == -1) {
						return;
					}
					var next = cells[nextRow][col];

					if (current == 0) {
						//下一个格子移动到当前位置。
						cells[row][col] = next;
						cells[nextRow][col] = 0;
						if (effect) { //如果动效开关打开,就处理动画
							// $("cell"+nextRow+col) 找到下一个对象对应的格子
							var obj = $("cell" + nextRow + col);
							var top = row * 120 + 20;
							var left = col * 120 + 20;
							animation.add(obj, top, left);
						}
					} else if (current == next) {
						//两个格子一样,就合并格子
						cells[row][col] = next + current;
						cells[nextRow][col] = 0;

						score += cells[row][col];

						row++;
						if (effect) { //如果动效开关打开,就处理动画
							// $("cell"+nextRow+col) 找到下一个对象对应的格子
							var obj = $("cell" + nextRow + col);
							var top = row * 120 + 20;
							var left = col * 120 + 20;
							animation.add(obj, top, left);
						}
					} else {
						//下个不一样,就忽略之
						row++;
					}
				}
			}

			function getNextInCol(col, startRow, step) {
				var row = startRow;
				while (true) {
					if (row < 0 || row >= 4) {
						return -1;
					}
					if (cells[row][col] != 0) {
						return row;
					}
					row += step;
				}
			}

			function getNextInRow(row, startCol, step) {
				var col = startCol;
				while (true) {
					if (col < 0 || col >= 4) {
						return -1;
					}
					if (cells[row][col] != 0) {
						return col;
					}
					col += step;
				}
			}

			function downAction() {
				if (state == CELL_MOVEING) {
					return false;
				}
				if (!canMoveDown()) {
					return false;
				}
				//每次处理一个列
				for (var col = 0; col < 4; col++) {
					//每一个列中 从放方向判断是否需要移动处理
					downCol(col);
				}
				return true;
			}
			// 处理一个列的移动
			function downCol(col) {
				//一个列中,按照方方向检查是否需要合并处理。
				for (var row = 3; row >= 0;) {
					var current = cells[row][col];
					var nextRow = getNextInCol(col, row - 1, -1);
					//没有下一个,就直接结束了
					if (nextRow == -1) {
						return;
					}
					var next = cells[nextRow][col];

					if (current == 0) {
						//下一个格子移动到当前位置。
						cells[row][col] = next;
						cells[nextRow][col] = 0;
						if (effect) { //如果动效开关打开,就处理动画
							// $("cell"+nextRow+col) 找到下一个对象对应的格子
							var obj = $("cell" + nextRow + col);
							var top = row * 120 + 20;
							var left = col * 120 + 20;
							animation.add(obj, top, left);
						}
					} else if (current == next) {
						//两个格子一样,就合并格子
						cells[row][col] = next + current;
						cells[nextRow][col] = 0;

						score += cells[row][col];

						row--;

						if (effect) { //如果动效开关打开,就处理动画
							// $("cell"+nextRow+col) 找到下一个对象对应的格子
							var obj = $("cell" + nextRow + col);
							var top = row * 120 + 20;
							var left = col * 120 + 20;
							animation.add(obj, top, left);
						}
					} else {
						//下个不一样,就忽略之
						row--;
					}
				}
			}

			function leftAction() {
				if (state == CELL_MOVEING) {
					return false;
				}
				if (!canMoveLeft()) {
					return false;
				}
				//每次处理一个行
				for (var row = 0; row < 4; row++) {
					//每一个行中 从放方向判断是否需要移动处理
					moveLeft(row);
				}
				return true;
			}
			// 处理一个列的移动
			function moveLeft(row) {
				//一个列中,按照方方向检查是否需要合并处理。
				for (var col = 0; col < 4;) {
					var current = cells[row][col];
					var nextCol = getNextInRow(row, col + 1, 1);
					//没有下一个,就直接结束了
					if (nextCol == -1) {
						return;
					}
					var next = cells[row][nextCol];

					//console.log("next:"+next);
					//console.log("current:"+current);

					if (current == 0) {
						//下一个格子移动到当前位置。
						cells[row][col] = next;
						cells[row][nextCol] = 0;
						if (effect) { //如果动效开关打开,就处理动画
							// $("cell"+nextRow+col) 找到下一个对象对应的格子
							var obj = $("cell" + row + nextCol);
							var top = row * 120 + 20;
							var left = col * 120 + 20;
							animation.add(obj, top, left);
						}
					} else if (current == next) {
						//两个格子一样,就合并格子
						cells[row][col] = next + current;
						cells[row][nextCol] = 0;

						score += cells[row][col];

						col++;
						if (effect) { //如果动效开关打开,就处理动画
							// $("cell"+nextRow+col) 找到下一个对象对应的格子
							var obj = $("cell" + row + nextCol);
							var top = row * 120 + 20;
							var left = col * 120 + 20;
							animation.add(obj, top, left);
						}
					} else {
						//下个不一样,就忽略之
						col++;
					}
				}
			}

			function rightAction() {
				if (state == CELL_MOVEING) {
					return false;
				}
				if (!canMoveRight()) {
					return false;
				}
				//每次处理一个行
				for (var row = 0; row < 4; row++) {
					//每一个行中 从放方向判断是否需要移动处理
					moveRight(row);
				}
				return true;
			}
			// 处理一个列的移动
			function moveRight(row) {
				//一个列中,按照方方向检查是否需要合并处理。
				for (var col = 3; col >= 0;) {
					var current = cells[row][col];
					var nextCol = getNextInRow(row, col - 1, -1);
					//没有下一个,就直接结束了
					if (nextCol == -1) {
						return;
					}
					var next = cells[row][nextCol];

					//console.log("next:"+next);
					//console.log("current:"+current);

					if (current == 0) {
						//下一个格子移动到当前位置。
						cells[row][col] = next;
						cells[row][nextCol] = 0;
						if (effect) { //如果动效开关打开,就处理动画
							// $("cell"+nextRow+col) 找到下一个对象对应的格子
							var obj = $("cell" + row + nextCol);
							var top = row * 120 + 20;
							var left = col * 120 + 20;
							animation.add(obj, top, left);
						}
					} else if (current == next) {
						//两个格子一样,就合并格子
						cells[row][col] = next + current;
						cells[row][nextCol] = 0;


						score += cells[row][col];

						col--;

						if (effect) { //如果动效开关打开,就处理动画
							// $("cell"+nextRow+col) 找到下一个对象对应的格子
							var obj = $("cell" + row + nextCol);
							var top = row * 120 + 20;
							var left = col * 120 + 20;
							animation.add(obj, top, left);
						}
					} else {
						//下个不一样,就忽略之
						col--;
					}
				}
			}

			function canMoveUp() {
				for (var col = 0; col < 4; col++) {
					for (var row = 1; row < 4; row++) {
						//格子上方是空位置, 可以移动
						if (cells[row][col] != 0 && cells[row - 1][col] == 0) {
							return true;
						}
						//格子上方相邻的相等,可以移动
						if (cells[row][col] != 0 && (cells[row][col] == cells[row - 1][col])) {
							return true;
						}
					}
				}
				return false;
			}

			function canMoveDown() {
				for (var col = 0; col < 4; col++) {
					for (var row = 0; row < 3; row++) {
						//格子上方是空位置, 可以移动
						if (cells[row][col] != 0 && cells[row + 1][col] == 0) {
							return true;
						}
						//格子上方相邻的相等,可以移动
						if (cells[row][col] != 0 && (cells[row][col] == cells[row + 1][col])) {
							return true;
						}
					}
				}
				return false;
			}

			function canMoveLeft() {
				for (var col = 1; col < 4; col++) {
					for (var row = 0; row < 4; row++) {
						//格子上方是空位置, 可以移动
						if (cells[row][col] != 0 && cells[row][col - 1] == 0) {
							return true;
						}
						//格子上方相邻的相等,可以移动
						if (cells[row][col] != 0 && (cells[row][col] == cells[row][col - 1])) {
							return true;
						}
					}
				}
				return false;
			}

			function canMoveRight() {
				for (var col = 0; col < 3; col++) {
					for (var row = 0; row < 4; row++) {
						//格子上方是空位置, 可以移动
						if (cells[row][col] != 0 && cells[row][col + 1] == 0) {
							return true;
						}
						//格子上方相邻的相等,可以移动
						if (cells[row][col] != 0 && (cells[row][col] == cells[row][col + 1])) {
							return true;
						}
					}
				}
				return false;
			}


			function test() {
				rightAction();
				state = CELL_MOVEING;
				animation.start(function() {
					//console.log("update");
					randomNumber();
					updateView();
					state = PLAYING;
				});
			}

			//更新显示,将表格中的数据,更新到界面显示
			function updateView() {
				for (var row = 0; row < 4; row++) {
					for (var col = 0; col < 4; col++) {
						var n = cells[row][col];
						var cell = $("cell" + row + col);
						//清楚显示的数据和显示样式
						cell.className = "cell";
						cell.innerHTML = "";
						if (n > 0) {
							//更新显示样式
							cell.className = "cell num" + n;
							//更新显示的数字
							cell.innerHTML = n;
						}
					}
				}

				$("score").innerHTML = score;
				$("finalScore").innerHTML = score;

			}
			//检查当前的表格中是否是满的,如果满了返回true,否则返回false
			function full() {
				for (var row = 0; row < 4; row++) {
					for (var col = 0; col < 4; col++) {
						if (cells[row][col] == 0) {
							return false;
						}
					}
				}
				return true;
			}
			//向表格随机插入一个数字,如果插入成功返回true,插入失败返回false
			function randomNumber() {
				if (full()) {
					return false;
				}
				while (true) {
					var col = parseInt(Math.random() * 4);
					var row = parseInt(Math.random() * 4);
					if (cells[row][col] == 0) {
						var n = Math.random() < 0.5 ? 2 : 4;
						cells[row][col] = n;
						return true;
					}
				}
			}

			function startAction() {
				$("gameOver").style.display = "none";
				for (var row = 0; row < 4; row++) {
					for (var col = 0; col < 4; col++) {
						cells[row][col] = 0;
					}
				}
				score = 0;
				randomNumber();
				randomNumber();
				updateView();
				state = PLAYING;
			}
			//元素查询方法
			function $(id) {
				return document.getElementById(id);
			}

			function has8192() {
				for (var row = 0; row < 4; row++) {
					for (var col = 0; col < 4; col++) {
						if (cells[row][col] == 8192) {
							return true;
						}
					}
				}
			}

			function hasSpace() {
				for (var row = 0; row < 4; row++) {
					for (var col = 0; col < 4; col++) {
						if (cells[row][col] == 0) {
							return true;
						}
					}
				}
			}


			/* 显示游戏结束界面 */
			function gameOver() {
				//发现8192游戏结束
				if (has8192()) {
					state = GAME_OVER;
					$("gameOver").style.display = "block";
					return true;
				}

				//发现空位置,游戏不结束    	
				if (hasSpace()) {
					return false;
				}

				//能够移动游戏不结束
				if (canMoveUp() || canMoveDown() || canMoveLeft() || canMoveRight()) {
					return false;
				}
				state = GAME_OVER;
				$("gameOver").style.display = "block";
				return true;
			}

			//软件启动初始代码
			window.onload = function() {
				$("newGame").onclick = function() {
					if (state == PLAYING)
						startAction();
				}
				$("restart").onclick = function() {
					if (state == GAME_OVER)
						startAction();
				}
				startAction();
				//监听键盘事件
				document.onkeydown = function(event) {
					if (state != PLAYING) {
						return;
					}
					var move = false;
					switch (event.keyCode) {
						case 37: //left
							move = leftAction();
							break;
						case 38: //up
							move = upAction();
							break;
						case 39: //right
							move = rightAction();
							break;
						case 40: //down
							move = downAction();
							break;
					}
					if (!move) {
						return;
					}
					if (effect) {
						state = CELL_MOVEING;
						animation.start(function() {
							//console.log("update");
							updateView();
							state = PLAYING;
							if (!gameOver()) {
								setTimeout(function() {
									randomNumber();
									updateView();
								}, 100);
							}
						});
					} else {
						if (!gameOver()) {
							setTimeout(function() {
								randomNumber();
								updateView();
							}, 100);
						}

						updateView();
						state = PLAYING;
					}
					gameOver();
				}; // 5211 0842 8479 快捷快递
			}
		</script>

六、测试和运行

配置和运行时记得要打开index.html再执行。
html + css + js使用HBuilder开发工具做2048益智游戏_第14张图片
html + css + js使用HBuilder开发工具做2048益智游戏_第15张图片
html + css + js使用HBuilder开发工具做2048益智游戏_第16张图片
html + css + js使用HBuilder开发工具做2048益智游戏_第17张图片
完毕。

七、懒人版全部源码

很多同学喜欢html 和 css 和 js都放在同一个文件中,我给大家也做了一个懒人版的2048,以下提供源码:

2048.html

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8" />
		<title>2048-懒人版</title>
		<!-- 2048.css -->
		<style type="text/css">
			* {
				padding: 0;
				margin: 0;
			
			}
			
			div,
			p,
			h1,
			h2,
			a,
			span {
				font-family: Arial;
				font-weight: bold;
			}
			
			header {
				padding-top: 16px;
			}
			
			h1 {
				font-size: 40px;
				font-weight: bold;
				text-align: center;
			}
			
			#gamePanel {
				margin: 0 auto;
				width: 500px;
				position: relative;
			}
			
			#gridPanel {
				width: 480px;
				height: 480px;
				background: #BBADA0;
				border-radius: 10px;
				padding: 20px 0 0 20px;
				position: relative;
			}
			
			#gamePanel p {
				padding: 8px;
			}
			
			/* 按钮样式 */
			.button {
				display: inline-block;
				padding: 10px;
				background: #9F8B77;
				border-radius: 6px;
				color: #FFF;
				cursor: pointer;
			}
			
			.grid,
			.cell {
				width: 100px;
				height: 100px;
				border-radius: 6px;
			}
			
			/* 背景网格 */
			#gamePanel .grid {
				background-color: #ccc0b3;
				float: left;
				margin: 0 20px 20px 0;
			}
			
			/* 格式化前景单元格中位置 */
			.cell {
				position: absolute;
				line-height: 100px;
				vertical-align: middle;
				text-align: center;
				font-size: 60px;
				color: #776E65;
			}
			
			/* 前景格中的行位置 */
			#cell00,
			#cell01,
			#cell02,
			#cell03 {
				top: 20;
			}
			
			#cell10,
			#cell11,
			#cell12,
			#cell13 {
				top: 140px;
			}
			
			#cell20,
			#cell21,
			#cell22,
			#cell23 {
				top: 260px;
			}
			
			#cell30,
			#cell31,
			#cell32,
			#cell33 {
				top: 380px;
			}
			
			/* 前景格中的列位置 */
			#cell00,
			#cell10,
			#cell20,
			#cell30 {
				left: 20px;
			}
			
			#cell01,
			#cell11,
			#cell21,
			#cell31 {
				left: 140px;
			}
			
			#cell02,
			#cell12,
			#cell22,
			#cell32 {
				left: 260px;
			}
			
			#cell03,
			#cell13,
			#cell23,
			#cell33 {
				left: 380px;
			}
			
			/* 数字显示效果 */
			.num8,
			.num16,
			.num32,
			.num64,
			.num128,
			.num256,
			.num512,
			.num1024,
			.num2048,
			.num4096,
			.num8192 {
				color: #fff;
			}
			
			.num1024,
			.num2048,
			.num4096,
			.num8192 {
				font-size: 40px;
			}
			
			.num2 {
				background: #eee4da;
			}
			
			.num4 {
				background: #ede0c8;
			}
			
			.num8 {
				background: #f2b179;
			}
			
			.num16 {
				background: #f59563;
			}
			
			.num32 {
				background: #f67c5f;
			}
			
			.num64 {
				background: #f65e3b;
			}
			
			.num128 {
				background: #edcf72;
			}
			
			.num256 {
				background: #edcc61;
			}
			
			.num512 {
				background: #9c0;
			}
			
			.num1024 {
				background: #33b5e5;
			}
			
			.num2048 {
				background: #09c;
			}
			
			.num4096 {
				background: #a6c;
			}
			
			.num8192 {
				background: #93c;
			}
			
			/* 格式化Game Over的样式 */
			#gameOver {
				display: none;
				position: absolute;
				width: 100%;
				height: 100%;
				top: 0;
				left: 0;
			}
			
			#gameOver div {
				width: 100%;
				height: 100%;
				background: #555;
				filter: alpha(Opacity=50);
				-moz-opacity: 0.5;
				opacity: 0.5;
			}
			
			#gameOver p {
				position: absolute;
				top: 150px;
				left: 100px;
				border-radius: 10px;
				width: 300px;
				border: 1px solid #EDCF72;
				background: #fff;
				line-height: 1.6em;
				font-size: 30px;
				color: #000;
				text-align: center;
			}
			
			.writer {
				width: 80px;
				margin-left: 30%;
			}
			
		</style>
		<script type="text/javascript">
			//game 封装了2048的数据和核心算法
			var cells = [
				[2, 0, 0, 0],
				[0, 32, 0, 0],
				[0, 4, 0, 0],
				[0, 0, 2048, 0]
			];
			//游戏进行中
			var PLAYING = 0;
			//方块正在移动动画处理中,期间不能响应键盘事件
			var CELL_MOVEING = 1;
			//游戏结束了,结束了就不能响应键盘事件了
			var GAME_OVER = 2;

			var score = 0;

			//当前游戏状态
			var state = PLAYING;

			//动态效果开关,打开后可以绘制方块的移动动画效果
			var effect = true;

			/* 向上的动作, */
			function upAction() {
				if (state == CELL_MOVEING) {
					return false;
				}
				if (!canMoveUp()) {
					return false;
				}
				//每次处理一个列
				for (var col = 0; col < 4; col++) {
					//每一个列中 从放方向判断是否需要移动处理
					upCol(col);
				}
				return true;
			}
			// 处理一个列的移动 
			function upCol(col) {
				//一个列中,按照方方向检查是否需要合并处理。
				for (var row = 0; row < 4;) {
					var current = cells[row][col];
					var nextRow = getNextInCol(col, row + 1, 1);
					//没有下一个,就直接结束了
					if (nextRow == -1) {
						return;
					}
					var next = cells[nextRow][col];

					if (current == 0) {
						//下一个格子移动到当前位置。
						cells[row][col] = next;
						cells[nextRow][col] = 0;
						if (effect) { //如果动效开关打开,就处理动画
							// $("cell"+nextRow+col) 找到下一个对象对应的格子
							var obj = $("cell" + nextRow + col);
							var top = row * 120 + 20;
							var left = col * 120 + 20;
							animation.add(obj, top, left);
						}
					} else if (current == next) {
						//两个格子一样,就合并格子
						cells[row][col] = next + current;
						cells[nextRow][col] = 0;

						score += cells[row][col];

						row++;
						if (effect) { //如果动效开关打开,就处理动画
							// $("cell"+nextRow+col) 找到下一个对象对应的格子
							var obj = $("cell" + nextRow + col);
							var top = row * 120 + 20;
							var left = col * 120 + 20;
							animation.add(obj, top, left);
						}
					} else {
						//下个不一样,就忽略之
						row++;
					}
				}
			}

			function getNextInCol(col, startRow, step) {
				var row = startRow;
				while (true) {
					if (row < 0 || row >= 4) {
						return -1;
					}
					if (cells[row][col] != 0) {
						return row;
					}
					row += step;
				}
			}

			function getNextInRow(row, startCol, step) {
				var col = startCol;
				while (true) {
					if (col < 0 || col >= 4) {
						return -1;
					}
					if (cells[row][col] != 0) {
						return col;
					}
					col += step;
				}
			}

			function downAction() {
				if (state == CELL_MOVEING) {
					return false;
				}
				if (!canMoveDown()) {
					return false;
				}
				//每次处理一个列
				for (var col = 0; col < 4; col++) {
					//每一个列中 从放方向判断是否需要移动处理
					downCol(col);
				}
				return true;
			}
			// 处理一个列的移动
			function downCol(col) {
				//一个列中,按照方方向检查是否需要合并处理。
				for (var row = 3; row >= 0;) {
					var current = cells[row][col];
					var nextRow = getNextInCol(col, row - 1, -1);
					//没有下一个,就直接结束了
					if (nextRow == -1) {
						return;
					}
					var next = cells[nextRow][col];

					if (current == 0) {
						//下一个格子移动到当前位置。
						cells[row][col] = next;
						cells[nextRow][col] = 0;
						if (effect) { //如果动效开关打开,就处理动画
							// $("cell"+nextRow+col) 找到下一个对象对应的格子
							var obj = $("cell" + nextRow + col);
							var top = row * 120 + 20;
							var left = col * 120 + 20;
							animation.add(obj, top, left);
						}
					} else if (current == next) {
						//两个格子一样,就合并格子
						cells[row][col] = next + current;
						cells[nextRow][col] = 0;

						score += cells[row][col];

						row--;

						if (effect) { //如果动效开关打开,就处理动画
							// $("cell"+nextRow+col) 找到下一个对象对应的格子
							var obj = $("cell" + nextRow + col);
							var top = row * 120 + 20;
							var left = col * 120 + 20;
							animation.add(obj, top, left);
						}
					} else {
						//下个不一样,就忽略之
						row--;
					}
				}
			}

			function leftAction() {
				if (state == CELL_MOVEING) {
					return false;
				}
				if (!canMoveLeft()) {
					return false;
				}
				//每次处理一个行
				for (var row = 0; row < 4; row++) {
					//每一个行中 从放方向判断是否需要移动处理
					moveLeft(row);
				}
				return true;
			}
			// 处理一个列的移动
			function moveLeft(row) {
				//一个列中,按照方方向检查是否需要合并处理。
				for (var col = 0; col < 4;) {
					var current = cells[row][col];
					var nextCol = getNextInRow(row, col + 1, 1);
					//没有下一个,就直接结束了
					if (nextCol == -1) {
						return;
					}
					var next = cells[row][nextCol];

					//console.log("next:"+next);
					//console.log("current:"+current);

					if (current == 0) {
						//下一个格子移动到当前位置。
						cells[row][col] = next;
						cells[row][nextCol] = 0;
						if (effect) { //如果动效开关打开,就处理动画
							// $("cell"+nextRow+col) 找到下一个对象对应的格子
							var obj = $("cell" + row + nextCol);
							var top = row * 120 + 20;
							var left = col * 120 + 20;
							animation.add(obj, top, left);
						}
					} else if (current == next) {
						//两个格子一样,就合并格子
						cells[row][col] = next + current;
						cells[row][nextCol] = 0;

						score += cells[row][col];

						col++;
						if (effect) { //如果动效开关打开,就处理动画
							// $("cell"+nextRow+col) 找到下一个对象对应的格子
							var obj = $("cell" + row + nextCol);
							var top = row * 120 + 20;
							var left = col * 120 + 20;
							animation.add(obj, top, left);
						}
					} else {
						//下个不一样,就忽略之
						col++;
					}
				}
			}

			function rightAction() {
				if (state == CELL_MOVEING) {
					return false;
				}
				if (!canMoveRight()) {
					return false;
				}
				//每次处理一个行
				for (var row = 0; row < 4; row++) {
					//每一个行中 从放方向判断是否需要移动处理
					moveRight(row);
				}
				return true;
			}
			// 处理一个列的移动
			function moveRight(row) {
				//一个列中,按照方方向检查是否需要合并处理。
				for (var col = 3; col >= 0;) {
					var current = cells[row][col];
					var nextCol = getNextInRow(row, col - 1, -1);
					//没有下一个,就直接结束了
					if (nextCol == -1) {
						return;
					}
					var next = cells[row][nextCol];

					//console.log("next:"+next);
					//console.log("current:"+current);

					if (current == 0) {
						//下一个格子移动到当前位置。
						cells[row][col] = next;
						cells[row][nextCol] = 0;
						if (effect) { //如果动效开关打开,就处理动画
							// $("cell"+nextRow+col) 找到下一个对象对应的格子
							var obj = $("cell" + row + nextCol);
							var top = row * 120 + 20;
							var left = col * 120 + 20;
							animation.add(obj, top, left);
						}
					} else if (current == next) {
						//两个格子一样,就合并格子
						cells[row][col] = next + current;
						cells[row][nextCol] = 0;


						score += cells[row][col];

						col--;

						if (effect) { //如果动效开关打开,就处理动画
							// $("cell"+nextRow+col) 找到下一个对象对应的格子
							var obj = $("cell" + row + nextCol);
							var top = row * 120 + 20;
							var left = col * 120 + 20;
							animation.add(obj, top, left);
						}
					} else {
						//下个不一样,就忽略之
						col--;
					}
				}
			}

			function canMoveUp() {
				for (var col = 0; col < 4; col++) {
					for (var row = 1; row < 4; row++) {
						//格子上方是空位置, 可以移动
						if (cells[row][col] != 0 && cells[row - 1][col] == 0) {
							return true;
						}
						//格子上方相邻的相等,可以移动
						if (cells[row][col] != 0 && (cells[row][col] == cells[row - 1][col])) {
							return true;
						}
					}
				}
				return false;
			}

			function canMoveDown() {
				for (var col = 0; col < 4; col++) {
					for (var row = 0; row < 3; row++) {
						//格子上方是空位置, 可以移动
						if (cells[row][col] != 0 && cells[row + 1][col] == 0) {
							return true;
						}
						//格子上方相邻的相等,可以移动
						if (cells[row][col] != 0 && (cells[row][col] == cells[row + 1][col])) {
							return true;
						}
					}
				}
				return false;
			}

			function canMoveLeft() {
				for (var col = 1; col < 4; col++) {
					for (var row = 0; row < 4; row++) {
						//格子上方是空位置, 可以移动
						if (cells[row][col] != 0 && cells[row][col - 1] == 0) {
							return true;
						}
						//格子上方相邻的相等,可以移动
						if (cells[row][col] != 0 && (cells[row][col] == cells[row][col - 1])) {
							return true;
						}
					}
				}
				return false;
			}

			function canMoveRight() {
				for (var col = 0; col < 3; col++) {
					for (var row = 0; row < 4; row++) {
						//格子上方是空位置, 可以移动
						if (cells[row][col] != 0 && cells[row][col + 1] == 0) {
							return true;
						}
						//格子上方相邻的相等,可以移动
						if (cells[row][col] != 0 && (cells[row][col] == cells[row][col + 1])) {
							return true;
						}
					}
				}
				return false;
			}


			function test() {
				rightAction();
				state = CELL_MOVEING;
				animation.start(function() {
					//console.log("update");
					randomNumber();
					updateView();
					state = PLAYING;
				});
			}

			//更新显示,将表格中的数据,更新到界面显示
			function updateView() {
				for (var row = 0; row < 4; row++) {
					for (var col = 0; col < 4; col++) {
						var n = cells[row][col];
						var cell = $("cell" + row + col);
						//清楚显示的数据和显示样式
						cell.className = "cell";
						cell.innerHTML = "";
						if (n > 0) {
							//更新显示样式
							cell.className = "cell num" + n;
							//更新显示的数字
							cell.innerHTML = n;
						}
					}
				}

				$("score").innerHTML = score;
				$("finalScore").innerHTML = score;

			}
			//检查当前的表格中是否是满的,如果满了返回true,否则返回false
			function full() {
				for (var row = 0; row < 4; row++) {
					for (var col = 0; col < 4; col++) {
						if (cells[row][col] == 0) {
							return false;
						}
					}
				}
				return true;
			}
			//向表格随机插入一个数字,如果插入成功返回true,插入失败返回false
			function randomNumber() {
				if (full()) {
					return false;
				}
				while (true) {
					var col = parseInt(Math.random() * 4);
					var row = parseInt(Math.random() * 4);
					if (cells[row][col] == 0) {
						var n = Math.random() < 0.5 ? 2 : 4;
						cells[row][col] = n;
						return true;
					}
				}
			}

			function startAction() {
				$("gameOver").style.display = "none";
				for (var row = 0; row < 4; row++) {
					for (var col = 0; col < 4; col++) {
						cells[row][col] = 0;
					}
				}
				score = 0;
				randomNumber();
				randomNumber();
				updateView();
				state = PLAYING;
			}
			//元素查询方法
			function $(id) {
				return document.getElementById(id);
			}

			function has8192() {
				for (var row = 0; row < 4; row++) {
					for (var col = 0; col < 4; col++) {
						if (cells[row][col] == 8192) {
							return true;
						}
					}
				}
			}

			function hasSpace() {
				for (var row = 0; row < 4; row++) {
					for (var col = 0; col < 4; col++) {
						if (cells[row][col] == 0) {
							return true;
						}
					}
				}
			}


			/* 显示游戏结束界面 */
			function gameOver() {
				//发现8192游戏结束
				if (has8192()) {
					state = GAME_OVER;
					$("gameOver").style.display = "block";
					return true;
				}

				//发现空位置,游戏不结束    	
				if (hasSpace()) {
					return false;
				}

				//能够移动游戏不结束
				if (canMoveUp() || canMoveDown() || canMoveLeft() || canMoveRight()) {
					return false;
				}
				state = GAME_OVER;
				$("gameOver").style.display = "block";
				return true;
			}

			//软件启动初始代码
			window.onload = function() {
				$("newGame").onclick = function() {
					if (state == PLAYING)
						startAction();
				}
				$("restart").onclick = function() {
					if (state == GAME_OVER)
						startAction();
				}
				startAction();
				//监听键盘事件
				document.onkeydown = function(event) {
					if (state != PLAYING) {
						return;
					}
					var move = false;
					switch (event.keyCode) {
						case 37: //left
							move = leftAction();
							break;
						case 38: //up
							move = upAction();
							break;
						case 39: //right
							move = rightAction();
							break;
						case 40: //down
							move = downAction();
							break;
					}
					if (!move) {
						return;
					}
					if (effect) {
						state = CELL_MOVEING;
						animation.start(function() {
							//console.log("update");
							updateView();
							state = PLAYING;
							if (!gameOver()) {
								setTimeout(function() {
									randomNumber();
									updateView();
								}, 100);
							}
						});
					} else {
						if (!gameOver()) {
							setTimeout(function() {
								randomNumber();
								updateView();
							}, 100);
						}

						updateView();
						state = PLAYING;
					}
					gameOver();
				}; // 5211 0842 8479 快捷快递
			}
			
			// animation.js的部分
			var animation = {
				tasks: [], //动画任务数据
				timer: null, //动画定时器
				times: 10, //定时器次数
				interval: 1000 / 60, //定时器间隔
				add: function(obj, top, left) {
			
					//动画已经开始了,不能添加任务了!
					if (this.timer) {
						return false;
					}
					if (!obj) {
						return false;
					}
			
					//计算移动步伐
					var t = (top - obj.offsetTop) / this.times;
					var l = (left - obj.offsetLeft) / this.times;
			
					//添加动画任务,其中obj是被移动到对象,top, left是移动以后的位置
					var task = {
						topStep: t,
						leftStep: l,
						element: obj,
						step: function() {
							var t = this.element.offsetTop;
							this.element.style.top = (t + this.topStep) + "px";
							var l = this.element.offsetLeft;
							this.element.style.left = (l + this.leftStep) + "px";
						},
						clear: function() {
							this.element.style.top = "";
							this.element.style.left = "";
						}
					};
					this.tasks[this.tasks.length] = task;
					return true;
				},
				start: function(callback) {
					//如果定时器已经启动,就不能再启动定时器了
					if (this.timer) {
						return false;
					}
			
					console.log("STATRING");
					if (this.tasks.length == 0) {
						if (callback) {
							callback();
						}
						return false;
					}
			
					//如果有callback就交给this.callback
					if (callback) {
						this.callback = callback;
					}
					this.timer = setInterval(function() {
						//console.log("timeOut");
						//console.log(animation.times);
			
						for (var i = 0; i < animation.tasks.length; i++) {
							var task = animation.tasks[i];
							task.step();
						}
			
						animation.times--;
						if (animation.times < 0) {
							animation.stop();
						}
					}, this.interval);
					return true;
				},
				stop: function() {
					if (this.timer) {
						window.clearInterval(this.timer);
						this.timer = null;
						this.times = 10;
			
					}
			
					//结束以后执行callback()
					if (this.callback) {
						this.callback();
					}
					for (var i = 0; i < this.tasks.length; i++) {
						var task = this.tasks[i];
						task.clear();
					}
					this.tasks = []; //清空动画任务
				},
				callback: null //动画结束时候执行的方法
			};
			
		</script>
	</head>
	<body>
		<header>
			<h1>2048</h1>
		</header>
		<div id="gamePanel">
			<p><a class="button" id="newGame">New Game</a> Score: <span id="score">0</span><span class="writer">小灰灰版</span></p>
			<div id="gridPanel">
				<div class="grid"> </div>
				<div class="grid"> </div>
				<div class="grid"> </div>
				<div class="grid"> </div>

				<div class="grid"> </div>
				<div class="grid"> </div>
				<div class="grid"> </div>
				<div class="grid"> </div>

				<div class="grid"> </div>
				<div class="grid"> </div>
				<div class="grid"> </div>
				<div class="grid"> </div>

				<div class="grid"> </div>
				<div class="grid"> </div>
				<div class="grid"> </div>
				<div class="grid"> </div>

				<div class="cell " id="cell00"> </div>
				<div class="cell " id="cell01"> </div>
				<div class="cell " id="cell02"> </div>
				<div class="cell " id="cell03"> </div>

				<div class="cell " id="cell10"> </div>
				<div class="cell " id="cell11"> </div>
				<div class="cell " id="cell12"> </div>
				<div class="cell " id="cell13"> </div>

				<div class="cell " id="cell20"> </div>
				<div class="cell " id="cell21"> </div>
				<div class="cell " id="cell22"> </div>
				<div class="cell " id="cell23"> </div>

				<div class="cell " id="cell30"> </div>
				<div class="cell " id="cell31"> </div>
				<div class="cell " id="cell32"> </div>
				<div class="cell " id="cell33"> </div>

			</div>
			<div id="gameOver">
				<div>
					<!--背景 -->
				</div>
				<p>
					<!-- 前景 -->
					Game Over!<br>
					Score: <span id="finalScore">0</span><br>
					<a class="button" id="restart">Try Again!</a>
				</p>
			</div>
		</div>
	</body>
</html>

你可能感兴趣的:(html,js,css,html5,html,css,css3,javascript)