本文详细介绍如何使用原生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;
}
页面渲染效果如下图所示:

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轴的二维数据结构。

这种数据结构的设计极大地简化了后续移动和合并操作的逻辑实现。
接下来编写一个函数,用于在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小游戏即告完成。
以上就是本文的全部内容,希望能为读者的学习带来帮助,也欢迎大家继续支持本站。