JS 实现一个简单的权重抽奖算法

发布于 2024-02-09 13:31:56 字数 2607 浏览 25 评论 0

平时工作中,小程序业务经常遇到抽奖场景,一般这类抽奖不会在前端做,而是由后端同学来写抽奖逻辑外加各种资格校验。虽说是后端的活,但前端也可以自己实现一个简易的抽奖算法。

抽奖的实现过程

抽奖算法有简单的,有复杂的各种实现,本文介绍的是 根据权重生成区间,然后 random 随机数 来获取抽中的奖品。具体过程如下:

  1. 首先根据奖品配置的权重,计算出权重区间,保存在数组里
  2. 接着执行 Math.random() 获取 minmax 范围的随机数
  3. 判断 2 中的随机数落在哪个权重区间,拿到区间索引 index
  4. 根据索引 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据

关于作者

文章
评论
28 人气
更多

推荐作者

櫻之舞

文章 0 评论 0

弥枳

文章 0 评论 0

m2429

文章 0 评论 0

野却迷人

文章 0 评论 0

我怀念的。

文章 0 评论 0

    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文