两种js抽奖概率算法附代码下载

来源:程序思维浏览:2509次
最近在做一个抽奖概率的功能,下面给大家分享一下:

第一种:

假设有一个数组[100,400,200,300],它的意思是,总数是100+400+200+300=1000. 取到第一个数的概率是100/1000,取到第二个数的概率是400/1000......代码如下:

复制代码
            function getResult(arr){
                var leng = 0;
                for(var i=0; i<arr.length; i++){
                    leng+=arr[i]                                     //获取总数
                }
                for(var i=0; i<arr.length; i++){
                    var random = parseInt(Math.random()*leng);       //获取 0-总数 之间的一个随随机整数
                    if(random<arr[i]){
                        return i                                     //如果在当前的概率范围内,得到的就是当前概率
                    }
                    else {
                        leng-=arr[i]                                 //否则减去当前的概率范围,进入下一轮循环
                    }
                }
            }   

下面来解释一下这个算法,把数组抽象出来,假设为a,b,c,d,这四个概率数,那么,他们的总和就是 a+b+c+d. 画成数轴:



从0-(a+b+c+d) 中取一个随机数,数字落在对应的空间里,取到的就是对应的概率.

第一次循环取数,有两个可能:

<a    或者    >a:

如果是第一种可能,那就直接是概率a/(a+b+c+d),得到的对应结果就是a.直接返回.

如果是第二种可能,那么概率应该是(b+c+d)/(a+b+c+d).然后进入第二次循环,第二次取数我们把a的概率空间减去,得到新的数轴:



新的数轴以原来的a为原点0,后面不变.这时候,总和变成 b+c+d.

从 0-(b+c+d) 中取一个随机数,数字落在对应的空间里,取到的就是对应的概率.

同样有两个可能:

<b    或者     >b

如果是第一种,那么它的概率就是 b/(b+c+d). 注意,这个概率出现的前提是第一次的结果是 >a ,所以总概率就是两次乘积: (b+c+d)/(a+b+c+d) * b/(b+c+d) 得到的结果是 b/(a+b+c+d),得到的对应结果就是b.返回.

如果是第二种,那么它的概率就是 (c+d)/(b+c+d). 同样,和 >a 的结果同时出现,这种情况的总概率应该是: (b+c+d)/(a+b+c+d) * (c+d)/(b+c+d) 得到的结果是(c+d)/(a+b+c+d).然后进入第三次循环,然后第三次循环时,我们再把b的概率空间减去............以此类推.............

这样直到最后...总能取到一个概率值...


这个算法可以用在抽奖上,比如有这样一组奖品和对应的概率:


       var gifts = [
                {
                    "name":"mac",
                    "prop":1
                },
                {
                    "name":"红米",
                    "prop":10
                },
                {
                    "name":"u盘",
                    "prop":40
                },
                {
                    "name":"香皂",
                    "prop":49
                }
            ];

就可以用前面的函数来进行抽奖:

            var gArr = [];
            for(var i=0; i<gifts.length; i++){
                gArr.push(gifts[i]['prop'])
            }
            console.log(gifts[getResult(gArr)]['name'])    

第二种:

先配置奖品数据,比如4个奖品类型,一等奖概率1%,二等奖概率3%,三等奖概率6%,参与奖90%,设置如下

       
var model = [{
    name: '一等奖',
    key: 'level1',
    radio: 1,
},{
    name: '二等奖',
    key: 'level2',
    radio: 3,
},{
    name: '三等奖',
    key: 'level3',
    radio: 6,
},{
    name: '参与',
    key: 'level4',
    radio: 90
}]
复制代码
配置好奖品后就可以初始化抽奖函数,执行抽奖

var draw = new Draw(model);

var drawResult = draw.getResult();

实现原理
  • 拿到奖品数组,重新遍历,生成按照权重分解后的数组,如上面的例子,生成的新数组长度为100,一等奖数组中有一个,二等奖3个,以此类推
  • 这样每个奖品在数组中的占比就跟权重保持一致了
  • 按照权重分解是第一步,还需要将数组顺序打乱,这样更加随机性
  • 生成完数组后,调用抽奖只是简单的从中随机取出一个,而这个就是中奖结果

核心代码如下:

function Draw(prizes) {
    var prizeList = [] //按照权重分解后的奖品数组
    prizes.map(function(item){
        prizeList.push({
            name: item.name,
            value: item.key
        })
        for(var i=0; i< item.radio; i++) {
            prizeList.push({
                name: item.name,
                value: item.key
            })
        }
    });
    prizeList = reset(prizeList);
    // 范围随机数
    function randomFrom(lowerValue, upperValue) {
        return Math.floor(Math.random() * (upperValue - lowerValue + 1) + lowerValue);
    };
    // 随机打乱数组
    function reset(arr) {
        var eachArr = arr.concat([])
        var lastArr = []
        function deepEach(deepArr) {
            if (deepArr.length) {
                var randomIndex = randomFrom(0, eachArr.length - 1)
                lastArr.push(eachArr[randomIndex])
                eachArr.splice(randomIndex, 1)
                deepEach(eachArr)
            }
        }
        deepEach(eachArr)
        return lastArr
    }
    this.getResult = function() {
        var random = randomFrom(0, prizeList.length - 1);
        return prizeList[random]
    }
}

声明:一般抽奖不会放到前台去做,但是它不仅仅可以用来抽奖,还可以用在游戏或者其它安全性要求较低的场合。

抽奖概率算法代码下载
精品好课
React实战视频教程仿京东移动端电商
React是前端最火的框架之一,就业薪资很高,本课程教您如何快速学会React并应用到实战,对正在工作当中或打算学习React高薪就业的你来说,那么这门课程便是你手中的葵花宝典。
HTML5视频播放器video开发教程
适用人群1、有html基础2、有css基础3、有javascript基础课程概述手把手教你如何开发属于自己的HTML5视频播放器,利用mp4转成m3u8格式的视频,并在移动端和PC端进行播放支持m3u8直播格式,兼容...
Vue2+Vue3+ES6+TS+Uni-app开发微信小程序从入门到实战视频教程
2021年最新Vue2+Vue3+ES6+TypeScript和uni-app开发微信小程序从入门到实战视频教程,本课程教你如何快速学会VUE和uni-app并应用到实战,教你如何解决内存泄漏,常用UI库的使用,自己...
VUE2+VUE3视频教程从入门到精通(全网最全的Vue课程)
VUE是目前最火的前端框架之一,就业薪资很高,本课程教您如何快速学会VUE+ES6并应用到实战,教你如何解决内存泄漏,常用UI库的使用,自己封装组件,正式上线白屏问题,性能优化等。对正在工作当中或打算学习VUE高薪就...
HTML5基础入门视频教程易学必会
HTML5基础入门视频教程,教学思路清晰,简单易学必会。适合人群:创业者,只要会打字,对互联网编程感兴趣都可以学。课程概述:该课程主要讲解HTML(学习HTML5的必备基础语言)、CSS3、Javascript(学习...
jQuery视频教程从入门到精通
jquery视频教程从入门到精通,课程主要包含:jquery选择器、jquery事件、jquery文档操作、动画、Ajax、jquery插件的制作、jquery下拉无限加载插件的制作等等......
最新完整React+VUE视频教程从入门到精,企业级实战项目
React和VUE是目前最火的前端框架,就业薪资很高,本课程教您如何快速学会React和VUE并应用到实战,教你如何解决内存泄漏,常用库的使用,自己封装组件,正式上线白屏问题,性能优化等。对正在工作当中或打算学习Re...
最新完整React视频教程从入门到精通纯干货纯实战
React是目前最火的前端框架,就业薪资很高,本课程教您如何快速学会React并应用到实战,教你如何解决内存泄漏,常用UI库的使用,自己封装组件,正式上线白屏问题,性能优化等。对正在工作当中或打算学习React高薪就...
收藏
扫一扫关注我们