js实现一个按照权重抽奖函数

5,974 阅读1分钟

使用方式

1 先配置奖品数据,比如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]
    }
}

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

附上github源码地址github.com/ColdDay/lot….