如何用H5实现好玩的2048小游戏


Posted in HTML / CSS onJuly 23, 2022

一、游戏介绍

相信大多数读者都玩过一款小游戏 2048,这款数字小游戏在几年前很是流行。2048是2014年由Gabriele Cirulli利用周末的时间写出的,果然大佬就是大佬,一个周末就写出了这么经典的游戏。游戏的玩法非常简单,利用上、下、左、右移动的方式拼出2048即算赢得游戏,因为游戏上手简单同时赢得游戏又存在一定难度,所以游戏的可玩性很高,本人当时也是十分喜爱这款游戏,下面讲解下如何用H5去实现这款游戏。

二、游戏界面

游戏界面十分简单,我截图了进行中的几个场景,基本由一块矩形游戏区,一个按钮及一个分数展示区域组成。

如何用H5实现好玩的2048小游戏

三、代码设计

H5代码:

H5代码十分简单,主要用16个div代表16个数字方块,再加上另外restart按钮区,还有一个分值展示区域。

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
    <title>2048</title>
     <link type="text/css" rel="stylesheet" href="css/style.css">
    <script type="text/javascript" language="javascript" src="js/jquery-3.6.0.min.js">
    	
   		document.addEventListener('plusready', function(){
   			//console.log("所有plus api都应该在此事件发生后调用,否则会出现plus is undefined。"	
   		});
   		
    </script>
    
    <script type="text/javascript" language="javascript" src="js/gamerun.js"></script>
</head>
	<body onload="init()">
	<div class="authorized" >
	<p>2048</p></div>
	<div class="restart" ontouchstart="restart()">Restart </div>
	<div class="score">
	<p class="maxnum" id="num_p">最高值</p>
	<p class="maxnum" id="num_v">0</p>
	</div>
   <article class="game"> 
     <div class="square"  id="f1"> </div>
     <div class="square"  id="f2"> </div>
     <div class="square"  id="f3"> </div>
     <div class="square"  id="f4"> </div>
     <div class="square"  id="f5"> </div>
     <div class="square"  id="f6"> </div>
     <div class="square"  id="f7"> </div>
     <div class="square"  id="f8"> </div>
     <div class="square"  id="f9"> </div>
     <div class="square"  id="f10"></div>
     <div class="square"  id="f11"> </div>
     <div class="square"  id="f12"></div>
     <div class="square"  id="f13"> </div>
     <div class="square"  id="f14"></div>
     <div class="square"  id="f15"> </div>
     <div class="square"  id="f16"> </div>  
  </article>
   <audio id="yin" src="media/anniu.mp3"autoplay="autoplay"> </audio>
  <footer></footer>
</body>
</html>

js代码:

js代码相对复杂一些,游戏处理逻辑主要可以分成以下两块:

(1)移动处理逻辑,游戏玩法是通过上下左右移动进行数字的相加变换。那么首先就会有上滑、下滑、左滑、右滑四个处理函数。上下滑动的时候,将相邻两行相同的数值进行相加;左右滑动的时候,将相邻两列相同的数值进行相加。

(2)移动判断逻辑。

首先第一类判断逻辑是判断是否可以移动。整个游戏区是 4X4的格局分布,那么在上下左右移动的时候我们会通过相邻的两行或者两列是否存在相同的数值去判断,如果有则可以继续移动,如果没有,则不可以继续移动。

其次,我们需要判断游戏是否可以继续,如果整个游戏区的数值方块已经被占满,上下左右都没有移动空间了,那么游戏就是结束了,game over。

(3)其余逻辑

其余的还剩一些比较简单的逻辑,颜色分配函数、重新开始函数、最大分值记录函数等。

// JavaScript Document
var flag=[false,false,false,false,false,false,false,false,
     false,false,false,false,false,false,false,false];
var ds=document.getElementsByClassName("square");
var color=["#FF9966","#FFCCCC","#CC9966","#99CCCC","#99CC99","#99CCFF","#CCCCFF","#FFCC00","#333399","#CC9999","#009999","#996666","#CCCCCC","#CCCCFF","#99CC99"];
var max_num=parseInt("2");
var lose_view=false;
 
  function init()  //初始化界面,生成2个数字方块
 {
	 var i=Math.round(Math.random()*16);
	 var j=Math.round(Math.random()*16);
   while(i==j)
	 { j=Math.round(Math.random()*16);
	 }
   ds[i].style.backgroundColor="#FF7578";
   ds[j].style.backgroundColor="#FF7578"; 
   ds[i].innerHTML="2";
   ds[j].innerHTML="2";
  flag[i]=true;
  flag[j]=true;
  document.body.addEventListener('load',load(event),false);
  //var msg=parseInt(document.getElementsByClassName("authorized")[0].innerText);
  //alert(msg);
  }
  
function max_score()   //记录取得的最大分数
{
	for (var i=0;i<ds.length;i++){
		var c_num = parseInt(ds[i].innerText);
		if( c_num > max_num ) 
		{
			max_num=c_num;
		}	
	}
   document.getElementById("num_v").innerHTML= max_num;
}
 function restart()  //重新开始游戏,重新回到初始化页面
 {
	 if(lose_view==true)
	 {  
		 var $h2=document.getElementById("reset1");
		// var $bu2=document.getElementById("reset2");
		 var $par2=$("body");	
		  $par2[0].removeChild($h2);
		 // $par2[0].removeChild($bu2);
		lose_view=false; 
		
	 }
 	 for (var i=0;i<ds.length;i++)
 	 {
 		 ds[i].innerHTML="";
 		 flag[i]=false;
 		ds[i].removeAttribute("style");
 	 }
 	 init();
 } 
 
 
 
 function voice()   //设置移动时产生的音效
{
var vs=document.getElementById("yin");
vs.play();
}
 
 
 
function load(event)   // 捕捉屏幕滑动事件
{
$("body").on("touchstart", function(e) {
    e.preventDefault();
    startX = e.originalEvent.changedTouches[0].pageX,
    startY = e.originalEvent.changedTouches[0].pageY;
});
$("body").on("touchend", function(e) 
{
    e.preventDefault();
    moveEndX = e.originalEvent.changedTouches[0].pageX,
    moveEndY = e.originalEvent.changedTouches[0].pageY,
    X = Math.floor(moveEndX - startX),
    Y = Math.floor(moveEndY - startY);
 
    if ( Math.abs(X)> Math.abs(Y)) 
    {
    	if (Math.abs(X)>20)
    	{
    		if( X > 0)
    		{
    		rightgo();
    		voice();
    		}
    		else
    		{
    		leftgo();
    		voice();
    		}
    	}
	 }
    else if(Math.abs(X)< Math.abs(Y))
    {
    	if (Math.abs(Y)>20)
    	{
    		if(Y > 0)
    		{
    		 bottomgo();
    		 voice();
    		}
    		
    		else
    		{
    		topgo();
    		voice();
    		}
    	}
    }
}
);
}
 
 
 
function addcolor()            //设置方块颜色
 { for(var i=0;i<ds.length;i++)
 {
	 var ss=parseInt(ds[i].innerHTML);
	 
	 switch(ss)
	{
	case 2:
	ds[i].style.backgroundColor=color[0];
	break;
	case 4:
	ds[i].style.backgroundColor=color[1];
	break;
	case 8:
	ds[i].style.backgroundColor=color[2];
	break;
	case 16:
	ds[i].style.backgroundColor=color[3];
	break;
	case 32:
	ds[i].style.backgroundColor=color[4];
	break;
	case 64:
	ds[i].style.backgroundColor=color[5];
	break;
	case 128:
	ds[i].style.backgroundColor=color[6];
	break;
	case 256:
	ds[i].style.backgroundColor=color[7];
	break;	
	case 512:
	ds[i].style.backgroundColor=color[8];
	break; 
	case 1024:
	ds[i].style.backgroundColor=color[9];
	break;
	case 2048:
	ds[i].style.backgroundColor=color[10];
	break;
	case 4096:
	ds[i].style.backgroundColor=color[11];
	break;
	case 8192:
	ds[i].style.backgroundColor=color[12];
	break;
	case 16384:
	ds[i].style.backgroundColor=color[13];
	break;
	default:
	break;
		 }
 }
	 }
 
function istop()
{  					//判断是否可以继续上移,true则表示可以
	var istop=false;
 
	for(var i1=4;i1<16;i1++) 
	{
		
     if(flag[i1]==true)
	 {  
	
		 if(flag[i1-4]==true)
     	 {
		  if( ds[i1].innerHTML==ds[i1-4].innerHTML )
		 	{
			  istop=true;
		 	}
		    
      		}
	    else
		  {
			istop=true;
		 }
		 } 	 
		}
 
	return istop;
}
 
function isbottom()  //判断是否可以继续下移,true则表示可以
{
	var isbottom=false;
	
	for(var i2=11;i2>=0;i2--)
	
	{
     if(flag[i2]==true)
	 {
		 if(flag[i2+4]==true)
      {
		  if( ds[i2].innerHTML==ds[i2+4].innerHTML )
		  
		 {
			  isbottom=true;
		 }
		  }
		  
		  else
		  
		  {
			isbottom=true;
		 }
		 } 	 
		}
	
	return isbottom;
}
 
function isleft(){  //判断是否可以继续左移,true则表示可以
	var isleft=false;
 
	for(var i3=0;i3<4;i3++)
	{
		for(var j3=0;j3<3;j3++)
	{
		 if(flag[j3+4*i3+1]==true)
	 {
		 if(flag[j3+4*i3]==true)
         {
	 if( ds[j3+4*i3].innerHTML==ds[j3+4*i3+1].innerHTML )
		 {
		  isleft=true;
		 }
		  }
		  else
		  {
			isleft=true;
			
		 }
		    }	 
	}
  }
 
 return isleft;
}
 
function isright(){     //判断是否可以继续右移,true则表示可以
	var isright=false;
	
	for(var i4=3;i4>=0;i4--)
	{
		for(var j4=2;j4>=0;j4--)
	{
		 if(flag[j4+4*i4]==true)
	 {
		 if(flag[j4+4*i4+1]==true)
      {
		   if( ds[j4+4*i4].innerHTML==ds[j4+4*i4+1].innerHTML )
		   {
		  isright=true;
		   }
		  }
		  else
		  {
			isright=true;
			  }
		 }	 
			}
	}
	
	return isright;
}
 
function islose()
{                //判断是否输掉游戏
   if (lose_view==false) {
	 var los=0;
	 for(var i5=0;i5<16;i5++)
	 { if(flag[i5]==true)
	   {
		   los++;
		   }
		 }
		 if(los==16)
		 {
			 var left=isleft();
             var right=isright();
			 var top=istop();
			 var bottom=isbottom();
			 
			 if((left||right||top||bottom)==false)
			 {	
				max_score();	
				var $h1=$('<div>');
				//var $bu1=$('<button>');
				var $par=$("body");
				$h1.attr("id","reset1");
				$h1.text('Game Over !');
				//$bu1.text('重新开始');
				//$bu1.attr("id","reset2");		
				$par.append($h1);
				//$par.append($bu1);
				
			var sleep = function(time) {
			    var startTime = new Date().getTime() + parseInt(time, 10);
			    while(new Date().getTime() < startTime) {}
			};
			lose_view=true;
		
			 //跳出失败提醒界面				
			//$bu1.click(restart());
			
			//$("body").on("touchend",restart());			
			//$("body").on("touchstart",function (){
			//	  $par[0].removeChild($h1[0]);
			// $par[0].removeChild($bu1[0]);
			// restart();
			//  });
			
			 }
  		}
	}
}
 
 
function topgo(){   
             //上移
	var top1=istop(); 
 
	for(var ss6=0;ss6<3;ss6++)
	{
	for(var i6=4;i6<16;i6++)
	{
     if(flag[i6]==true)
	 {
		 if(flag[i6-4]==true)
      {
		  if( ds[i6].innerHTML==ds[i6-4].innerHTML )
		{  var sum=parseInt(ds[i6].innerHTML)*2;
		  ds[i6-4].innerHTML=sum;
		  flag[i6]=false;
		  ds[i6].removeAttribute("style");
		  ds[i6].innerHTML="";
		}
		  }
		  else
		  {
			ds[i6-4].innerHTML=ds[i6].innerHTML;
			 ds[i6-4].style.backgroundColor="#FF9E3E";
			flag[i6-4]=true;
			 
			ds[i6].innerHTML="";
			ds[i6].removeAttribute("style");
			flag[i6]=false;		
		 }
		 } 	 
		}
		}
       
		if(top1==true) 
		{
		var kk1=Math.round(Math.random()*15);
		while(flag[kk1]==true)
		{
			var kk1=Math.round(Math.random()*15);
			}
         ds[kk1].innerHTML="2";
		 flag[kk1]=true;
	    addcolor();
	  
		}
		else
		{
			islose();
			}
	}
 
function leftgo(){                      //左移
	var left1=isleft();
	for(var ss7=0;ss7<3;ss7++)
	{
	for(var i7=0;i7<4;i7++)
	{
		for(var j7=0;j7<3;j7++)
	{
		 if(flag[j7+4*i7+1]==true)
	 {
		 if(flag[j7+4*i7]==true)
      {
		  if( ds[j7+4*i7].innerHTML==ds[j7+4*i7+1].innerHTML )
		{  var sum=parseInt(ds[j7+4*i7+1].innerHTML)*2;
		  ds[j7+4*i7].innerHTML=sum;
		  flag[j7+4*i7+1]=false;
		  ds[j7+4*i7+1].removeAttribute("style");
		  ds[j7+4*i7+1].innerHTML="";
		}
		  }
		  else
		  {
			ds[j7+4*i7].innerHTML=ds[j7+4*i7+1].innerHTML;
			 ds[j7+4*i7].style.backgroundColor="#FF9E3E";
			flag[j7+4*i7]=true;
			 
			ds[j7+4*i7+1].innerHTML="";
			ds[j7+4*i7+1].removeAttribute("style");
			flag[j7+4*i7+1]=false;
			
			  }
		 }	 
			}
	}
	}
	
	if(left1==true){
	var kk2=Math.round(Math.random()*15);
		while(flag[kk2]==true)
		{
			var kk2=Math.round(Math.random()*15);
			}
		 ds[kk2].style.backgroundColor="#FF9E3E";
         ds[kk2].innerHTML="2";
		 flag[kk2]=true;
	addcolor();
}
   else
   {
	   islose();
	   }
}
 
function rightgo(){                //右移
	var right1=isright();
	for(var ss8=0;ss8<3;ss8++)
	{
	for(var i8=3;i8>=0;i8--)
	{
		for(var j8=2;j8>=0;j8--)
	{
		 if(flag[j8+4*i8]==true)
	 {
		 if(flag[j8+4*i8+1]==true)
      {
		  if( ds[j8+4*i8].innerHTML==ds[j8+4*i8+1].innerHTML )
		{  var sum=parseInt(ds[j8+4*i8+1].innerHTML)*2;
		  ds[j8+4*i8+1].innerHTML=sum;
		  flag[j8+4*i8]=false;
		  ds[j8+4*i8].removeAttribute("style");
		  ds[j8+4*i8].innerHTML="";
		}
		  }
		  else
		  {
			ds[j8+4*i8+1].innerHTML=ds[j8+4*i8].innerHTML;
			 ds[j8+4*i8+1].style.backgroundColor="#FF9E3E";
			flag[j8+4*i8+1]=true;
			 
			ds[j8+4*i8].innerHTML="";
			ds[j8+4*i8].removeAttribute("style");
			flag[j8+4*i8]=false;
			
			  }
		 }	 
			}
	}}
	
	if(right1==true){
	var kk3=Math.round(Math.random()*15);
		while(flag[kk3]==true)
		{
			var kk3=Math.round(Math.random()*15);
			}
		 ds[kk3].style.backgroundColor="#FF9E3E";
         ds[kk3].innerHTML="2";
		 flag[kk3]=true;
	addcolor();
	}
	else
	{
		islose();
		}
		
	//	var ss=max_score();
		//alert(ss);
}
 
function bottomgo(){                 		//下移
	var bottom1=isbottom();
	for(var ss9=0;ss9<3;ss9++)
	{
	for(var i9=11;i9>=0;i9--)
	{
     if(flag[i9]==true)
	 {
		 if(flag[i9+4]==true)
      {
		  if( ds[i9].innerHTML==ds[i9+4].innerHTML )
		{  var sum=parseInt(ds[i9].innerHTML)*2;
		  ds[i9+4].innerHTML=sum;
		  flag[i9]=false;
		  ds[i9].removeAttribute("style");
		  ds[i9].innerHTML="";
		}
		  }
		  else
		  {
			ds[i9+4].innerHTML=ds[i9].innerHTML;
			 ds[i9+4].style.backgroundColor="#FF9E3E";
			flag[i9+4]=true;
			 
			ds[i9].innerHTML="";
			ds[i9].removeAttribute("style");
			flag[i9]=false;
			
		 }
		 } 	 
		}
	}
	    
		if(bottom1==true){
		var kk4=Math.round(Math.random()*15);
		while(flag[kk4]==true)
		{
			var kk4=Math.round(Math.random()*15);
			}
		 ds[kk4].style.backgroundColor="#FF9E3E";
         ds[kk4].innerHTML="2";
		 flag[kk4]=true;
		 addcolor()
		 }
		 else
		 {
			islose();
			 }
}

css代码:

@charset "utf-8";
/* CSS Document */
body,html{
	height:100vw;
	width: 100vw;
	padding: 0;
	margin: 0;
	background:fixed;
	background-color: papayawhip;
	}
	
.authorized {
	color: grey;
	margin-left: 2%;
	text-align:center;
	font-style: normal;
	font-size:210%;
	margin-top:10%;
	width: 30%;
   }
   
.restart {
	position: absolute;
	margin-left: 5%;
	width: 25vw;
	height: 10vw;
	padding-top:5%;
	text-align:center;
	font-size: 22px;
	background-color:#99CCCC;
	color: white;
	border-radius: 5% 5% 5% 5%;
}
   
.score {
	position: absolute;
	margin-left: 50%;
	padding-top: 2%;
	width:45vw ;
	background-color:#99CCCC;
	color: white;
	border-radius:5% 5% 5% 5%;
}
 
.maxnum {	
	position: relative;
	float:left;
	margin-left: 3%;
	font-size: 120%;
	text-align: center;
	color: white;
	width: 40%;
	height: 4vw;
}
#num_p {
	margin-top: 5%;
	margin-left: 5%;
}
#num_v {
	margin-top: 5%;
	color:#ffd700;
	font-size: 25px;}
  
.game{
	position:absolute;
   	top:30% ;
	left:2.5%;
	width:95vw;
    height:95vw;
	background-color:#AAAA; 
	border-radius:5% 5% 5% 5%;
	     }
		 
 #reset1{
	position:absolute;
	top:30% ;
	left:2.5%;
	width:95vw;
	height:60vw;
	font-size: 40px;
	background: rgba(250,250,250,0.5);
	text-align: center;
	padding-top: 35%;
	color: grey;
	border-radius:5% 5% 5% 5%;} 
 
#reset2 {
position:absolute;
width: 30vw;
height: 13vw;
margin:70% 20% 30% 35%;
font-size: 20px;
padding-left: 0.125rem;
background-color: lightsalmon;
font-weight: bold;
color: white;
border-radius:5% 5% 5% 5%;
}
 
.square{
	position:relative;
	width:23%;
	height:23%;
    line-height: 180%; /*行高,指的是两行文字基线之间的距离,又可以称为这行文字所占的高度 */
	float:left;
	background-color:#DDDDDD;
	border-radius:15% 15% 15% 15%;
	margin:1% 1% 1% 1%;
	color:white;
	text-align:center;
	font-size:12vw;
	}

四、源码及APK

可以利用Hbuilder将H5代码打包成移动端应用,这样我们就可以在手机端安装APP愉快的玩耍了。下面是我打包的安卓包,点击自取:2048-touch_jb51.rar

到此这篇关于如何用H5实现好玩的2048小游戏的文章就介绍到这了,更多相关HTML5实现2048游戏内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章,希望大家以后多多支持三水点靠木!

 
HTML / CSS 相关文章推荐
css3弹性盒模型(Flexbox)详细介绍
Oct 08 HTML / CSS
css3的transform造成z-index无效解决方案
Dec 04 HTML / CSS
用CSS3打造HTML5的Logo(实现代码)
Jun 16 HTML / CSS
CSS3圆角边框和边界图片效果实例
Jul 01 HTML / CSS
纯CSS3实现漂亮的input输入框动画样式库(Text input love)
Dec 29 HTML / CSS
HTML5地理定位与第三方工具百度地图的应用
Nov 17 HTML / CSS
HTML5里autofocus自动聚焦属性使用介绍
Jun 22 HTML / CSS
HTML5中的Article和Section元素认识及使用
Mar 22 HTML / CSS
html5使用canvas实现弹幕功能示例
Sep 11 HTML / CSS
canvas如何绘制钟表的方法
Dec 13 HTML / CSS
解析浏览器的一些“滚动”行为鉴赏
Sep 16 HTML / CSS
使用SVG实现提示框功能的示例代码
Jun 05 HTML / CSS
css让页脚保持在底部位置的四种方案
Jul 23 #HTML / CSS
浅谈为什么我的 z-index 又不生效了
Jul 15 #HTML / CSS
纯CSS实现一个简单步骤条的示例代码
Jul 15 #HTML / CSS
CSS中使用grid布局实现一套模板多种布局
Jul 15 #HTML / CSS
如何解决flex文本溢出问题小结
Jul 15 #HTML / CSS
使用HBuilder制作一个简单的HTML5网页
使用CSS定位HTML元素的实现方法
You might like
php下将多个数组合并成一个数组的方法与实例代码
2011/02/03 PHP
ajax完美实现两个网页 分页功能的实例代码
2013/04/16 PHP
php 判断字符串中是否包含html标签
2014/02/17 PHP
PHP实现将科学计数法转换为原始数字字符串的方法
2014/12/16 PHP
刷新PHP缓冲区为你的站点加速
2015/10/10 PHP
解决php写入数据库乱码的问题
2019/09/17 PHP
JavaScript 图片预览效果 推荐
2009/12/22 Javascript
JavaScript中的View-Model使用介绍
2011/08/11 Javascript
Js 时间间隔计算的函数(间隔天数)
2011/11/15 Javascript
微信JS接口汇总及使用详解
2015/01/09 Javascript
JavaScript中setTimeout和setInterval函数的传参及调用
2016/03/11 Javascript
WebPack基础知识详解
2017/01/16 Javascript
jQuery实现的分页功能示例
2017/01/22 Javascript
jQuery动态生成不规则表格(前后端)
2017/02/21 Javascript
详解JS数组Reduce()方法详解及高级技巧
2017/08/18 Javascript
深入浅出vue图片路径的实现
2019/09/04 Javascript
Openlayers实现地图全屏显示
2020/09/28 Javascript
JavaScript实现图片合成下载的示例
2020/11/19 Javascript
Python对字符串实现去重操作的方法示例
2017/08/11 Python
浅谈tensorflow1.0 池化层(pooling)和全连接层(dense)
2018/04/27 Python
Python之Django自动实现html代码(下拉框,数据选择)
2020/03/13 Python
Python如何将函数值赋给变量
2020/04/28 Python
关于Python3的import问题(pycharm可以运行命令行import错误)
2020/11/18 Python
详解CSS3选择器:nth-child和:nth-of-type之间的差异
2017/09/18 HTML / CSS
海信商城:海信电视、科龙空调、容声冰箱官方专卖
2017/02/07 全球购物
美国最大的农村生活方式零售店:Tractor Supply Company(TSC)
2017/05/15 全球购物
Notino罗马尼亚网站:购买香水和化妆品
2019/07/20 全球购物
Notino瑞典:购买香水和美容产品
2019/07/26 全球购物
室内设计实习自我鉴定
2013/09/25 职场文书
英文简历中的自我评价
2013/10/06 职场文书
消防安全检查制度
2014/02/04 职场文书
网吧管理制度范本
2015/08/05 职场文书
小学语文新课改心得体会
2016/01/22 职场文书
Java并发编程之原子性-Atomic的使用
2022/03/16 Java/Android
win10电脑右下角输入法图标不见了?Win10右下角不显示输入法的解决方法
2022/07/23 数码科技
Java Redisson多策略注解限流
2022/09/23 Java/Android