如何用H5實現(xiàn)好玩的2048小游戲
一、游戲介紹
相信大多數(shù)讀者都玩過一款小游戲 2048,這款數(shù)字小游戲在幾年前很是流行。2048是2014年由Gabriele Cirulli利用周末的時間寫出的,果然大佬就是大佬,一個周末就寫出了這么經(jīng)典的游戲。游戲的玩法非常簡單,利用上、下、左、右移動的方式拼出2048即算贏得游戲,因為游戲上手簡單同時贏得游戲又存在一定難度,所以游戲的可玩性很高,本人當時也是十分喜愛這款游戲,下面講解下如何用H5去實現(xiàn)這款游戲。
二、游戲界面
游戲界面十分簡單,我截圖了進行中的幾個場景,基本由一塊矩形游戲區(qū),一個按鈕及一個分數(shù)展示區(qū)域組成。

三、代碼設(shè)計
H5代碼:
H5代碼十分簡單,主要用16個div代表16個數(shù)字方塊,再加上另外restart按鈕區(qū),還有一個分值展示區(qū)域。
<!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都應(yīng)該在此事件發(fā)生后調(diào)用,否則會出現(xiàn)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代碼相對復(fù)雜一些,游戲處理邏輯主要可以分成以下兩塊:
(1)移動處理邏輯,游戲玩法是通過上下左右移動進行數(shù)字的相加變換。那么首先就會有上滑、下滑、左滑、右滑四個處理函數(shù)。上下滑動的時候,將相鄰兩行相同的數(shù)值進行相加;左右滑動的時候,將相鄰兩列相同的數(shù)值進行相加。
(2)移動判斷邏輯。
首先第一類判斷邏輯是判斷是否可以移動。整個游戲區(qū)是 4X4的格局分布,那么在上下左右移動的時候我們會通過相鄰的兩行或者兩列是否存在相同的數(shù)值去判斷,如果有則可以繼續(xù)移動,如果沒有,則不可以繼續(xù)移動。
其次,我們需要判斷游戲是否可以繼續(xù),如果整個游戲區(qū)的數(shù)值方塊已經(jīng)被占滿,上下左右都沒有移動空間了,那么游戲就是結(jié)束了,game over。
(3)其余邏輯
其余的還剩一些比較簡單的邏輯,顏色分配函數(shù)、重新開始函數(shù)、最大分值記錄函數(shù)等。
// 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個數(shù)字方塊
{
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() //記錄取得的最大分數(shù)
{
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() //設(shè)置移動時產(chǎn)生的音效
{
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() //設(shè)置方塊顏色
{ 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()
{ //判斷是否可以繼續(xù)上移,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() //判斷是否可以繼續(xù)下移,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(){ //判斷是否可以繼續(xù)左移,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(){ //判斷是否可以繼續(xù)右移,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()
{ //判斷是否輸?shù)粲螒?
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代碼打包成移動端應(yīng)用,這樣我們就可以在手機端安裝APP愉快的玩耍了。下面是我打包的安卓包,點擊自取:2048-touch_jb51.rar
到此這篇關(guān)于如何用H5實現(xiàn)好玩的2048小游戲的文章就介紹到這了,更多相關(guān)HTML5實現(xiàn)2048游戲內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持腳本之家!
相關(guān)文章

HTML5實現(xiàn)的移動端購物車自動結(jié)算功能示例代碼
本文介紹HTML5實現(xiàn)移動端購物車自動結(jié)算,通過WebStorage、事件監(jiān)聽、DOM操作等技術(shù),確保實時更新與數(shù)據(jù)同步,優(yōu)化性能及無障礙性,提升用戶體驗,感興趣的朋友一起看看吧2025-06-18- 在HTML5中,<button>標簽用于定義一個可點擊的按鈕,它是創(chuàng)建交互式網(wǎng)頁的重要元素之一,本文將深入解析HTML5中的<button>標簽,詳細介紹其屬性、樣式以及實際2025-06-18
基于 HTML5 Canvas 實現(xiàn)圖片旋轉(zhuǎn)與下載功能(完整代碼展示)
本文將深入剖析一段基于 HTML5 Canvas 的代碼,該代碼實現(xiàn)了圖片的旋轉(zhuǎn)(90 度和 180 度)以及旋轉(zhuǎn)后圖片的下載功能,通過對代碼的解讀,我們可以學習到如何利用 Canvas API2025-06-18
HTML5 getUserMedia API網(wǎng)頁錄音實現(xiàn)指南示例小結(jié)
本教程將指導(dǎo)你如何利用這一API,結(jié)合Web Audio API,實現(xiàn)網(wǎng)頁錄音功能,從獲取音頻流到處理和保存錄音,整個過程將逐步詳解,此外,還討論了getUserMedia API的使用限制和最2025-06-16- HTML5的搜索框是一個強大的工具,能夠有效提升用戶體驗,通過結(jié)合自動補全功能和適當?shù)臉邮?,可以?chuàng)建出既美觀又實用的搜索界面,這篇文章給大家介紹HTML5 搜索框Search Box2025-06-13
- Checkbox是HTML5中非常重要的表單元素之一,通過合理使用其屬性和樣式自定義方法,可以為用戶提供豐富多樣的交互體驗,這篇文章給大家介紹HTML5中Checkbox標簽的深入全面解2025-06-13
- 本實例展示了一種基于HTML5技術(shù)的圖片上傳功能,無需外部插件即可通過拖放圖片實現(xiàn)上傳,涉及到HTML5的拖放API和File API,以及使用CSS來增強用戶界面的交互性和視覺反饋,2025-05-16
- 在HTML5和CSS中,定位(positioning)是控制元素在頁面上位置的重要機制,主要有四種定位方式:靜態(tài)定位(static)、相對定位(relative)、絕對定位(absolute)和固定定位(fixed),2025-05-13
- Microdata作為HTML5新增的一個特性,它允許開發(fā)者在HTML文檔中添加更多的語義信息,以便于搜索引擎和瀏覽器更好地理解頁面內(nèi)容,本文將探討HTML5中Microdata的使用方法以及2025-04-21
在HTML語法中,表格主要通過< table >、< tr >和< td >3個標簽構(gòu)成,本文通過實例代碼講解HTML5表格語法格式,感興趣的朋友一起看看吧2025-04-21




