原生JavaScript实现2048游戏完整教程

作者:木棉时间:2026-10-24 08:49:52浏览:385

本文详细介绍如何使用原生JavaScript、HTML和CSS从零构建2048小游戏。内容涵盖16格网格的DOM结构创建、二维数组存储格子对象、随机生成数字2或4的逻辑、键盘事件监听以及上下左右移动合并算法,适合前端初学者学习游戏开发基础。

本文分享一个2048小游戏的完整实现案例,供读者参考学习。

HTML与CSS界面布局

开发2048游戏的基础是构建包含16个格子的网格界面。首先利用HTML和CSS完成标签定义与样式设置,随后编写JavaScript核心逻辑。


<div id="box">//一个盒子里面16个小div
 <div id="son"></div>
 <div id="son"></div>
 <div id="son"></div>
 <div id="son"></div>
 <div id="son"></div>
 <div id="son"></div>
 <div id="son"></div>
 <div id="son"></div>
 <div id="son"></div>
 <div id="son"></div>
 <div id="son"></div>
 <div id="son"></div>
 <div id="son"></div>
 <div id="son"></div>
 <div id="son"></div>
 <div id="son"></div>
</div>

具体的CSS样式设置如下(仅供参考):


#box{
 width: 450px;
 height: 450px;
 background-color: brown;
 display: flex;
 flex-wrap: wrap;
 justify-content: space-evenly;
 border: 1px solid #000;
 margin: 100px auto;
 border-radius: 10px;
 }
 div>div{
 margin-top: 5px;
 width: 100px;
 height: 100px;
 border-radius: 5px;
 background-color: bisque;
 text-align: center;
 line-height: 100px;
 font-size: 40px;
 }

页面渲染效果如下图所示:

HTML与CSS界面布局

JavaScript核心逻辑实现

接下来进入JavaScript核心逻辑的实现阶段。首先,使用CSS选择器获取页面中所有代表小格子的div元素。


var divs = document.querySelectorAll('[id ==son]');

随后,创建一个二维数组用于存储这16个格子对应的DOM对象,以便后续通过坐标进行访问和操作。


var arr = [[],[],[],[]];
var a = 0;
for(var i=0 ;i < 4; i ++){
 for(var j=0 ;j < 4; j++){
 arr[i][j] = divs[a];
 a++ ;
 }
}

通过上述步骤,我们建立了基于i和j轴的二维数据结构。

HTML与CSS界面布局

这种数据结构的设计极大地简化了后续移动和合并操作的逻辑实现。

接下来编写一个函数,用于在16个格子中随机选择一个空格子,并填入数字2或4。该函数将在后续步骤中被多次调用。


function sj(){ //产生随机数
 var a = Math.floor(Math.random() * 4);
 var b = Math.floor(Math.random() * 4);
 if(arr[a][b].innerHTML == ""){
 if(Math.random()>0.5){
 arr[a][b].innerHTML = 2;
 }else{
 arr[a][b].innerHTML = 4;
 }
 
 }else{ //如果该格子不为空我们在执行函数
 sj();
 }
}

另一个关键函数用于判断游戏是否结束:当所有格子均被填满且无法继续合并时,判定游戏结束。此函数同样需要在后续逻辑中调用。


function js(){ //游戏是否结束
 var bool = true;
 for(var i=0 ;i < 4; i ++){
 for(var j=0 ;j < 4; j++){
 if(arr[i][j].innerHTML == ""){
  bool = false;
 }else{
  
 }
 }
 } 
 if(bool){
 alert("游戏结束");
 for(var i=0 ;i < 4; i ++){
 for(var j=0 ;j < 4; j++){
 arr[i][j] = null;
 }
 }
 
 }
}

接下来分别编写响应键盘上下左右按键的函数逻辑。

以“向上”移动为例进行详细说明:

具体逻辑包括:①若上方格子为空且当前格子不为空,则交换两者的值;②若上方格子有数字且与当前格子数值相等,则将上方格子的值乘以2,当前格子置为空。其他情况保持不变。


function downtop(){ //按上 执行的函数
 for(var i=0 ;i < 4; i ++){
 for(var j=0 ;j < 4; j++){
 if(arr[i][j].innerHTML == "" && i<3 &&arr[i+1][j].innerHTML != ""){
 arr[i][j].innerHTML = arr[i+1][j].innerHTML ;
 arr[i+1][j].innerHTML = "";
 downtop(); // 如果条件满足就执行
  // 不满足了就不会进入到if里了
 }else if(i<3&&arr[i][j].innerHTML !="" && arr[i+1][j].innerHTML !="" &&arr[i][j].innerHTML == arr[i+1][j].innerHTML){
 arr[i][j].innerHTML = 2*arr[i+1][j].innerHTML ;
 arr[i+1][j].innerHTML = "";
 }else{
 
 }
 }
 }

}

同理只需调整(部分参数)即可实现其余三个方向按键的逻辑:


function downbottom(){
 for(var i=3 ;i > 0 ; i--){
 for(var j=0 ;j < 4; j++){
 if(arr[i-1][j].innerHTML != "" && i>0 &&arr[i][j].innerHTML == "" ){ 
 arr[i][j].innerHTML = arr[i-1][j].innerHTML ;
 arr[i-1][j].innerHTML = "";
 downbottom();
 }
 else if(arr[i-1][j].innerHTML !=""&& arr[i][j].innerHTML !="" && i>0 &&arr[i-1][j].innerHTML == arr[i][j].innerHTML){
 arr[i][j].innerHTML = 2*arr[i-1][j].innerHTML ;
 arr[i-1][j].innerHTML = "";
 }
 }
 }
}

function downleft(){
 for(var i=0 ;i < 4; i ++){
 for(var j=0 ;j < 4; j++){
 if(arr[i][j].innerHTML == "" && j<3 &&arr[i][j+1].innerHTML != ""){
 arr[i][j].innerHTML = arr[i][j+1].innerHTML ;
 arr[i][j+1].innerHTML = "";
 downleft();
 }else if( j<3&& arr[i][j].innerHTML !=""&& arr[i][j+1].innerHTML !="" &&arr[i][j].innerHTML == arr[i][j+1].innerHTML){
 arr[i][j].innerHTML = 2*arr[i][j+1].innerHTML ;
 arr[i][j+1].innerHTML = "";
 }
 }
 }

}


function downright(){
 
 for(var i=0 ;i < 4; i ++){
 for(var j = 3 ;j > 0; j--){
 if(j > 0 && arr[i][j].innerHTML == ""&&arr[i][j-1].innerHTML != ""){
 arr[i][j].innerHTML = arr[i][j-1].innerHTML ;
 arr[i][j-1].innerHTML = "";
 downright();
 }else if( j>0 && arr[i][j].innerHTML !=""&& arr[i][j-1].innerHTML !="" &&arr[i][j].innerHTML == arr[i][j-1].innerHTML){
 arr[i][j].innerHTML = 2*arr[i][j-1].innerHTML ;
 arr[i][j-1].innerHTML = "";
 }
 }
 }

 }

为不同数值的格子设置不同的背景颜色(此功能可选,视需求而定)。


function color(){

for(var i=0 ;i < 4; i ++){
 for(var j=0 ;j < 4; j++){
 switch(arr[i][j].innerHTML){
 case "": arr[i][j].style.backgroundColor = "bisque";break; 
 case "2": arr[i][j].style.backgroundColor = "red";break; 
 case "4": arr[i][j].style.backgroundColor = "orange";break; 
 case "8": arr[i][j].style.backgroundColor = "yellow";break; 
 case "16": arr[i][j].style.backgroundColor = "green";break; 
 case "32": arr[i][j].style.backgroundColor = "blue";break; 
 case "64": arr[i][j].style.backgroundColor = "#000";break; 
 case "128": arr[i][j].style.backgroundColor = "aqua";break; 
 case "256": arr[i][j].style.backgroundColor = "pink";break; 
 }
 
 
 }
}

}

键盘事件监听与游戏流程控制

最后,为整个窗口绑定键盘监听事件,以响应用户的操作。

各方向按键对应的keyCode分别为:上38、下40、左37、右39。每次按键触发后,依次执行以下操作:①调用对应方向的移动函数;②调用随机生成数字的函数;③调用判断游戏是否结束的函数;④调用根据数值更新样式的函数。此外,游戏初始化时需调用两次随机生成函数,以预设初始的两个数字。


window.onkeydown = function(e){
 switch(e.keyCode){
 case 37: downleft(); sj(); color(); js(); break; //左
 case 38: downtop(); sj(); color(); js(); break; //上
 case 39: downright(); sj(); color(); js(); break; //右
 case 40: downbottom(); sj(); color(); js(); break; //下
 }

}
sj(); //开局自动有默认的2个数
sj(); 

至此,一个简单的2048小游戏即告完成。

以上就是本文的全部内容,希望能为读者的学习带来帮助,也欢迎大家继续支持本站。

作者最新文章