游戏中的权重和概率实现

这个问题不仅在游戏配置领域, 几乎在任何后台数据需要灵活配置的地方, 都可以无缝契合使用.

最初的问题以及解决方案:

Q: 有个怪物, 死亡掉落 ABC 三个物品, 概率相同, 为 A 1/3, B 1/3, C 1/3.

A: 最初的设计, 一般为 r = 随机(0,100), 如果 r ∈ [0, 34) 则为 A, r ∈ [34, 67) 则为 B, …

策划改需求了?

Q: 增加物品 D, 概率占 1/2, 其余 ABC 比例仍相同, 为 A 1/6, B 1/6 , C 1/6.

要改代码里面的数据, 233…

策划又改需求了?!

Q: …

那么在无穷无尽的需求变动中, 如何实现一套以不变应万变的概率系统了?!?!

那就是使用配置表, 大致思路如下: A|1,B|1,C|1

意思为 A 占一份, B 占一份, C 占一份, 总份数为 1+1+1 = 3, 那么 ABC 的概率均等为 1/3.

在增加了新的 D 需求的时候, 只需要变更配置: A|1,B|1,C|1,D:3 即可完成需求, 代码无需改动.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
const randSettings = (setting) => {
let point = 0;

// 总权重
let total = 0;

// 每个配置的权重
const items = setting.split(/,/g)
.map(item => item.split(/|/g))
.reduce((accumulator, current) => {
const key = current[0];
const value = parseFloat(current[1]);

total += value;
accumulator[key] = value;

return accumulator;
}, {});

// 随机权重
const random = Math.random(0,1) * total;

// 所有的参数
const keys = Object.keys(items);

if (!keys || keys.length <= 0) return null;

// 计算那个数的权重符合
for( let idx = 0; idx < keys.length; idx++ ) {
point += items[keys[idx]];
if (point >= random) return keys[idx];
}

// 默认返回最后一个数
return keys[keys.length - 1];
}

let setting = 'A|1,B|1,C|1';
console.log(randSettings(setting));
Donate - Support to make this site better.
捐助 - 支持我让我做得更好.