2048 游戏实现

AI 智能总结

简介

2048 是一款风靡全球的数字益智游戏,玩家通过方向键滑动 4x4 棋盘上的数字方块,相同数字碰撞时合并为两倍,目标是合成 2048。游戏厅版本完整实现了滑动合并算法、分数计算和游戏结束判定。

数据结构

棋盘表示

使用 4x4 二维数组存储每个格子的数值,0 表示空格:

1var SIZE = 4;
2var board = [];
3for (var i = 0; i < SIZE; i++) {
4  board[i] = [0, 0, 0, 0];
5}

CSS Grid 渲染

棋盘使用 CSS Grid 布局:

1.tzfe-board {
2  display: grid;
3  grid-template-columns: repeat(4, var(--tz-cell, 72px));
4  grid-template-rows: repeat(4, var(--tz-cell, 72px));
5  gap: 8px;
6  padding: 8px;
7  background: #bbada0;
8  border-radius: 8px;
9}

核心算法

单行滑动合并

滑动的核心逻辑:去掉空格 → 合并相邻相同数字 → 补零到长度 4:

 1function slideRow(row) {
 2  // 1. 过滤掉所有 0
 3  var arr = row.filter(function(v) { return v !== 0; });
 4
 5  // 2. 从左到右合并相邻相同数字
 6  for (var i = 0; i < arr.length - 1; i++) {
 7    if (arr[i] === arr[i + 1]) {
 8      arr[i] *= 2;
 9      score += arr[i];
10      arr.splice(i + 1, 1); // 移除被合并的元素
11    }
12  }
13
14  // 3. 末尾补 0 到长度 4
15  while (arr.length < SIZE) arr.push(0);
16
17  return arr;
18}

四个方向实现

利用单行滑动算法,四个方向通过旋转矩阵实现:

 1function move(direction) {
 2  var moved = false;
 3  var oldBoard = board.map(function(r) { return r.slice(); });
 4
 5  if (direction === 'left') {
 6    for (var i = 0; i < SIZE; i++) board[i] = slideRow(board[i]);
 7  }
 8  else if (direction === 'right') {
 9    // 反转 → 左滑 → 反转回来
10    for (var i = 0; i < SIZE; i++)
11      board[i] = slideRow(board[i].slice().reverse()).reverse();
12  }
13  else if (direction === 'up') {
14    // 提取列 → 左滑 → 写回
15    for (var j = 0; j < SIZE; j++) {
16      var col = [];
17      for (var i = 0; i < SIZE; i++) col.push(board[i][j]);
18      col = slideRow(col);
19      for (var i = 0; i < SIZE; i++) board[i][j] = col[i];
20    }
21  }
22  else if (direction === 'down') {
23    // 提取列(反向) → 左滑 → 反向写回
24    for (var j = 0; j < SIZE; j++) {
25      var col = [];
26      for (var i = SIZE - 1; i >= 0; i--) col.push(board[i][j]);
27      col = slideRow(col).reverse();
28      for (var i = 0; i < SIZE; i++) board[i][j] = col[SIZE - 1 - i];
29    }
30  }
31
32  // 检测是否发生移动
33  for (var i = 0; i < SIZE; i++)
34    for (var j = 0; j < SIZE; j++)
35      if (oldBoard[i][j] !== board[i][j]) moved = true;
36
37  return moved;
38}

随机生成

在空白位置随机生成 2(90%概率)或 4(10%概率):

 1function spawnTile() {
 2  var emptyCells = [];
 3  for (var i = 0; i < SIZE; i++)
 4    for (var j = 0; j < SIZE; j++)
 5      if (board[i][j] === 0) emptyCells.push([i, j]);
 6
 7  if (emptyCells.length === 0) return false;
 8
 9  var pos = emptyCells[Math.floor(Math.random() * emptyCells.length)];
10  board[pos[0]][pos[1]] = Math.random() < 0.9 ? 2 : 4;
11  return true;
12}

游戏结束判定

当没有空格且任何相邻格子都无法合并时,游戏结束:

1function canMove() {
2  for (var i = 0; i < SIZE; i++)
3    for (var j = 0; j < SIZE; j++) {
4      if (board[i][j] === 0) return true;
5      if (j < SIZE - 1 && board[i][j] === board[i][j + 1]) return true;
6      if (i < SIZE - 1 && board[i][j] === board[i + 1][j]) return true;
7    }
8  return false;
9}

2048 达成检测

1function checkWin() {
2  for (var i = 0; i < SIZE; i++)
3    for (var j = 0; j < SIZE; j++)
4      if (board[i][j] === 2048) return true;
5  return false;
6}

方块颜色系统

不同数值的方块使用不同背景色,从浅到深:

 1.tzfe-tile.t2    { background: #eee4da; color: #776e65; }
 2.tzfe-tile.t4    { background: #ede0c8; color: #776e65; }
 3.tzfe-tile.t8    { background: #f2b179; color: #f9f6f2; }
 4.tzfe-tile.t16   { background: #f59563; color: #f9f6f2; }
 5.tzfe-tile.t32   { background: #f67c5f; color: #f9f6f2; }
 6.tzfe-tile.t64   { background: #f65e3b; color: #f9f6f2; }
 7.tzfe-tile.t128  { background: #edcf72; color: #f9f6f2; font-size: 1.5rem; }
 8.tzfe-tile.t256  { background: #edcc61; color: #f9f6f2; font-size: 1.5rem; }
 9.tzfe-tile.t512  { background: #edc850; color: #f9f6f2; font-size: 1.5rem; }
10.tzfe-tile.t1024 { background: #edc53f; color: #f9f6f2; font-size: 1.2rem; }
11.tzfe-tile.t2048 { background: #edc22e; color: #f9f6f2; font-size: 1.2rem; }

2 和 4 使用深色文字,8 及以上使用白色文字。128 以上缩小字号以适配格子大小。

游戏结束覆盖层

游戏结束时显示半透明覆盖层和提示文字:

 1.tzfe-overlay {
 2  position: absolute;
 3  inset: 0;
 4  background: rgba(238, 228, 218, 0.73);
 5  display: flex;
 6  align-items: center;
 7  justify-content: center;
 8  border-radius: 8px;
 9  z-index: 10;
10}
11.tzfe-overlay-msg {
12  font-size: 2rem;
13  font-weight: 800;
14  color: #776e65;
15}

分数与最高分

1// 更新最高分
2if (score > best) {
3  best = score;
4  localStorage.setItem('arcade-tzfe-best', best);
5}
6
7// 状态栏更新
8document.getElementById('atz-score').textContent = score;
9document.getElementById('atz-best').textContent = best;

总结

2048 的核心在于单行滑动合并算法的设计——通过反转和矩阵转置,四个方向都可以复用同一个 slideRow 函数。CSS Grid 渲染配合颜色分级系统提供了清晰的视觉反馈。

留言评论

期待你的想法

评论加载中