游戏中的中奖随机算法

410 阅读2分钟

最近在写一个游戏中中奖的随机概率算法,暂时的要求有如下:

  1. 若干个奖项之中,需要选择其中的4个
  2. 每个奖项的概率都需要随时可以调整
  3. 调整概率的时候,不要太麻烦,可以相对来调整,比如想调整奖项1和奖项2是1:2的关系

想了想,就写了下算法,记录下,别忘记了

因为是写游戏,所以逻辑是用lua写的,说实话,lua真的是太难嚼了,身为脚本语言,却没有脚本语言的各种语法糖,硬生生的用底层语言的方式来作出了脚本语言的特性,而且对go to Definition一点都不友好

-- key是商品名称, value是概率
-- 比例不需要加起来等于1,根据需要随意调整
local probs = {
    ["总额*2"] = 0.9,
    ["总额*5"] = 0.7,
    ["总额*10"] = 0.1,
    ["总额*20"] = 0.03,
    ["总额*50"] = 0.005,
    ["次数*5"] = 0.8,
    ["次数*10"] = 0.7,
    ["次数*15"] = 0.1,
    ["次数*20"] = 0.03,
}

function Choose(probs)
    local total = 0;
    for _, value in pairs(probs) do
        total = total + value
    end

    --- 根据总和生成一个随机值,然后根据区间段来定位,区间段短的,分到的几率就低
    local randnum = math.random() * total

    for key, value in pairs(probs) do
        if randnum <= value then
            return key
        else
            randnum = randnum - value
        end
    end
end

-- table 拷贝,用到lue wiki(http://lua-users.org/wiki/)上的片段
function shallowcopy(orig)
    local orig_type = type(orig)
    local copy
    if orig_type == 'table' then
        copy = {}
        for orig_key, orig_value in pairs(orig) do
            copy[orig_key] = orig_value
        end
    else -- number, string, boolean, etc
        copy = orig
    end
    return copy
end

-- 需要4个值,所以就打印4次,因为不能重复,所以每次取值就去掉已选的值
local probs_cp = shallowcopy(probs)
for i = 1, 4, 1 do
    value = Choose(probs_cp)
    probs_cp[value] = nil
    print(value)
end

用上面这个算法,从宏观来说,概率确实的按照要求来的,当然实际过程中,random的随机种子不要每次都一样

打印结果如下

次数*5
总额*2
总额*5
次数*10