使用方法
- 这个宾果卡号生成器先让你定「卡片数量」:默认 20 张,可填 1~50 的整数。一场小型活动 20 张够用,班级或门店场景可以直接填 50。
- 「随机种子」默认 20261001,这是示例里那批卡的来源。想换一批就改成别的数字;填 0 表示每次打开都用真随机值,实际用到的种子会显示在结果摘要里,抄下来就能复现同一批卡。
- 「把 N 列正中一格设为 FREE 自由空格」默认勾选。这是标准 75 球卡的印法:中间格开局即算已标记。取消勾选后 N 列会补满 5 个号码,每张卡从 24 个号码变成 25 个。
- 点「生成卡片」(或在任意输入框里按 Enter),上面会铺开 5×5 卡面网格,下面是同内容的号码对照表。
- 对照表默认显示 12 行,点「加载更多」展开全部;「导出 CSV」把整批卡存成表格文件,「复制对照表」按 TSV 复制到剪贴板,方便直接分发给主持人。
- 换回演示数据点「载入示例」,卡片数量、种子与 FREE 开关会一起恢复到 20 / 20261001 / 勾选状态。
这个宾果卡号生成器能解决什么问题
一是批量印卡。线下宾果活动通常要几十张互不相同的卡,手写既慢又容易重复。这里一次生成 50 张,号码全部落在规定号段内、列内不重复,直接打印或抄录即可。
二是避免两张卡撞号。两张卡的号码越接近,越容易出现同时中奖或明显不公平的观感。本工具按标准列区间抽样,一张卡(含 FREE)的可能组合数是 30034 × 1365 = 111,007,923,832,370,565 种,生成 20 张出现两张完全相同的概率只有 1.71×10−15。
三是可复现。策划案里写清「种子 20261001、20 张、带 FREE」,任何人任何时候重新打开本页填同样的参数,拿到的就是同一批卡。活动复盘、A/B 两场用同一批卡对照、或者印坏了要补第 13 张,都不用重新排。
四是给孩子做认数字练习。把卡片数量设成 1、取消 FREE,就是一张标准 5×5 数字方格;N 列 31–45、O 列 61–75 的区间划分本身就是十进制分段练习。本工具不做抽号器、不做中奖判定、不生成叫号动画,也不按「一行五连」的行列对角线分布去优化卡面。
生成原理:75 球列区间、部分 Fisher–Yates 与可复现种子
列区间为什么是这五段。宾果卡号生成器遵循的美式宾果用 1~75 共 75 个球,卡面是 5 列 × 5 行。75 正好被 5 整除,每列分到 15 个号码:B 列 1~15、I 列 16~30、N 列 31~45、G 列 46~60、O 列 61~75。这个分段不是约定俗成的习惯,而是「75 个球平均分给 5 个字母」的唯一整数解——每列宽度固定 15,5×15 = 75,没有任何余数需要处理。所以看到一张卡上 B 列出现 16、或者 O 列出现 60,就可以直接判定这张卡不符合 75 球规则。
抽样算法是部分 Fisher–Yates。第 i 张卡的第 k 列,做法是:先按升序把该列的 15 个号码装进数组,然后让下标 i 从 0 走到 k−1,每一步在区间 [i, 14] 里等概率取一个下标 j,把 a[i] 与 a[j] 交换;循环结束取数组前 k 个元素。Fisher–Yates 的正确性来自「n 个元素的全排列有 n! 种,而每一步是在剩余元素里等概率选一个」,n 步之后每个排列等概率出现;只走 k 步就是一次无放回均匀抽样,C(15,k) 组结果等概率。要 5 个号码时它只调用 5 次随机数,而把整列洗一遍需要 15−1 = 14 次——省下的 9 次既省时间,也缩小了随机源被不当映射的面。
取模偏差用拒绝采样消掉。每次取到的随机数是 32 位无符号整数,范围 0~4294967295。若直接写 v % 15,因为 232 = 4294967296 不能被 15 整除,余数 0 会比余数 1 多出现一次,对应号码 1 被抽中的概率略高于号码 2,分布出现肉眼看不见的偏斜。本工具先算接受上限 Math.floor(4294967296 ÷ 15) × 15 = 4294967280,随机数落在 4294967280~4294967295 这 16 个取值上就丢弃重抽,接受率是 4294967280 ÷ 4294967296 = 99.99999998%,拒绝比例 2.328×10−8%,代价可以忽略。
列内不做升序排列。洗牌后的顺序原样自上而下填进列里。真实印刷的宾果卡列内本来就是乱序,如果为了「好看」把每列排成升序,等于抹掉了一层随机性,而且同一颗种子在不同实现间会对不上号。示例卡 1 的 B 列自上而下是 15、12、2、5、11,就是这个原因。
种子用 mulberry32。它是一个 32 位状态的伪随机数发生器:每次先把状态加上常数 0x6D2B79F5,再用 Math.imul 做两轮异或移位混合得到输出。第 i 张卡的种子是「基础种子 + (i−1)」,所以第 1 张卡永远只由基础种子决定——你把卡片数量从 20 改成 5,前 5 张卡的内容不会变,这是补印单张时很实用的一条性质。种子填 0 时,基础种子改由 crypto.getRandomValues 取一个 32 位整数,摘要里会把实际值报出来。
要声明一句:mulberry32 不是密码学安全的随机源。它的内部状态是 32 位,观察到连续输出后可以被反推出后续结果,因此别拿它生成口令、密钥或任何有奖凭据。宾果卡只需要「同一张卡别重复、不同卡看着不一样」,这类用途对密码学强度没有要求。
完整示例(种子 20261001,20 张卡)
示例条件与页面默认值一致:20 张卡、随机种子 20261001、勾选 FREE 自由空格。第 1 张卡(种子 20261001)的实测结果:
- B 列:15、12、2、5、11(都在 1~15 内,五个各不相同);
- I 列:21、18、28、16、20(都在 16~30 内);
- N 列:34、38、39、40,中间第 3 行是 FREE,所以只抽 4 个号码;
- G 列:55、58、60、57、51(都在 46~60 内);
- O 列:73、72、69、74、65(都在 61~75 内)。
这张卡一共 24 个号码,号码之和实测为 933(240 个号码位的理论期望是 912,单张波动属于正常),最小号码 2、最大号码 74,24 个号码互不相同。整批 20 张卡合起来覆盖了 75 个号码中的全部 75 个,每一列的 15 个号码也都被覆盖到;列内重复 0 处,越界号码 0 个。
把种子换成 20261002,其余参数不动,第 1 张卡会整张换掉;而把卡片数量从 20 改成 5、种子仍是 20261001,前 5 张卡与上面完全一致。
列区间、抽样个数与组合数对照表
下表把五列的规则、单列组合数与整卡组合数列全。「单列组合数」就是 C(15,k),也就是这一列可能出现的号码组数。
| 列 | 号码区间 | 区间宽度 | 带 FREE 时抽几个 | 不带 FREE 时抽几个 | 单列组合数 C(15,k) |
|---|---|---|---|---|---|
| B | 1–15 | 15 | 5 | 5 | 3003 |
| I | 16–30 | 15 | 5 | 5 | 3003 |
| N | 31–45 | 15 | 4 | 5 | 1365 / 3003 |
| G | 46–60 | 15 | 5 | 5 | 3003 |
| O | 61–75 | 15 | 5 | 5 | 3003 |
五列相互独立相乘,就得到整张卡的可能组合数:
| 卡型 | 每张号码数 | 整卡组合数 | 科学计数 |
|---|---|---|---|
| 带 FREE 中间格 | 24 | 30034 × 1365 = 111,007,923,832,370,565 | 约 1.11×1017 |
| 不带 FREE,N 列补满 | 25 | 30035 = 244,217,432,431,215,243 | 约 2.44×1017 |
有了总数就能算撞卡概率。同一批里两两配对的数量是 C(n,2),出现任意一对完全相同的概率就是配对数除以整卡组合数:
| 一次生成 | 两两配对数 C(n,2) | 出现两张完全相同的概率 | 实际含义 |
|---|---|---|---|
| 5 张 | 10 | 约 9.0×10−17 | 可以认为不会发生 |
| 12 张 | 66 | 约 5.95×10−16 | 可以认为不会发生 |
| 20 张 | 190 | 约 1.71×10−15 | 可以认为不会发生 |
| 50 张 | 1225 | 约 1.10×10−14 | 即使生成上限也远低于任何现实阈值 |
另一组常用数字是分布统计:每个指定号码出现在它所属列某张卡上的概率是 5 ÷ 15 = 33.33%;一张带 FREE 的卡覆盖 24 ÷ 75 = 32.0% 的球;各列号码之和的期望分别是 B 40、I 115、N 152、G 265、O 340,整卡合计 912(N 列不带 FREE 时为 190,整卡合计 950)。
输入范围、边界与校验说明
- 卡片数量 1~50 的整数。这个宾果卡号生成器一次铺开 50 × 25 = 1250 个格子,再多会让页面滚动变得笨重;一场活动发 50 张互不相同的卡已足够。填 0、负数、小数或空值都会被拒绝并指出具体字段。
- 随机种子 0~999999999 的整数。上限 999999999 小于 232 = 4294967296,完全落在 mulberry32 的 32 位状态范围内,不会碰到 JavaScript 双精度在 253 之后丢有效位的问题。填 0 表示每次自动,实际值会在摘要里回显,方便复现。
- 勾选 FREE 时每张卡 24 个号码,取消后 25 个。N 列的号码之和期望会从 152 变成 190,整卡期望和从 912 变成 950。两者都不是错误值,只是卡型不同。
- 一张卡里的号码天然互不相同。五个列的区间互不重叠(1–15、16–30、31–45、46–60、61–75),所以跨列不可能撞号,列内又因为无放回抽样而不重复,整卡必然是 24 个或 25 个不同号码,工具不需要再做一次去重。
- 每张卡都会现场校验三项。列内是否有重复号码、号码是否越出所属列区间、FREE 是否落在第 3 行 N 列,结果写在摘要第 2 句里。这三项都是结构性约束,正常生成时各项恒为 0。
- 列内不排序、跨列不交换。每列的号码自上而下就是洗牌顺序,也不存在「把某个号码挪到别的列」这种操作——列区间是号码的身份,不是显示位置。
- 种子相同、卡数不同时,前面的卡不变。第 i 张卡只由「基础种子 + (i−1)」决定,所以先印 5 张再补到 20 张,前 5 张内容不会乱。反过来说,如果你想整批重来,改种子而不是改卡数。
- 本工具产出的卡片只做号码排布。不判断中奖、不跟踪叫号、不记录已标记的格子,也不会把 FREE 之外任何格子预先标掉。
常见问题
为什么列区间非得是 1–15、16–30 这样固定的?
因为 1~75 共 75 个号码要平均分给 B、I、N、G、O 五列,75 ÷ 5 = 15 是唯一的整数解。每列固定 15 个号码后,卡面才能保证「同一个号码只可能出现在某一列的某一格」。这不是可以自由调整的排版偏好,而是 75 球规则的组成部分;90 球宾果用的是 3 行 9 列、每列宽度只有 9 或 10,两者不能混用。
中间格 FREE 是什么,关掉会怎样?
FREE 是标准 75 球卡印在 N 列正中的那格,开局就当作已经被叫到,所以它不占号码。勾选时 N 列只抽 4 个号码,分别放在第 1、2、4、5 行,整卡 24 个号码;取消勾选后 N 列补满 5 个号码,整卡 25 个。两种卡型的组合数不一样,前者是 30034×1365,后者是 30035。
同一列的号码为什么不按从小到大排?
真实印刷的宾果卡列内本来就是乱序,玩家要自己逐格找号码,排序反而会让找号变得有规律。更重要的是,把每列排成升序会丢掉一层随机信息:洗牌得到的是「有顺序的 5 个号码」,排序后只剩「这 5 个号码的集合」,同一颗种子在不同实现里就对不上了。示例卡 1 的 B 列是 15、12、2、5、11,正是洗牌后的原顺序。
用同一个种子重复点「生成卡片」,结果会一模一样吗?
会,完全一样。种子固定时 mulberry32 的整条输出序列是确定的,抽样结果自然一致——这正是「可复现」的意义。要换一批卡,把种子改掉任何一个数字即可;种子填 0 时才会每次都不一样,此时摘要会告诉你本次实际用了哪个种子,抄下来就能重现这一批。
生成 50 张卡会不会出现两张完全相同的?
理论上可能,实际概率约 1.10×10−14,也就是千亿分之一量级,可以认为不会发生。计算方式是:50 张卡有 C(50,2) = 1225 对,任意一对撞卡的概率是 1225 ÷ 111,007,923,832,370,565。如果你需要绝对保证,导出 CSV 后按行比对一次即可,列排序一致的号码集合就是重复卡。
这里的随机数是密码学安全的吗?能拿来抽奖吗?
不是。种子模式走的是 mulberry32,它只有 32 位内部状态,属于快速伪随机,不适合任何安全用途;即使种子填 0 换用 crypto.getRandomValues 取种,后续序列仍然由这个 32 位算法展开。宾果卡只需要号码分布正确、卡片之间不重复,不需要抗预测。抽奖、抽签、发凭证请用真正取加密随机源的随机数工具。
一张卡里会不会出现两个相同号码?
不会。跨列不可能重复,因为五个列区间互不重叠;列内不会重复,因为抽样是无放回的(部分 Fisher–Yates 取前 k 个)。所以带 FREE 的卡必然是 24 个互不相同的号码,不带 FREE 是 25 个。工具仍然每次都现场校验一遍并把结果写进摘要,方便你确认。
为什么一次最多只能生成 50 张?
50 张已经要渲染 1250 个数字格,再加上对照表的 50 行,页面体积和滚动长度都比较可观了。撞卡概率在 50 张时只有 1.10×10−14,数量并不是瓶颈,真正需要更多卡片的分批生成即可——每一批换一个种子,批次之间同样不会撞卡。