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

如何在JavaScript中为英雄斗龙游戏的函数/循环添加延迟?

问题描述

我是编程新手,请多指教。我需要制作一个英雄与龙轮流对战的小游戏,需求如下:

  • 双方初始生命值均为10
  • 每轮包含3个回合,轮次结束后根据胜负减少对方生命值
  • 回合胜负通过随机数模拟掷骰子决定,每回合结果要打印到控制台
  • 当前游戏运行太快,不到1秒就结束,希望给控制台输出添加2秒延迟提升趣味性

我尝试过两种方法但都失败了:

  1. 使用setTimeout(getTurnPoints,2000),结果导致无限循环
  2. 用async/await结合Promise实现延迟的getRoundWinner函数,但控制台只打印"Nobody won"

期望效果:控制台每回合输出后暂停2秒,轮次结束后打印对应结果。以下是带中文注释的完整代码:

function startQuest() {
    console.log("The Quest got started!");
    startGame();
}
function restartQuest() {
    console.log("Restart got clicked!");
}
// 用于创建对象的类模板:
class Fighter {
    constructor (name, lifeEnergy) {
        this.name = name;
        this.lifeEnergy = lifeEnergy;
    }
    getAttack() {
        let randomNumber = Math.floor(Math.random()*5) + 2;  
        return randomNumber;
    };
};
// 利用模板创建对象:
let dragon = new Fighter("Dragon",10)
let hero = new Fighter("Hero",10)
// 判断回合胜者的函数:
function getTurnWinner(attackHero, attackDragon) {
    if (attackHero > attackDragon) {
        return -1;
    }
    else if (attackHero < attackDragon) {
        return 1;
    }
    else {
        return 0;
    }
};
// 用于存储分数的数组:
let dragonPointsRoundEnd = [];
let heroPointsRoundEnd = [];
// 为每个回合分配分数的函数:
function getTurnPoints() {
// 在此处添加延迟?? 
let turnWinner = getTurnWinner(hero.getAttack(), dragon.getAttack());
if (turnWinner === -1) {
    console.log("The Hero won");
    heroPointsRoundEnd.push(3);
    dragonPointsRoundEnd.push(0);
}
else if (turnWinner === 1) {
    console.log("The Dragon won")
    heroPointsRoundEnd.push(0);
    dragonPointsRoundEnd.push(3);
}
else {
    console.log("Nobody won")
    heroPointsRoundEnd.push(1);
    dragonPointsRoundEnd.push(1);
}
};
// 将每个回合的分数存储到上方数组的函数:
function getRoundWinner() {
    for (let i = 0; i < 3; i++) {
// 在此处添加延迟??
        getTurnPoints();
}
};
// 以下变量用于存储每轮计算后的总分:
let dragonCalculatedPoints = "";
let heroCalculatedPoints = "";
// 此函数计算分数并存储到上方变量中:
function calculateRoundPoints() {
getRoundWinner();
dragonCalculatedPoints = dragonPointsRoundEnd[0] + dragonPointsRoundEnd[1] + dragonPointsRoundEnd[2];
heroCalculatedPoints = heroPointsRoundEnd[0] + heroPointsRoundEnd[1] + heroPointsRoundEnd[2];
};
function calculateLifeRoundEnd() {
    calculateRoundPoints();
    if (dragonCalculatedPoints > heroCalculatedPoints && dragonCalculatedPoints >= 7) {
       console.log("The Dragon won the round");
       hero.lifeEnergy -= 3;
    }
    else if (dragonCalculatedPoints > heroCalculatedPoints) {
        console.log("The Dragon won the round");
        hero.lifeEnergy -= 1;
    }
    else if (heroCalculatedPoints > dragonCalculatedPoints && heroCalculatedPoints >= 7) {
        console.log("The Hero won the round")
        dragon.lifeEnergy -= 3;
    }
    else if (heroCalculatedPoints > dragonCalculatedPoints) {
        console.log("The Hero won the round")
        dragon.lifeEnergy -= 1;
    }
    else {
        console.log("Nobody won the round");
    }
};
function startGame() {
while (dragon.lifeEnergy >= 1 && hero.lifeEnergy >= 1) {
    calculateLifeRoundEnd();
    dragonPointsRoundEnd = [];
    heroPointsRoundEnd = [];
    if (dragon.lifeEnergy <= 0) {
    console.log("The Hero won the battle with " + hero.lifeEnergy + " to 0");
    break;
    }
    else if (hero.lifeEnergy <= 0) {
        console.log("The Dragon won the battle with " + dragon.lifeEnergy + " to 0");
        break;
    }
};
};
解决方案

原代码的核心问题是同步执行逻辑与异步延迟不兼容:直接用setTimeout会让异步代码脱离同步流程,错误的async/await用法导致分数未被正确收集就执行了结果计算。以下是修正后的完整代码,通过异步流程控制实现预期延迟效果:

function startQuest() {
    console.log("冒险开始!");
    startGame();
}
function restartQuest() {
    console.log("已重新开始!");
}

// 战士类模板
class Fighter {
    constructor(name, lifeEnergy) {
        this.name = name;
        this.lifeEnergy = lifeEnergy;
    }
    getAttack() {
        // 生成2-6的随机攻击值
        let randomNumber = Math.floor(Math.random() * 5) + 2;  
        return randomNumber;
    };
};

// 创建对战双方
let dragon = new Fighter("巨龙", 10)
let hero = new Fighter("英雄", 10)

// 判断单回合胜者:-1英雄胜,1巨龙胜,0平局
function getTurnWinner(attackHero, attackDragon) {
    if (attackHero > attackDragon) {
        return -1;
    } else if (attackHero < attackDragon) {
        return 1;
    } else {
        return 0;
    }
};

// 延迟工具函数:返回指定毫秒后resolve的Promise
function delay(ms) {
    return new Promise(resolve => setTimeout(resolve, ms));
}

// 执行单回合并添加延迟
async function getTurnPoints() {
    const attackHero = hero.getAttack();
    const attackDragon = dragon.getAttack();
    const turnWinner = getTurnWinner(attackHero, attackDragon);
    
    if (turnWinner === -1) {
        console.log("本回合:英雄获胜");
        await delay(2000); // 回合输出后延迟2秒
        return { hero: 3, dragon: 0 };
    } else if (turnWinner === 1) {
        console.log("本回合:巨龙获胜");
        await delay(2000);
        return { hero: 0, dragon: 3 };
    } else {
        console.log("本回合:平局");
        await delay(2000);
        return { hero: 1, dragon: 1 };
    }
};

// 执行一轮3个回合,收集并计算总分
async function getRoundWinner() {
    let heroTotal = 0;
    let dragonTotal = 0;
    for (let i = 0; i < 3; i++) {
        const points = await getTurnPoints();
        heroTotal += points.hero;
        dragonTotal += points.dragon;
    }
    return { heroTotal, dragonTotal };
};

// 计算本轮结果并更新生命值
async function calculateLifeRoundEnd() {
    const roundResult = await getRoundWinner();
    const heroTotal = roundResult.heroTotal;
    const dragonTotal = roundResult.dragonTotal;

    if (dragonTotal > heroTotal) {
        if (dragonTotal >= 7) {
            console.log("本轮:巨龙大胜!英雄生命值-3");
            hero.lifeEnergy -= 3;
        } else {
            console.log("本轮:巨龙获胜!英雄生命值-1");
            hero.lifeEnergy -= 1;
        }
    } else if (heroTotal > dragonTotal) {
        if (heroTotal >= 7) {
            console.log("本轮:英雄大胜!巨龙生命值-3");
            dragon.lifeEnergy -= 3;
        } else {
            console.log("本轮:英雄获胜!巨龙生命值-1");
            dragon.lifeEnergy -= 1;
        }
    } else {
        console.log("本轮:平局,双方生命值无变化");
    }
    console.log(`当前状态:英雄 ${hero.lifeEnergy} HP | 巨龙 ${dragon.lifeEnergy} HP\n`);
};

// 异步启动游戏循环
async function startGame() {
    console.log("=== 英雄 vs 巨龙 对战开始 ===");
    while (dragon.lifeEnergy > 0 && hero.lifeEnergy > 0) {
        await calculateLifeRoundEnd();
        
        if (dragon.lifeEnergy <= 0) {
            console.log(`=== 战斗结束!英雄以 ${hero.lifeEnergy} HP 获胜! ===`);
            break;
        } else if (hero.lifeEnergy <= 0) {
            console.log(`=== 战斗结束!巨龙以 ${dragon.lifeEnergy} HP 获胜! ===`);
            break;
        }
    }
};

关键修改说明

  1. 新增delay工具函数:封装setTimeout为Promise,用await实现可控延迟,避免回调混乱。
  2. getTurnPoints改为异步函数:执行回合逻辑后添加2秒延迟,同时返回该回合分数,替代原全局数组存储(全局数组在异步流程中易出现数据覆盖)。
  3. getRoundWinner改为异步函数:用await逐个执行回合,确保前一回合完成后再进行下一个,同时直接计算本轮总分。
  4. startGame改为异步函数:将同步while循环改为异步循环,每轮等待本轮所有回合完成后再进入下一轮,保证流程按延迟顺序执行。
  5. 修复分数计算逻辑:原代码中全局数组未被异步填充就执行计算,导致总分始终为0,现在通过异步返回的分数直接计算,避免数据错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 03:42:04