如何用JavaScript构建控制台版扫雷游戏

来源:建站教程作者:半糖头衔:草根站长
导读:本期聚焦于小伙伴创作的《如何用JavaScript构建控制台版扫雷游戏》,敬请观看详情,探索知识的价值。以下视频、文章将为您系统阐述其核心内容与价值。如果您觉得《如何用JavaScript构建控制台版扫雷游戏》有用,将其分享出去将是对创作者最好的鼓励。

扫雷是经典的益智游戏,传统版本多带有图形界面,而控制台版扫雷可以让我们专注于核心逻辑的实现,非常适合用来练习JavaScript的基础语法和算法思维。整个游戏运行在Node.js环境中,通过命令行交互完成操作。

如何用JavaScript构建控制台版扫雷游戏

需求分析

控制台版扫雷需要实现以下核心功能:

  • 生成指定大小的棋盘,默认是9行9列
  • 随机在棋盘中布置固定数量的地雷,默认10个
  • 玩家输入坐标进行扫雷操作
  • 点击到地雷则游戏失败,点击到非地雷区域则显示周围地雷数量
  • 如果点击到空白区域(周围地雷数为0),则递归展开所有相邻的空白区域
  • 当所有非地雷区域都被揭开时,游戏胜利

核心实现步骤

1. 初始化棋盘

首先我们需要创建两个二维数组,一个用来存储地雷的实际分布,另一个用来存储玩家看到的棋盘状态。地雷分布数组中用1表示地雷,0表示安全区域;玩家棋盘数组中用*表示未揭开的区域,数字表示周围地雷数量。

// 定义棋盘行数、列数和地雷数量
const ROWS = 9;
const COLS = 9;
const MINES = 10;

// 初始化地雷分布数组,全部填充0
const mineMap = Array.from({ length: ROWS }, () => Array(COLS).fill(0));
// 初始化玩家可见棋盘,全部填充*
const playerMap = Array.from({ length: ROWS }, () => Array(COLS).fill('*'));

2. 随机布置地雷

我们需要随机生成MINES个不同的坐标,在地雷分布数组中标记为1。为了避免重复布置,每次生成坐标后需要检查该位置是否已经有地雷。

function placeMines() {
    let placed = 0;
    while (placed < MINES) {
        // 生成0到ROWS-1的随机行索引
        const row = Math.floor(Math.random() * ROWS);
        // 生成0到COLS-1的随机列索引
        const col = Math.floor(Math.random() * COLS);
        // 如果该位置没有地雷,则放置地雷
        if (mineMap[row][col] === 0) {
            mineMap[row][col] = 1;
            placed++;
        }
    }
}

3. 计算每个区域周围的地雷数量

对于每个非地雷区域,我们需要统计它周围8个相邻位置的地雷总数,这个数量会显示给玩家。首先编写一个函数用来统计指定坐标周围的地雷数量。

function countAdjacentMines(row, col) {
    let count = 0;
    // 遍历周围8个方向
    for (let i = -1; i <= 1; i++) {
        for (let j = -1; j <= 1; j++) {
            // 跳过自身位置
            if (i === 0 && j === 0) continue;
            const newRow = row + i;
            const newCol = col + j;
            // 检查坐标是否在棋盘范围内
            if (newRow >= 0 && newRow < ROWS && newCol >= 0 && newCol < COLS) {
                // 如果相邻位置是地雷,计数加1
                if (mineMap[newRow][newCol] === 1) {
                    count++;
                }
            }
        }
    }
    return count;
}

4. 递归展开空白区域

当玩家点击的区域周围地雷数为0时,需要自动展开所有相邻的空白区域,这个逻辑需要用递归实现。递归的终止条件是:坐标超出范围、该位置已经被揭开、该位置是地雷。

function expandArea(row, col) {
    // 坐标超出范围,直接返回
    if (row < 0 || row >= ROWS || col < 0 || col >= COLS) return;
    // 该位置已经被揭开,直接返回
    if (playerMap[row][col] !== '*') return;
    // 该位置是地雷,不展开
    if (mineMap[row][col] === 1) return;

    // 计算该位置周围的地雷数量
    const mineCount = countAdjacentMines(row, col);
    // 将数量更新到玩家棋盘
    playerMap[row][col] = mineCount.toString();

    // 如果周围地雷数为0,递归展开相邻区域
    if (mineCount === 0) {
        for (let i = -1; i <= 1; i++) {
            for (let j = -1; j <= 1; j++) {
                if (i === 0 && j === 0) continue;
                expandArea(row + i, col + j);
            }
        }
    }
}

5. 游戏主逻辑与交互

最后我们需要编写游戏的主循环,负责打印棋盘、接收玩家输入、处理操作结果、判断游戏胜负。这里使用Node.js的readline模块来实现命令行输入交互。

const readline = require('readline');

// 创建readline接口
const rl = readline.createInterface({
    input: process.stdin,
    output: process.stdout
});

// 打印玩家棋盘
function printPlayerMap() {
    // 打印列号
    process.stdout.write('   ');
    for (let i = 0; i < COLS; i++) {
        process.stdout.write(` ${i} `);
    }
    process.stdout.write('n');
    // 打印每一行
    for (let i = 0; i < ROWS; i++) {
        // 打印行号
        process.stdout.write(`${i}  `);
        for (let j = 0; j < COLS; j++) {
            process.stdout.write(` ${playerMap[i][j]} `);
        }
        process.stdout.write('n');
    }
}

// 检查游戏是否胜利
function checkWin() {
    for (let i = 0; i < ROWS; i++) {
        for (let j = 0; j < COLS; j++) {
            // 如果存在未揭开的非地雷区域,游戏未胜利
            if (mineMap[i][j] === 0 && playerMap[i][j] === '*') {
                return false;
            }
        }
    }
    return true;
}

// 游戏主流程
function startGame() {
    // 布置地雷
    placeMines();
    console.log('欢迎来到控制台扫雷游戏!');
    console.log('请输入坐标,格式为:行 列,例如:1 2');
    console.log('输入q可以退出游戏');

    // 游戏循环
    function gameLoop() {
        printPlayerMap();
        rl.question('请输入你的操作:', (input) => {
            // 输入q退出游戏
            if (input.trim().toLowerCase() === 'q') {
                console.log('游戏已退出');
                rl.close();
                return;
            }

            // 解析输入的坐标
            const parts = input.trim().split(' ');
            if (parts.length !== 2) {
                console.log('输入格式错误,请按照 行 列 的格式输入');
                gameLoop();
                return;
            }

            const row = parseInt(parts[0]);
            const col = parseInt(parts[1]);

            // 检查坐标是否合法
            if (isNaN(row) || isNaN(col) || row < 0 || row >= ROWS || col < 0 || col >= COLS) {
                console.log('坐标不合法,请输入0到8之间的数字');
                gameLoop();
                return;
            }

            // 检查该位置是否已经被揭开
            if (playerMap[row][col] !== '*') {
                console.log('该位置已经被揭开,请选择其他位置');
                gameLoop();
                return;
            }

            // 点击到地雷,游戏失败
            if (mineMap[row][col] === 1) {
                console.log('你踩到地雷了!游戏失败');
                // 打印所有地雷的位置
                for (let i = 0; i < ROWS; i++) {
                    for (let j = 0; j < COLS; j++) {
                        if (mineMap[i][j] === 1) {
                            playerMap[i][j] = 'X';
                        }
                    }
                }
                printPlayerMap();
                rl.close();
                return;
            }

            // 展开区域
            expandArea(row, col);

            // 检查是否胜利
            if (checkWin()) {
                console.log('恭喜你,扫雷成功!游戏胜利');
                printPlayerMap();
                rl.close();
                return;
            }

            // 继续游戏循环
            gameLoop();
        });
    }

    gameLoop();
}

// 启动游戏
startGame();

运行与测试

将上述代码保存为minesweeper.js文件,确保本地已经安装Node.js环境,在命令行中执行node minesweeper.js即可启动游戏。按照提示输入行和列的坐标,比如输入0 0就是点击左上角的第一个格子,输入q可以随时退出游戏。

你可以根据自己的需求修改ROWS、COLS和MINES常量来调整棋盘大小和地雷数量,比如改成16行16列40个地雷,就可以得到中级难度的扫雷游戏。

JavaScript扫雷游戏控制台程序递归算法修改时间:2026-07-22 03:51:15

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。