---
title: 這個轉盤公平嗎
nav: 這個轉盤公平嗎
order: 3
description: 中獎者是先抽出來的，動畫只是讓轉盤停在那一格。說明為什麼「讓轉盤自由旋轉看它停在哪」反而不公平，以及這個工具怎麼被驗證。
updated: 2026-08-13
---

## 先抽人，再轉盤

這個轉盤的運作順序是：

1. 按下「開始」的**那一瞬間**，就用加權隨機抽出中獎者
2. 反推「要讓那一格停在指針下，轉盤該轉到哪個角度」
3. 播 6 秒的減速動畫，停在那個角度

也就是說，**動畫只是演出來的**，結果在動畫開始前就決定了。

聽起來像作弊，其實相反 —— 這是比較公平的做法。

## 為什麼不讓轉盤自由旋轉

直覺上「隨機給一個力道讓它自由停下」比較公平，但實際上不是：

轉盤最後停在哪，取決於**起始角度 ＋ 隨機力道 ＋ 減速曲線**三者的組合。
這三個東西都不是均勻分布的：

- **起始角度**是上一輪停的位置，不是隨機的
- **減速曲線**（`easeOutQuart` 之類）讓最後一段轉得很慢，落點會集中在某些區域
- 力道的隨機範圍如果不是圓周的整數倍，某些角度被掃過的次數就是比較多

三個偏差疊起來，結果就是**某些格子比較容易停**。而最糟的是：
這種偏差**完全看不出來**。畫面上轉盤在轉、看起來很隨機，但跑一萬次就會看到分布不平。

先抽再轉的做法把「隨機」壓縮成一行程式：

```js
let r = Math.random() * 總權重;
for (…) { r -= 這個人的權重; if (r < 0) return 這個人; }
```

這一行可以直接被驗證，動畫怎麼寫都不會影響它。

## 怎麼驗證

這個工具的抽選函式有自動化測試，每次改版都會跑：

- **20 萬次抽樣**，權重 1／2／3／4 的實際中獎比例與理論值（10%／20%／30%／40%）
  誤差必須小於 1%
- 權重全部相同時必須是均勻分布
- **扇形寬度必須等於權重比例** —— 防止「畫面等分、實際加權」那種說謊的畫面
- **動畫的目標角度必須讓指定的那一格精準對準指針**（誤差小於 10⁻⁹）——
  防止「畫面指到 A、名單記的是 B」

最後一條特別重要：如果動畫算錯，現場會看到指針明明停在張三，跳出來的名字卻是李四。
那在尾牙舞台上是無法解釋的。

## 隨機來源是什麼

`Math.random()`，也就是瀏覽器內建的偽隨機數產生器。

⚠️ 誠實說明它的性質：這是**偽隨機**，不是密碼學等級的亂數。
對抽獎來說綽綽有餘（沒有人能預測或操縱它），但它不適合用在需要防止有心人破解的場合
（例如線上博弈）。尾牙抽獎用它是完全合理的。

## 還有一道守衛

動畫是非同步的，而瀏覽器會**完全暫停背景分頁的動畫**（實測：分頁隱藏時 1 秒 0 幀）。
主持人切去看投影片再切回來，中獎結果才會補寫入 —— 而那時候狀態可能已經變了。

所以結果寫進名單之前會**重新確認**兩件事：這個獎項還有名額、這個人還有資格。
不確認的話會出現「3 個名額卻列出 4 位中獎者」或「一人只中一次卻中了兩次」。
這兩個在畫面上都很明顯，但開發時測不到 —— 它們是實際踩到之後才補上的守衛。

現場操作的注意事項見[尾牙現場的實務](/lucky-wheel/docs/on-stage)。
