Community编程与开发github.com

洗牌陷阱检测器

捕获洗牌、随机选择和不公平的几率,并正确测试分布。当代码对数组进行洗牌、随机化测验答案或选项、选取随机子集、分配几率、生成战利品或奖励时,或者当有人说结果“感觉被操控”、“总是选同一个”或询问如何洗牌或随机化时,使用此技能。

洗牌陷阱检测器 是什么?

这是一个专注于检测和修复 JavaScript 中常见随机化错误的 AI 技能。它主要针对开发人员和 AI 代理,帮助他们识别由 `Array.sort(() => Math.random() - 0.5)` 模式导致的倾斜洗牌(分布不均匀),该模式虽然常见,但违反了排序比较器的预期一致性,从而产生有偏差的排列。该技能提供了正确的 Fisher-Yates 洗牌实现和分布测试方法,并指导如何区分伪洗牌与合法的随机噪声(如物理抖动)。此外,它还涉及验证向用户显示的几率与实际代码滚动结果的一致性,如进度条或成功概率,以确保界面承诺是可达成的。该技能支持所有 JavaScript 环境,并强调通过计算模拟而非肉眼观察来验证随机性。

兼容平台✓Claude Code~Codex CLI~Cursor
npx skills add https://github.com/Chibuchibs/free-claude-skills/tree/HEAD/skills/randomness-correctness

Installed? Explore more 编程与开发 skills: steipete/bluebubbles, steipete/eightctl, steipete/blucli · View all 6 →

在你喜欢的 AI 中提问

打开一个已预加载此 Agent Skill 的新对话。

文档

并非真正的洗牌

JavaScript 中最常见的随机化错误:

const shuffled = items.sort(() => Math.random() - 0.5);   // 错误

它看起来没问题,而且随处可见。但它并不是真正的洗牌。排序比较器期望是一致的,而这个是不一致的,因此引擎的排序会产生倾斜的排列。

在四个测验选项上测量:

位置正确答案落在此处的概率
028.3%
128.2%
224.7%
318.8%

均匀分布应该是每个位置 25%。实际上,总是猜第一个选项比随机猜测更好——注意到这一点的玩家会获得优势,而测验就默默地不公平了。

修复方法

Fisher-Yates 洗牌,写成一个辅助函数,只调用一次:

function shuffle(a) {
  const out = [...a];
  for (let i = out.length - 1; i > 0; i--) {
    const j = Math.floor(Math.random() * (i + 1));
    [out[i], out[j]] = [out[j], out[i]];
  }
  return out;
}

然后替换所有出现的地方。这个错误通常不只出现一次——一个代码库中曾在十一个地方出现过:洗牌选项、决定出现哪些问题、选择哪些项目被提供、排序菜单选项。每个地方都稍微倾斜了某些东西。

不要基于模式匹配进行全局替换。 (Math.random() - 0.5) 也会在物理学和抖动中合法地作为噪声出现:

velocity += (Math.random() - 0.5) * 0.012;   // 这个保留不动

检查每个匹配项是否实际上是排序比较器。

测试分布

不要凭肉眼判断随机性。用计数来检验:

const pos = [0,0,0,0], N = 200000;
for (let i = 0; i < N; i++) {
  const order = shuffle(['a','b','c','d'].map((t,i) => [t,i]));
  pos[order.findIndex(o => o[1] === 0)]++;
}
pos.forEach((c,i) => console.log(i, (c/N*100).toFixed(1) + '%'));

各位置之间的百分比差距超过约 3 个百分点意味着存在偏差。

为测试使用合适的生成器。 手工编写的线性同余生成器可能产生 1-2 个百分点的“误差”,看起来像真正的错误,但实际上是测试本身的问题。Math.random() 对检查分布来说足够均匀——将自定义生成器留到需要可重现种子的时候使用,并单独进行验证。

检查你展示给用户的几率

如果你在任何地方显示几率——百分比、进度条、成功概率——确保它们与代码实际滚动的结果匹配。模拟真实滚动几十万次并进行比较:

cred   0  显示 5.0%/40.0%/55.0%   实际 5.0%/40.0%/55.0%
cred 100  显示 40.0%/40.0%/20.0%  实际 40.0%/40.1%/20.0%

最差误差低于半个百分点意味着显示没有说谎。显示的概率与实际结果不符比不显示更糟糕,因为人们会据此做决策。

顺便检查一下

确认声明的目标实际可达。一个显示“3 of 5”的计数器告诉玩家目标是 5;如果 5 只发生 0.17% 的时间,那么界面就是在承诺一个实际上永远不会发生的事情。计算出你显示的每个里程碑的真实概率。

Individual skills in this repo

This repo contains 1 individual skill — each has its own dedicated page.

相关技能