JS 实现一个简单的权重抽奖算法
平时工作中,小程序业务经常遇到抽奖场景,一般这类抽奖不会在前端做,而是由后端同学来写抽奖逻辑外加各种资格校验。虽说是后端的活,但前端也可以自己实现一个简易的抽奖算法。
抽奖的实现过程
抽奖算法有简单的,有复杂的各种实现,本文介绍的是 根据权重生成区间,然后 random 随机数
来获取抽中的奖品。具体过程如下:
- 首先根据奖品配置的权重,计算出权重区间,保存在数组里
- 接着执行
Math.random()
获取min
到max
范围的随机数 - 判断 2 中的随机数落在哪个权重区间,拿到区间索引
index
- 根据索引
index
去奖品配置里拿到对应中奖奖品
代码实现
约定奖品的配置是如下格式:
const prizes = [
{
name: "抽奖券",
weight: 50,
},
{
name: "大奖",
weight: 70,
},
{
name: "二奖",
weight: 80,
}
]
接下来实现抽奖函数 draw
,代码如下:
function draw(prizes) {
// 根据每个奖品的权重,生成区间 [[0, 50], [50, 100], ...]
const intervals = prizes.reduce((acc, curr, idx) => {
const weight = curr.weight
const [preStart, preEnd] = acc[acc.length-1] || [0, 0]
acc.push([preEnd, preEnd + weight])
return acc
}, [])
// 找到区间的最小和最大值
const [min, max] = intervals.reduce((acc, curr) => {
if (curr && curr.length) {
acc[0] = Math.min(acc[0], curr[0])
acc[1] = Math.max(acc[1], curr[1])
}
return acc
}, [Number.MAX_SAFE_INTEGER, Number.MIN_SAFE_INTEGER])
// 随机一个数
const luckyNumber = random(min, max)
// 看落在哪个区间
const luckPrizeIndex = intervals.findIndex(item => item[0] <= luckyNumber && item[1] > luckyNumber)
if (luckPrizeIndex === -1) {
// 当做未中奖来处理
}
// 找到中奖奖品
const luckyPirze = prizes[luckPrizeIndex]
return luckyPirze
}
function random(min, max) {
return Math.floor(Math.random() * (max - min + 1) + min)
}
测试
以这份数据为例:
const prizes = [
{
name: "抽奖券",
weight: 50,
},
{
name: "大奖",
weight: 70,
},
{
name: "二奖",
weight: 80,
}
]
编写测试函数:
function testDraw() {
const countMap = {}
for (let i = 0; i < 10000; i++) {
const prize = draw(prizes)
if (prize) {
countMap[prize.name] = (countMap[prize.name] || 0) + 1
}
}
return countMap
}
执行 10000 次抽奖,得到如下结果:
核算下来,二奖的中奖率约为 35%
,大奖的中奖率约为 39%
,抽奖券的中奖率约为 24%
。与我们奖品配置的权重相比,略高一点点。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论