效果图

实现代码

<!DOCTYPE HTML>
<html>
	<head>
		<meta http-equiv="Content-Type" content="text/html;charset=utf-8"/>
		<title>2048</title>
		<style type="text/css">
			.basic{
				height:80px;
				width:80px;
				background-color:#DBDBDB;
				float:left;
				margin:2px;
			}
			.row{
				height:80px;
				clear:both;
			}
		</style>
	</head>
	
	<body>
		<div id="pool"></div>
		<div id="sample" class="basic" style='opacity: 0;'></div>
		<div>score:<span id='score' style="font-size:200%;font-weight:bold;"></span></div>
		
		<script type="text/javascript" >
			//对象内使用,要加this
			var container={
				rowNum:4,
				colNum:4,
				score:0,//靠弄个Cookie记录下游戏记录
				isMoved:false,//Block 有没有移动过
				content:[],//{x:col,y:row,v:value}
				colour:['#DBDBDB','#56A36C','#EFCEE8',
						'#81C2D6','#8192D6','#D9B3E6',
						'#DCF7A1','#83FCD8','#E8F2FF',
						'#91C6FF','#B8F788','#58D2E8',
						'#F2B6B6','#E8ED51','#FFE3FB',
						'#E8FF8C','#FFDEC9','#F5A433',
						'#E6109B','#96C4E6','#E560CD'],
				colourObject:{},
				//初始化 背景
				loadBackground:function(){
					var pool = document.getElementById("pool");
					var sample = document.getElementById("sample")
					var margin = 2;
					var dotWidth = parseFloat(sample.offsetWidth)   margin;//基本方块宽度   margin
					for(var i = 0; i != this.rowNum; i  ){
		
						//创建行
						var rDiv = document.createElement("div");
						rDiv.setAttribute('id','r'   i);
						rDiv.setAttribute('class','row');
						
						for(var j = 0; j != this.colNum; j  ){
							var cDiv = document.createElement("div");
							cDiv.setAttribute('id','c' j   '_r'   i);
							cDiv.setAttribute('class','basic');
							rDiv.appendChild(cDiv);
						}
						rDiv.setAttribute('width',(this.colNum * (dotWidth   margin))   'px')
						pool.appendChild(rDiv);
					}
				},
				findBlock:function(colx, rowy){
					return this.content.find(function(value){
						return value.x == colx && value.y == rowy;
					});
				},
				addBlockToMine:function(){//开局或移动后,添加新块
					var zeroBlockArray = this.content.filter(function(value){
						return value.v == 0;
					});
					
					if(zeroBlockArray.length != 0){
						zeroBlockArray[this.makeRandomInteger(zeroBlockArray.length)].v = 
							(this.makeRandomInteger(2)   1) * 2;
					}
				},
				makeRandomInteger:function(scope){
					return Math.floor(Math.random() * scope);
				},
				checkDeath:function(){
					if(this.content.filter(function(value){
							return value.v == 0;
						}).length != 0){
						return false;//有零块就表示没有死
					}else{
						//满格时,检测相邻之间可合并的可能性//Jallen Kwong
						//再没有合并的可能,没有的话,游戏就结束
						
						//穷举法(不聪明的方法)
						for(var i = 0; i < this.rowNum; i  ){
							if(i != this.rowNum - 1){
								for(var j = 0;j < this.colNum; j  ){
									var mainBlock = this.findBlock(j, i);
									var downBlock = this.findBlock(j, i   1);

									if(j != this.colNum - 1){
										var rightBlock = this.findBlock(j   1,i);
									
										if(mainBlock.v == rightBlock.v 
											|| mainBlock.v == downBlock.v){
											return false;
										}
									}else{
										if(mainBlock.v == downBlock.v){
											return false;
										}
									}
								
								}
							}else{
								for(var j = 0;j < this.colNum - 1; j  ){
									var mainBlock = this.findBlock(j, i);
									var rightBlock = this.findBlock(j   1, i);
									
									if(mainBlock.v == rightBlock.v){
										return false;
									}
								}
							}							
						}
						return true;//真的Game Over
					}
				},
				refresh:function(){//刷新显示页面
					for(var row = 0;row < this.rowNum;row  ){
						for(var col = 0;col < this.colNum;col  ){
							var value = this.findBlock(col,row).v;
							var elem = document.getElementById('c' col '_r' row);
							elem.style.backgroundColor = this.colourObject[value] == undefined?this.colourObject[0]:this.colourObject[value];
							elem.innerHTML 
								= (value == 0 ? "" : "<span style='font-size:200%;font-weight:bold;'>" value "</span>");
						}
					}
					
					document.getElementById('score').innerHTML = this.score;
				},
				addKeyListener:function(event){
					var keycode = event.keyCode;
					if(keycode >= 37 && keycode <= 40){
						//alert(keycode);
						event.preventDefault();
						var changeCount = 0;//记住块有没真正得移动过
						switch(keycode){
						
							case 37://左
								//console.log(keycode);
								for(var i = 0; i < this.rowNum; i  ){
									var queue = [];
									var flag = false;
									
									//入栈
									for(var j = 0 ; j < this.colNum; j  ){
										var block = this.findBlock(j, i);
										
										if(block.v == 0){
											continue;
										}
									
										flag = this.coreCalculate(block, queue, flag);
									}
									
									//出队列
									for(var k = 0 ;k < this.colNum; k  ){
										changeCount  = this.outOfQueue(k, i, queue, k);
									}
									
								}
								break;
							case 38://上
								for(var i = 0; i < this.colNum; i  ){
									var queue = [];
									var flag = false;
									
									for(var j = 0 ;j < this.rowNum; j  ){
										var block = this.findBlock(i, j);
										
										if(block.v == 0){
											continue;
										}
									
										flag = this.coreCalculate(block, queue, flag);
									}
									
									//出队列
									for(var k = 0 ;k < this.rowNum; k  ){
										changeCount  = this.outOfQueue(i, k, queue, k);
									}
								}
								break;
							case 39://右
								for(var i = 0; i < this.rowNum; i  ){
									var queue = [];
									var flag = false;
									//入栈
									for(var j = this.colNum - 1 ; j >= 0; j--){
										var block = this.findBlock(j, i);
										
										if(block.v == 0){
											continue;
										}
									
										flag = this.coreCalculate(block, queue, flag);
									}
									//console.log(queue);
									//出队列
									for(var k = this.colNum - 1 ,l = 0;k >= 0; k--,l  ){
										changeCount  = this.outOfQueue(k, i, queue, l);
									}
								}
							
								break;
							case 40://下
								for(var i = 0; i < this.colNum; i  ){
									var queue = [];
									var flag = false;
									for(var j = this.rowNum - 1 ;j >= 0; j--){
										var block = this.findBlock(i, j);
										
										if(block.v == 0){
											continue;
										}
									
										flag = this.coreCalculate(block, queue, flag);
									}
									
									//出队列
									for(var k = this.rowNum - 1 ,l = 0;k >= 0; k--,l  ){
										changeCount  = this.outOfQueue(i, k, queue, l);
									}
								}
								break;
							default:break;
						}
						
						//要检查content的v们有没有改变过
						//1.入栈操作前,要来个数组拷贝,然后在做比对,这做法并不聪明
						//2.出队列的时候,跟原来的值进行比较,有改变 changCount  
						
						//console.log('changeCount:'   changeCount);
						if(changeCount != 0){
							this.addBlockToMine();
							
							this.refresh();//刷新显示页面
							
							if(this.checkDeath()){
								alert("Game Over!");
								document.onkeydown = function(event){
									var keycode = event.keyCode;
									if(keycode >= 37 && keycode <= 40){
										event.preventDefault();
										alert("Game Over!");
									}
								};
							}
					
						}
					}
				},
				init:function(){
					for(var row = 0; row < this.rowNum; row  ){
						for(var col = 0; col < this.colNum; col  ){
							this.content[this.content.length] = {x:col,y:row,v:0};
						}
					}
					
					for(var i = 0;i <= 20;i  ){
						if(i == 0){
							this.colourObject[i] = this.colour[i];
							continue;
						}
						this.colourObject[Math.pow(2,i)] = this.colour[i];
					}
					//console.log(this.colourObject[7]);
					
				},
				coreCalculate:function(block, queue, flag){ flag的作用,入栈方式有问题,譬如2,2,4  应得 4,4 但结果 得8
					if(queue.length == 0 ){
						queue[queue.length] = block.v;
						return flag;
					}else{
						var tailOfQueue = queue[queue.length - 1];
						if((tailOfQueue == block.v) && !flag){
							this.score  = (queue[queue.length - 1] = tailOfQueue * 2);
							return true;
						}else{
							queue[queue.length] = block.v;
							return false;
						}
					}
				},
				outOfQueue:function(colx, rowy, queue, index){
					var block = this.findBlock(colx, rowy);
					var oldValue = block.v;
					block.v = queue[index] == undefined ? 0 : queue[index];
					return oldValue != block.v? 1 : 0;
				}
			};
		
			//main
			window.onload = function(){
				container.loadBackground();
				container.init();
				//alert(container.findBlock(1,1).v);
				container.addBlockToMine();
				container.addBlockToMine();
				container.refresh();
				document.addEventListener('keydown', function(event){
					container.addKeyListener(event);
				});
			};
		
		</script>
	</body>
</html> 

到此这篇关于基于JS制作一个简易的2048游戏的文章就介绍到这了,更多相关JS 2048游戏内容请搜索Devmax以前的文章或继续浏览下面的相关文章希望大家以后多多支持Devmax!

基于JS制作一个简易的2048游戏的更多相关文章

  1. html5 拖拽及用 js 实现拖拽功能的示例代码

    这篇文章主要介绍了html5 拖拽及用 js 实现拖拽,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

  2. amaze ui 的使用详细教程

    这篇文章主要介绍了amaze ui 的使用详细教程,本文通过多种方法给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

  3. swift皮筋弹动发射飞机ios源码

    这是一个款采用swift实现的皮筋弹动发射飞机游戏源码,游戏源码比较详细,大家可以研究学习一下吧。

  4. Swift与Js通过WebView交互

    开发环境:Swfit2.3XCode8.2基础概念jscontext,jscontext是代表JS的执行环境,通过-evaluateScript:方法就可以执行一JS代码JSValue,JSValue封装了JS与ObjC中的对应的类型,以及调用JS的API等JSExport,JSExport是一个协议,遵守此协议,就可以定义我们自己的协议,在协议中声明的API都会在JS中暴露出来,才能调用Swif

  5. JSCore swift

    如果双方相互引用,会造成循环引用,而导致内存泄露。以上是Jscore的基本使用,比较简单

  6. Swift WKWebView的js调用swift

    最近项目需求,需要用到JavaScriptCore和WebKit,但是网上的资源有限,而且比较杂,都是一个博客复制另外一个博客,都没有去实际敲代码验证,下面给大家分享一下我的学习过程。

  7. Swift WKWebView的swift调用js

    不多说,直接上代码:在html里面要添加的的代码,显示swift传过去的参数:这样就实现了swift给js传参数和调用!

  8. 在 Swift 專案中使用 Javascript:編寫一個將 Markdown 轉為 HTML 的編輯器

    你有強烈的好奇心,希望在你的iOS專案中使用JavaScript。jscontext中的所有值都是JSValue對象,JSValue類用於表示任意類型的JavaScript值。因此,我們既需要寫Swift代碼也要寫JavaScript代碼。此外,我們還會在JavaScript中按照這個類的定義來創建一個對象并對其屬性進行賦值。從Swift中呼叫JavaScript就如介紹中所言,JavaScriptCore中最主要的角色就是jscontext類。一個jscontext對象是位於JavaScript環境和本

  9. swift - WKWebView JS 交互

    本文介绍WKWebView怎么与js交互,至于怎么用WKWebView这里就不介绍了HTML代码APP调JS代码结果JS给APP传参数首先注册你需要监听的js方法名2.继承WKScriptMessageHandler并重写userContentController方法,在该方法里接收JS传来的参数3.结果

  10. swift 开发UIWebView跟JS的交互

    前言作为小白的我,才开始入门IOS,选择了swift来进行入门学习,学习做着公司一个简单的小小项目,该项目需要进行跟H5进行交互,然后我就开始研究了UIWebView的使用,其实基本原理跟Android的一样,因为我是Android开发的,所以就顺水推舟了。))//这里设置你需要加载的地址}overridefuncdidReceiveMemoryWarning(){super.didReceiveMemoryWarning()//disposeofanyresourcesthatcanberecreate

随机推荐

  1. js中‘!.’是什么意思

  2. Vue如何指定不编译的文件夹和favicon.ico

    这篇文章主要介绍了Vue如何指定不编译的文件夹和favicon.ico,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

  3. 基于JavaScript编写一个图片转PDF转换器

    本文为大家介绍了一个简单的 JavaScript 项目,可以将图片转换为 PDF 文件。你可以从本地选择任何一张图片,只需点击一下即可将其转换为 PDF 文件,感兴趣的可以动手尝试一下

  4. jquery点赞功能实现代码 点个赞吧!

    点赞功能很多地方都会出现,如何实现爱心点赞功能,这篇文章主要为大家详细介绍了jquery点赞功能实现代码,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  5. AngularJs上传前预览图片的实例代码

    使用AngularJs进行开发,在项目中,经常会遇到上传图片后,需在一旁预览图片内容,怎么实现这样的功能呢?今天小编给大家分享AugularJs上传前预览图片的实现代码,需要的朋友参考下吧

  6. JavaScript面向对象编程入门教程

    这篇文章主要介绍了JavaScript面向对象编程的相关概念,例如类、对象、属性、方法等面向对象的术语,并以实例讲解各种术语的使用,非常好的一篇面向对象入门教程,其它语言也可以参考哦

  7. jQuery中的通配符选择器使用总结

    通配符在控制input标签时相当好用,这里简单进行了jQuery中的通配符选择器使用总结,需要的朋友可以参考下

  8. javascript 动态调整图片尺寸实现代码

    在自己的网站上更新文章时一个比较常见的问题是:文章插图太宽,使整个网页都变形了。如果对每个插图都先进行缩放再插入的话,太麻烦了。

  9. jquery ajaxfileupload异步上传插件

    这篇文章主要为大家详细介绍了jquery ajaxfileupload异步上传插件,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  10. React学习之受控组件与数据共享实例分析

    这篇文章主要介绍了React学习之受控组件与数据共享,结合实例形式分析了React受控组件与组件间数据共享相关原理与使用技巧,需要的朋友可以参考下

返回
顶部