問題 1
一般隨機模式會讀取歷史開獎號碼嗎?
不會。開始抽取時只建立 1 至 49 的新號碼池;結果 API 和歷史資料沒有傳入抽取函式。
數據與實測
沿着實際按鈕流程追查號碼池、畫面動畫、本機歷史及 Web Crypto,逐項回答下一次抽取究竟讀取了甚麼。
文內數字由版本化歷史快照、公開公式或實際程式流程產生;相關段落會交代起止日期、分母、計算步驟與適用限制。
內文
按下「開始攪珠」後,程式先清除上一輪計時器和畫面結果,再建立一個新的 LuckyDrum。一般隨機模式的 drum 只有一項初始資料:1 至 49 的完整陣列。它沒有接收上一組結果、官方歷史結果、熱門號碼表或使用者以前的選擇。
每抽一球,程式在目前陣列長度內選一個索引,取出該位置的號碼,再用 splice 從陣列刪除。第一球由 49 個位置選,第二球由剩下 48 個位置選,如此類推。刪除動作保證同一組內不會再抽到已取出的號碼,這種做法稱為無放回抽取。
抽取期間,畫面會快速顯示不同號碼,營造攪珠效果。這些動畫號碼每隔一段時間獨立取得,只寫入 currentShuffleNumber 作顯示。動畫停止後,程式才呼叫 drum.draw() 取得正式結果;currentShuffleNumber 從未傳入號碼池,也不會被當成候選號碼。
這個分隔很重要。若使用者看到動畫曾出現 4,最後結果又有 4,那只是兩次獨立取值恰好相同,不是動畫把 4 推入結果。相反,即使動畫從未顯示某號碼,它仍可在正式抽取時被選中。
| 程式中的資料 | 何時產生 | 用途 | 會否決定最後號碼 |
|---|---|---|---|
| currentShuffleNumber | 動畫播放期間 | 顯示滾動球 | 不會 |
| LuckyDrum.pool | 每次按開始時 | 保存尚未抽出的候選號碼 | 會 |
| drawnBalls | 每球正式抽出後 | 顯示本輪已完成結果 | 已是結果,不會回頭加權 |
| localStorage 最近記錄 | 整組完成後 | 在目前瀏覽器列出最近 12 組 | 不會 |
| GA4 事件 | 開始及完成操作時 | 記錄模式、目標數量等使用情況 | 不會,事件不包含抽出號碼 |
自選模式不是一律「把選中的號碼加進結果」,要視你選了多少個及目標需要多少個。
| 操作情況 | 程式實際做法 | 隨機部分 |
|---|---|---|
| 一般隨機 | 建立 1–49 完整池,逐球抽出並移除 | 所有目標號碼 |
| 自選 0 個 | 與一般隨機相同 | 所有目標號碼 |
| 自選少於目標 | 先固定自選號碼,從 1–49 移除它們,再補足 | 只抽欠缺數量 |
| 自選剛好等於目標 | 直接完成該批自選號碼 | 沒有隨機補號 |
| 自選多於目標 | 把候選池改成自選清單,再從中抽至目標數量 | 只在自選清單內抽 |
例如目標為 6 碼而你自選 3、7、19,程式先把三碼放進結果,亦從 1 至 49 的池中刪除它們,再抽另外三個,所以同組不會重複。若你自選十個號碼而目標仍是六個,候選池就只有該十個,結果不可能出現清單以外的號碼。
切換回一般隨機模式時,自選陣列會清空。每次重新開始亦會建立新 drum;它不會沿用上一輪抽剩的 43 個號碼。
程式使用瀏覽器 window.crypto.getRandomValues() 取得 32 位元無符號整數,範圍由 0 至 4,294,967,295。它不是 Math.random(),亂數材料由瀏覽器和作業系統提供。MDN 將 getRandomValues() 定位為可取得具密碼學強度亂數值的介面,但實際來源仍由瀏覽器實作;本站沒有聲稱它等同或模擬香港賽馬會的實體攪珠機。
若直接把所有 32 位元值除以 49 取餘數,因為 2³² 不能被 49 整除,部分餘數會比其他餘數多對應一個原始值。差距極小,但程式仍將它消除:先找出不超過 2³²、又可被目前池大小整除的最大界線;落在界線以上便捨棄並再取一個值。池大小為 49 時,尾段共有 39 個值會重取。號碼池縮至 48、47 時,界線亦會重新計算。
| 每球步驟 | 程式動作 | 防止的問題 |
|---|---|---|
| 1 | Web Crypto 取得 32 位元值 | 避免依賴 Math.random() |
| 2 | 超出可平均分配界線便重取 | 避免取餘數偏差 |
| 3 | 對目前池大小取餘數,得到索引 | 每個剩餘位置機會相同 |
| 4 | 取出並刪除該位置 | 同組不重複 |
| 5 | 全組完成後由小至大顯示 | 只改顯示次序,不改內容 |
首頁下方的最近記錄使用瀏覽器 localStorage,鍵名為 lucky_six_history,最多保留 12 組。程式只在整組狀態變成 COMPLETED 後寫入;開始新一輪的 handleStart 沒有讀取 history。刪除畫面記錄也只改 localStorage,不會觸及亂數函式。
官方歷史結果則由結果頁的資料模組取得,與 Machine 元件分開。Machine 沒有 import 結果快照,也沒有接收熱號、冷號或上期號碼參數。因此目前程式結構中不存在「歷史結果改變一般隨機權重」的路徑。
每組內不重複,不等於不同組之間必須完全不同。新一組重建 49 號碼池後,與上一組至少共享一碼的理論機率是 1 − C(43,6) ÷ C(49,6) = 56.4%。若程式強迫下一組避開上一組六碼,看起來會「更隨機」,實際上卻把第二組池縮成 43 個,改變了每個號碼原本的機會。
現有測試會檢查四類事情:輸出必須在指定範圍;同一號碼池抽取不重複;遇到會造成取餘數偏差的尾段值時確實重取;大量重複操作時,各候選號碼的入選次數沒有明顯偏離預期。它也分別測試完全隨機、自選後補齊、以及從較大自選池抽取的流程。
測試不能「證明未來每一組都看起來平均」。以 1,000 組六碼為例,每個指定號碼平均入選 122.45 次,標準差約 10.37 次;有人較多、有人較少才是正常結果。若 49 個號碼剛好全部一樣多,反而不可能,因為 6,000 不能平均分成 49 份。
更重要的是,自動測試只核對我們寫下的性質,不是第三方安全認證。讀者可查看方法論、實際重複率的歷史研究,以及 MDN 的 Crypto.getRandomValues 說明。若日後抽取程式改動,這頁和相應測試亦必須一起更新。
FAQ
問題 1
不會。開始抽取時只建立 1 至 49 的新號碼池;結果 API 和歷史資料沒有傳入抽取函式。
問題 2
不會。每次按下開始都建立新號碼池。最近記錄只在抽完後存入目前瀏覽器,下一次抽取流程沒有讀取這些號碼。
問題 3
不會。切回一般隨機時,自選陣列會被清空,抽取重新由完整 49 號碼池開始。
問題 4
不參與。動畫定時取得號碼只供畫面顯示;正式結果在每次動畫停止後,由 LuckyDrum 的剩餘號碼池另行抽取。
實際操作