基于Math.random()的爆炸骰函数在嵌套调用时异常,返回理论上不可能的最大值
基于Math.random()的爆炸骰函数在嵌套调用时异常,返回理论上不可能的最大值
嘿,我一眼就瞅到问题根儿在哪了——类型不匹配搞的鬼!
咱们拆解着看:
- 你在
multiDiceRoll里用diceString.split("d")处理骰子字符串,比如输入"1d8",拆分后得到的diceType是字符串"8",不是数字类型的8。 - 然后你把这个字符串
"8"直接传给了explosiveDiceRoll当maxRoll参数。 - 但你的
diceRoll函数返回的是数字类型的结果(比如8),在explosiveDiceRoll的循环判断roll === maxRoll里,数字8和字符串"8"用严格相等===比较会返回false——循环压根不会触发重滚逻辑!直接就把初始的8返回了,这就是为啥不该出现的8会冒出来。
至于你单独测试explosiveDiceRoll时没问题,是因为你直接传的是数字(比如8),类型一致,严格相等判断能正常工作。
解决方案
只需要把multiDiceRoll里的diceAmount和diceType转换成数字就行,用parseInt或者Number都可以:
function multiDiceRoll(diceString,advantage) { diceString = diceString.split("d"); let diceAmount = parseInt(diceString[0], 10); // 转为数字 let diceType = parseInt(diceString[1], 10); // 转为数字 console.log(`${diceAmount}d${diceType}`); let results = []; for(let i = 0; i <= Math.min(2,Math.abs(advantage)); i++) { let result = 0; for(let d = 1; d <= diceAmount; d++) { let roll = explosiveDiceRoll(diceType); console.log(`${roll},${diceType} - SHOULD NOT EQUAL`); result += roll; } results.push(result); } console.log(results); if(advantage >= 0) return Math.max(...results); else return Math.min(...results); }
另外,建议给explosiveDiceRoll也加个参数类型转换的保险,防止以后再不小心传字符串进去:
function explosiveDiceRoll(maxRoll) { maxRoll = parseInt(maxRoll, 10); // 确保是数字类型 let roll = diceRoll(maxRoll); let sum = roll; while(roll === maxRoll) { roll = diceRoll(maxRoll); if(roll === 0) console.log("zero error"); sum += roll } return sum; }
改完之后,严格相等判断就能正常触发重滚逻辑,再也不会出现返回最大值的情况了。你再用之前的while循环测试,应该能和单独测试explosiveDiceRoll一样一直运行下去。
备注:内容来源于stack exchange,提问作者KaiMcKiernan
相关产品推荐
相关产品推荐

