You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用JavaScript实现Pacman地图随机化?每次打开生成不同地图

Pacman随机地图实现方案

核心思路

把原来的静态world变量替换成动态生成函数的返回值,每次页面加载时调用该函数生成不同的地图结构,再交给drawWorld渲染。


步骤1:编写随机地图生成函数

根据Pacman地图的元素规则(比如0=路径、1=墙、2=食物、3=Pacman出生点、4=幽灵出生点),编写生成逻辑。以下提供两种方案:

方案A:简单随机生成(快速实现)

适合快速迭代,控制墙的比例,避开出生点区域:

// 定义地图尺寸
const MAP_ROWS = 20;
const MAP_COLS = 20;

function generateRandomWorld() {
  // 初始化全路径地图
  let world = Array(MAP_ROWS).fill().map(() => Array(MAP_COLS).fill(0));
  
  // 随机生成墙(占比约35%)
  const wallCount = Math.floor(MAP_ROWS * MAP_COLS * 0.35);
  for (let i = 0; i < wallCount; i++) {
    let row = Math.floor(Math.random() * MAP_ROWS);
    let col = Math.floor(Math.random() * MAP_COLS);
    // 避开中心出生点区域
    if (Math.abs(row - MAP_ROWS/2) > 2 && Math.abs(col - MAP_COLS/2) > 2) {
      world[row][col] = 1;
    }
  }
  
  // 设置Pacman出生点(中心偏下)
  const pacmanRow = Math.floor(MAP_ROWS/2) + 1;
  const pacmanCol = Math.floor(MAP_COLS/2);
  world[pacmanRow][pacmanCol] = 3;
  
  // 设置幽灵出生点(中心偏上)
  const ghostRow = Math.floor(MAP_ROWS/2) - 1;
  const ghostCol = Math.floor(MAP_COLS/2);
  world[ghostRow][ghostCol] = 4;
  
  // 填充食物(所有路径位置)
  for (let row = 0; row < MAP_ROWS; row++) {
    for (let col = 0; col < MAP_COLS; col++) {
      if (world[row][col] === 0) {
        world[row][col] = 2;
      }
    }
  }
  
  return world;
}

方案B:迷宫式生成(保证连通性)

用深度优先搜索生成完整连通的迷宫,避免Pacman被困:

const MAP_ROWS = 20;
const MAP_COLS = 20;

function generateMazeWorld() {
  // 初始全为墙
  let world = Array(MAP_ROWS).fill().map(() => Array(MAP_COLS).fill(1));
  const stack = [];
  
  // 从中心位置开始打通迷宫
  let currentRow = Math.floor(MAP_ROWS/2);
  let currentCol = Math.floor(MAP_COLS/2);
  world[currentRow][currentCol] = 0;
  stack.push([currentRow, currentCol]);
  
  // 四个方向(上下左右,步长为2保证墙的间隔)
  const directions = [[-2,0], [2,0], [0,-2], [0,2]];
  
  while (stack.length > 0) {
    const [row, col] = stack.pop();
    // 随机打乱方向顺序
    const shuffledDirs = [...directions].sort(() => Math.random() - 0.5);
    
    for (const [dr, dc] of shuffledDirs) {
      const newRow = row + dr;
      const newCol = col + dc;
      // 检查边界和是否为墙
      if (newRow > 0 && newRow < MAP_ROWS-1 && newCol > 0 && newCol < MAP_COLS-1 && world[newRow][newCol] === 1) {
        // 打通当前位置与新位置之间的墙
        world[row + dr/2][col + dc/2] = 0;
        world[newRow][newCol] = 0;
        stack.push([newRow, newCol]);
      }
    }
  }
  
  // 设置出生点和食物(同方案A)
  const pacmanRow = Math.floor(MAP_ROWS/2) + 1;
  const pacmanCol = Math.floor(MAP_COLS/2);
  world[pacmanRow][pacmanCol] = 3;
  
  const ghostRow = Math.floor(MAP_ROWS/2) - 1;
  const ghostCol = Math.floor(MAP_COLS/2);
  world[ghostRow][ghostCol] = 4;
  
  for (let row = 0; row < MAP_ROWS; row++) {
    for (let col = 0; col < MAP_COLS; col++) {
      if (world[row][col] === 0) {
        world[row][col] = 2;
      }
    }
  }
  
  return world;
}

步骤2:替换静态world变量

把原来的静态数组替换成生成函数的调用结果,页面加载时自动生成新地图:

// 替换原来的静态world
const world = generateRandomWorld(); // 或 generateMazeWorld()

步骤3:适配drawWorld函数

只要你的drawWorld是基于world数组的元素类型渲染(比如通过switch判断tile值),就不需要大改。示例逻辑:

function drawWorld() {
  for (let row = 0; row < world.length; row++) {
    for (let col = 0; col < world[row].length; col++) {
      const tile = world[row][col];
      switch(tile) {
        case 1:
          drawWall(col, row); // 绘制墙的函数
          break;
        case 2:
          drawFood(col, row); // 绘制食物的函数
          break;
        case 3:
          drawPacman(col, row); // 绘制Pacman的函数
          break;
        case 4:
          drawGhost(col, row); // 绘制幽灵的函数
          break;
        default:
          drawPath(col, row); // 绘制路径的函数
      }
    }
  }
}

这样每次打开页面时,都会生成全新的随机地图,满足需求。

内容的提问来源于stack exchange,提问作者user20176624

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.17 14:01:02