CHUAN2 DEV ENGINE
996 正版授权研发中心 · 360 授权合作教学中心 · 抖音传奇直播合作授权 · 快手推广运营商授权
OFFICIAL LICENSED ACADEMY 查验官方授权证书 →
// 威海旷世互娱教学基地 · 技术文章
进阶实战996引擎洗牌算法Fisher-Yates

【进阶实战】洗牌算法Fisher-Yates:公平抽签封装

2026-09-24 22:22 作者:996 技术组 0 阅读 996引擎Lua教程传奇脚本进阶实战996引擎Lua洗牌算法Fisher-Yates

业务场景

师门每日任务池的抽签用"每条任务配随机数再排序"实现,玩家连刷三个月摸出规律:某些任务出现的概率明显偏低——排序键法在并列随机数时行为有偏,且 n 个元素的全排列并不能被均匀覆盖。公平抽签改用 Fisher-Yates 洗牌:从尾向前逐位与随机位置交换,每种排列严格等概率,5 个任务的 120 种排列严格等概率。

核心实现

Fisher-Yates 洗牌与部分抽取:整池洗牌、取前 k 个即为等概率抽 k 个。示例代码如下:

lua
local function shuffle(t)
    for i = #t, 2, -1 do
        local j = math.random(i)
        t[i], t[j] = t[j], t[i]
    end
    return t
end
local function drawDailies(actor)
    actor = getplayerbyname(actor)
    local pool = {}
    for i = 1, 20 do
        pool[i] = "师门任务" .. i
    end
    shuffle(pool)
    local picks = {}
    for i = 1, 5 do
        picks[i] = pool[i]
    end
    setplayvar(actor, "HUMAN", "DailyTasks", table.concat(picks, "|"), 1)
    sendmsg(actor, 1, "今日师门任务已抽取 5 项。")
    return picks
end

洗牌不动原池的副本版示例代码如下:

lua
local function shuffleCopy(t)
    local copy = {}
    for i, v in ipairs(t) do
        copy[i] = v
    end
    return shuffle(copy)
end

接口拆解

math.random(i) 返回 1 到 i 的含边界整数,与循环变量 i 逐位配对是 Fisher-Yates 等概率的关键——随机范围写成 i-1 或 0 到 i 都会破坏均匀性。setplayvar(actor, "HUMAN", "DailyTasks", 串, 1) 把当日抽签结果落库,重启后任务不重抽。洗牌就地修改原表,需要保留原池时先浅拷贝再洗。

踩坑记录

洗牌抽签踩过三个坑:一是把 math.random(i) 误写成 math.random(0, i),0 号位是 Lua 表不存在的下标,抽到即把 nil 换进池子,后续拼接报错——含边界规则要背牢;二是抽奖接口被高频调用时共用同一批随机序列,两个玩家同一毫秒抽签拿到相同排列,引擎随机源按调用次序推进,高频入口在抽签前混入玩家名哈希做一次额外随机扰动;三是"取前 5 个"被写成"洗完再截断存储",池子本身 20 项的顺序也被覆盖,同池的其他玩法(全池展示)顺序天天变,展示层改用洗牌副本、抽签层用原池截断,两条线互不污染。

作者履历与出处

本文由 996 技术组基于 996 引擎官方知识库与浮生梦老师课程体系整理。团队长期从事传奇类引擎 Lua 后端逻辑、客户端界面与商业版本交付,内容以官方知识库与真实项目为出处,按版本持续修订。

← 返回文章地图返回研学路径

最新技术文章 · 实战干货

LATEST ARTICLES

全站技术干货持续更新:996 引擎 / Lua 实战帖,语法、参数与示例一篇讲透。进入文章地图 · 查看全部 →

策划架构996引擎

【策划架构】帮会试炼场:限时挑战的门票与积分设计

设计初衷 帮会活动只有攻城与聚餐两板斧:非攻城日帮会频道冷清,成员缺乏共同目标。帮会试炼场设计:帮会自有试炼场(限时挑战波次…

2026-09-26 03:53 996 技术组 · 0 阅读
策划架构996引擎

【策划架构】帮会会费:成员会费的收缴与公示设计

设计初衷 帮会资金靠少数大佬捐献:金主一走帮会资金断崖,普通成员没有参与感也不会珍惜帮会资源。帮会会费设计:成员按职位每周缴…

2026-09-26 03:53 996 技术组 · 0 阅读
策划架构996引擎

【策划架构】募兵编制:帮会扩军的募兵与编制作业设计

设计初衷 帮会扩张靠熟人拉人:增长有天花板、新人质量参差、老人不愿带新。募兵编制设计:帮会发布募兵任务包(新人完成入帮任务即…

2026-09-26 03:53 996 技术组 · 0 阅读
高级技巧996引擎

【高级技巧】协程超时兜底:resume与pcall的组合封装

底层原理 协程体内出错时 resume 返回 ok=false 与错误对象,但协程体若死循环则 resume 永久挂起——错…

2026-09-26 03:53 996 技术组 · 0 阅读
高级技巧996引擎

【高级技巧】协程双向通信:resume传参与yield回传封装

底层原理 coroutine.resume 的实参会在协程内成为首个 yield 的返回值;coroutine.yield …

2026-09-26 03:53 996 技术组 · 0 阅读
进阶实战996引擎

【进阶实战】摆摊自动补货:摊位库存的定时补齐封装

业务场景 挂摊卖药每小时断货:玩家下线前上满货,两小时后摊位空转。摊位自动补货封装:上摊时设定补货仓库(背包或帮会仓),定时…

2026-09-26 03:53 996 技术组 · 0 阅读