序言
欢迎来到“2048”的魔法阵 🔢
本篇带来简易版-2048 数字游戏的编程实践~
废话少说,直接开冲!!
先看码上掘金效果:
设计思路
首先,玩过 2048 的都知道:基础版本是一个 4x4 的网格,作为游戏的主界面;
然后关键是生成数字和移动,即:
1、游戏在开始时和每次数字移动后要随机在空白格子生成数字2或4
2、玩家可以通过上、下、左、右箭头键移动数字。相同的数字在移动过程中会合并
接着就是,每一轮操作后,游戏界面格子的数字要实时更新;
按照这个思路,设想一下:会有哪些函数方法?
那么,一些基础的应该有比如:
-
initializeGame()
: 初始化游戏界面,生成4x4的网格; -
handleInput(event)
: 处理用户的键盘输入,控制数字的移动方向; -
slide(direction)
: 根据用户的输入移动和合并数字; -
getColumn(col)
: 获取指定列的数字,辅助处理上下移动的逻辑; -
addNumber()
: 在空白的格子中随机生成数字2或4; -
render()
: 更新并渲染游戏界面,显示当前的数字分布;
代码实现
有了基本思路,直接开撸~
HTML 和 CSS 部分比较简单,JS 部分按照上述思路逐步细化:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>2048 Game</title>
<style>
#game-container {
display: grid;
grid-template-columns: repeat(4, 100px);
grid-template-rows: repeat(4, 100px);
gap: 10px;
margin: 50px auto;
}
.cell {
width: 100px;
height: 100px;
background-color: #f4f4f4;
display: flex;
justify-content: center;
align-items: center;
font-size: 32px;
font-weight: bold;
}
</style>
</head>
<body>
<div id="game-container"></div>
<script>
const size = 4;
let grid = Array(size).fill().map(() => Array(size).fill(''));
function createCell(row, col) {
const cell = document.createElement('div');
cell.id = `cell-${row}-${col}`;
cell.className = 'cell';
return cell;
}
// 初始化4x4的网格
function initializeGame() {
const gameContainer = document.getElementById('game-container');
for (let row = 0; row < size; row++) {
for (let col = 0; col < size; col++) {
gameContainer.appendChild(createCell(row, col));
}
}
}
document.addEventListener('keydown', handleInput);
// 处理用户的键盘输入
function handleInput(event) {
let gridChanged = false;
switch (event.key) {
case 'ArrowUp':
gridChanged = slide('up');
break;
case 'ArrowDown':
gridChanged = slide('down');
break;
case 'ArrowLeft':
gridChanged = slide('left');
break;
case 'ArrowRight':
gridChanged = slide('right');
break;
}
// 如果网格发生了改变,添加新的数字并重新渲染界面
if (gridChanged) {
addNumber();
render();
}
}
// 根据用户的输入移动和合并数字
function slide(direction) {
const originalGrid = JSON.stringify(grid);
for (let i = 0; i < size; i++) {
let row = (direction === 'up' || direction === 'down') ? getColumn(i) : grid[i].slice();
row = row.filter(cell => cell !== ''); // Remove empty cells
if (direction === 'down' || direction === 'right') {
row.reverse();
}
for (let j = 1; j < row.length; j++) {
if (row[j - 1] === row[j]) {
row[j - 1] *= 2;
row[j] = '';
}
}
row = row.filter(cell => cell !== ''); // Remove merged cells
while (size - row.length) {
row.push(''); // Fill the row with empty cells
}
if (direction === 'down' || direction === 'right') {
row.reverse();
}
if (direction === 'up' || direction === 'down') {
for (let j = 0; j < size; j++) {
grid[j][i] = row[j];
}
} else {
grid[i] = row;
}
}
return JSON.stringify(grid) !== originalGrid;
}
// 获取指定列的数字
function getColumn(col) {
const column = [];
for (let i = 0; i < size; i++) {
column.push(grid[i][col]);
}
return column;
}
// 在空白的格子中随机生成数字2或4
function addNumber() {
const availableCells = [];
for (let i = 0; i < size; i++) {
for (let j = 0; j < size; j++) {
if (!grid[i][j]) {
availableCells.push({ row: i, col: j });
}
}
}
if (availableCells.length) {
const { row, col } = availableCells[Math.floor(Math.random() * availableCells.length)];
grid[row][col] = Math.random() < 0.9 ? 2 : 4;
}
}
// 更新并渲染游戏界面
function render() {
grid.forEach((row, i) => {
row.forEach((number, j) => {
const cell = document.getElementById(`cell-${i}-${j}`);
cell.textContent = number || '';
});
});
}
initializeGame();
addNumber();
addNumber();
render();
</script>
</body>
</html>
打完收工,整个代码思路比较清晰的~ 我们将代码分割成多个函数,使每个函数都有明确的职责,也可以提高代码的可读性和可维护性。
代码调优
更进一步:代码调优;毕竟代码总是有优化的空间。
针对以上代码,我们还有能做的,比如:
1、还差一个结束判断,即当没有空格且所有相邻的数字都不相等时,添加一个函数来判断游戏是否结束,并给出相应的提示;
2、还可以为玩家提供撤销上一步的操作的功能,增加游戏的可玩性;
3、还可以考虑兼顾响应式兼容等等
所以以上只是一个简易版的 2048,可以更快地帮助我们理解代码的功能和运行机制
以上!以上便是本次键码经典游戏之 2048 分享;
感兴趣的同学可以动手试试~