九宫格抽奖概率问题!!

公司项目需要九宫格抽奖,大奖为1%,谢谢惠顾99%!大牛看一下下面这个中奖概率设置有啥漏洞没有,实际测了一下,抽了好多次才抽到话费50元图片描述

阅读 12.6k
7 个回答

这种逻辑应该后台写,并且在提交中奖结果时要进行验证,否则前端太容易篡改数据了。

  1. 点击抽奖时,请求后台

  2. 后台返回抽奖结果

  3. 前端播放抽奖动画,并且保证最后停在返回的中奖结果项上

--- 更新 ---
大致给你个权重算法

// 权重越小越难中奖
// 这里iphone中奖概率为 1/2001 大致为 0.000499
const prizeList = [
    { name: 'iphone', weight: 1 }, 
    { name: 'book', weight: 1000 },
    { name: 'sorry', weight: 1000 }
]

function config (prizeList) {
    let index = 0
    prizeList.forEach(prize => {
        prize.min = index
        prize.max = index + prize.weight
        index += prize.weight
    })
    
    return function () {
        let num = random(0, index - 1)
        return prizeList.filter(prize => prize.max > num && prize.min <= num)[0]
    }
}

// test
function test (total, prizeName) {
    const lottery = config(prizeList)
    let n = 0
    for (let i = 0; i < total; i++) {
        if (lottery().name === prizeName) {
            n++
        }
    }
    console.log(prizeName, n / total)
}

test(100000, 'iphone') // iphone 0.00047
test(100000, 'book') // book 0.50047

外籍杰克兄说得对,首先这种逻辑别放在前端。

然后,只说实现的逻辑,提供一种思路,随机数落在0-1中间的任何一个数概率是相同的,那么,落在0~0.5之间的概率就是50%,落在0.5~0.6之间的概率就是10%。
确认好每个奖的中奖率,比如大奖是1%,二等奖是10%,三等奖是89%,那就判断随机数生成后落在哪个范围里。0~0.01之间就是大奖,0.01~0.11之间就是二等奖,大于0.11就是三等奖。

确定好中了几等奖以后,剩下的是前端要做的事情,顺时针或者逆时针挨个高亮,每循环完一遍时间间隔变长一点,看上去就是转速变慢了,然后转个三圈以后,只要高亮到那个奖项停止动画。

这个应该是我能想到的最直接了当的解决思路了。

随机数不就搞定了,比如获取1~100之间的随机数,抽到1的是大奖,完了随便根据情况再随机(毕竟奖品有便宜有贵的不是),其他2-100是谢谢惠顾。

PS:真是烦这种抽奖,都特么这个套路。

一句话,前段只负责显示,后端说中了,前段就显示中奖,后端不想理,一辈子都是瞎逼抽

楼主你的思路是正确的,但是代码有 BUG,你的 getRand 用的是 mt_rand 生成 1-sum 的随机整数,也就是,对应你设置的数组权重 v 的值,就会明白为什么得到的 1% 是(话费50元),剩下就是(谢谢惠顾)。
说重点:根据你的随机算法思路,权重 v 里面的值必须是整数。
把你的数组权重 v 改成以下的值,应该就可以有正确的结果。

$prize_arr = array(
        0 => array('v' => 10), //概率 10/10000
        1 => array('v' => 10), //概率 10/10000
        2 => array('v' => 20), //概率 20/10000
        3 => array('v' => 50), //概率 50/10000
        4 => array('v' => 100), //概率 100/10000
        5 => array('v' => 10), //概率 10/10000
        6 => array('v' => 9800), //概率 9800/10000
    );

之前我也是用这个方法,后面发现这个算法中奖概率太高了,相当于把每个奖品都放一个箱子,从上到下,每个奖品都单独抽到中奖为止,大大提高了中奖机率。
我改用只取一次的办法,把所有的奖品和干扰球都放到数组里面,在数组里面随机取一个,是奖品球再查看是否有剩余奖品,无则,返回谢谢惠顾。
一般来说,谢谢惠顾这个奖项必有,除非你其它奖品设置的概率高,数量无限制,不然,谢谢惠顾概率肯定最高最高,这个奖项可以不考虑概率,只用它的奖项名称,返回“谢谢,继续加油哦”。
链接描述

前端只呈现页面效果就好,逻辑判断一定是在后台处理的,淘宝倒计时有时候都能被更改,别说这么贵的抽奖了。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题