如何实现相对版本的setTimeout以随机间隔扣减生命值?
问题场景
需要开发一个程序,核心逻辑是:
- 初始化
health变量为100 - 让生命值在随机间隔(如2秒、3秒、5秒)以随机数值(10、20、25点)减少,这类扣血事件称为"Injuries"
- 由于每次间隔和扣血量都要随机变化,选择用
setTimeout替代setInterval实现,但运行时生命值会快速无限减少,误以为是setTimeout不是相对延迟,实际是调用setTimeout时错误直接执行了函数。
错误原因
问题出在decreaseHealth函数内的这行代码:
setTimeout(decreaseHealth(), possibleIntervals[random]);
setTimeout的第一个参数需要传入函数引用,而不是函数执行的结果。写decreaseHealth()会立即执行该函数,同时把函数的返回值(此处为undefined)传给setTimeout,并且函数内部又会立即触发下一次调用,形成无限递归,导致生命值瞬间被扣除至负数。
修正后的代码
JavaScript 部分
var health = 100; var possibleInjuries = [20, 10, 25]; var possibleIntervals = [5000, 2000, 3000]; // 初始调用,设置第一次扣血延迟 setTimeout(decreaseHealth, getRandomInterval()); function decreaseHealth() { // 随机获取扣血量和下一次的延迟时间 const hit = possibleInjuries[Math.floor(Math.random() * possibleInjuries.length)]; const nextInterval = getRandomInterval(); health -= hit; $("#health").text(health); // 生命值大于0时才继续触发下一次扣血 if (health > 0) { setTimeout(decreaseHealth, nextInterval); } } // 封装随机获取间隔的函数,避免重复代码 function getRandomInterval() { return possibleIntervals[Math.floor(Math.random() * possibleIntervals.length)]; }
HTML 部分
<html> <head> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.1/jquery.min.js"></script> <title>Eat the lettuce</title> </head> <body> <span>Health:</span><span id="health">100</span>% </body> </html>
优化说明
- 去掉了全局的
random变量,每次调用时直接生成随机索引,避免全局变量污染 - 封装了
getRandomInterval函数,统一处理随机间隔的获取,代码更清晰 - 添加了生命值大于0的判断,当生命值耗尽时停止扣血逻辑,符合游戏常理
- 核心修正:把
setTimeout(decreaseHealth(), ...)改为setTimeout(decreaseHealth, ...),传递函数引用而非立即执行函数
内容的提问来源于stack exchange,提问作者DennisM
相关产品推荐
相关产品推荐

