Khi nhấn quay, điều gì thực sự xảy ra bên dưới? Kết quả có thực sự ngẫu nhiên không, hay có thể bị can thiệp? Bài này giải thích cơ chế kỹ thuật đằng sau vòng quay may mắn — từ cách sinh số ngẫu nhiên, cách phân bổ xác suất, đến lý do tại sao mỗi lần quay là độc lập hoàn toàn — kèm theo nguồn kỹ thuật có thể kiểm chứng.
Vòng Quay Dùng Loại Random Nào?
Có hai loại random thường gặp trong lập trình:
- PRNG – Pseudorandom Number Generator (Bộ sinh số giả ngẫu nhiên): Dùng thuật toán toán học để tạo ra chuỗi số trông có vẻ ngẫu nhiên. Kết quả thực ra có thể tái tạo lại nếu biết “hạt giống” (seed) ban đầu. Đây là loại phổ biến nhất trong phần mềm thông thường.
- CSPRNG – Cryptographically Secure Pseudorandom Number Generator: Mạnh hơn PRNG, dùng cho mật mã học và bảo mật, lấy entropy từ nguồn phần cứng hoặc hệ điều hành. Khó đoán hơn đáng kể dù về bản chất vẫn là PRNG.
Vòng quay may mắn trên web dùng PRNG, cụ thể là hàm Math.random() có sẵn trong JavaScript — đây là lựa chọn tiêu chuẩn cho ứng dụng web không yêu cầu bảo mật cấp cao.
Math.random() Hoạt Động Như Thế Nào?
Theo tài liệu chính thức của MDN Web Docs — nguồn tham khảo JavaScript được Mozilla duy trì và cộng đồng lập trình viên toàn cầu tin dùng — Math.random() trả về một số thực giả ngẫu nhiên trong khoảng [0, 1) với phân phối gần đồng đều. Quan trọng hơn, MDN ghi rõ: “The implementation selects the initial seed to the random number generation algorithm; it cannot be chosen or reset by the user” — tức là người dùng không thể kiểm soát hay đặt lại seed.
Nguồn: MDN Web Docs – Math.random()
Để chọn ngẫu nhiên một mục trong danh sách N phần tử, vòng quay thực hiện phép tính:
chỉ_số = Math.floor(Math.random() * N)
Ví dụ danh sách có 5 tên: Math.random() trả về 0.742 → nhân với 5 = 3.71 → làm tròn xuống = 3 → chọn phần tử thứ 4 (chỉ số bắt đầu từ 0). Mỗi lần gọi Math.random() là một phép tính độc lập, không liên quan đến lần trước.
Math.random() Có Đủ Ngẫu Nhiên Không?
MDN cũng cảnh báo rõ ràng: “Math.random() does not provide cryptographically secure random numbers. Do not use them for anything related to security.” Thay vào đó, MDN khuyến nghị dùng Web Crypto API — cụ thể là window.crypto.getRandomValues().
Tuy nhiên, với mục đích sử dụng thông thường của vòng quay — chọn người phát biểu, rút thăm quà nhỏ, quyết định ăn gì — Math.random() hoàn toàn đủ. Chất lượng random của nó tốt hơn nhiều so với bốc thăm giấy viết tay. Yêu cầu dùng CSPRNG chỉ đặt ra khi ứng dụng liên quan đến bảo mật hay tiền thật.
Xác Suất Phân Bổ Như Thế Nào?
Khi danh sách có N mục và mỗi mục có trọng số bằng nhau, xác suất xuất hiện của mỗi mục là:
P(mục i) = 1 / N
Ví dụ cụ thể:
- 2 mục → mỗi mục 50%
- 4 mục → mỗi mục 25%
- 10 mục → mỗi mục 10%
- 100 mục → mỗi mục 1%
Diện tích mỗi ô trên bánh xe phản ánh đúng xác suất này — ô nào cũng bằng nhau khi trọng số đồng đều.
Tại Sao Mỗi Lần Quay Là Độc Lập?
Đây là điểm nhiều người hay nhầm. Câu hỏi thường gặp: “Nếu tên A vừa trúng, lần sau A có ít khả năng trúng hơn không?”
Câu trả lời: Không — trừ khi bạn bật tùy chọn “Xóa tên sau khi quay trúng”.
Mỗi lần gọi Math.random() là một phép tính hoàn toàn mới, không lưu trạng thái từ lần trước. Vòng quay không “nhớ” ai đã trúng. Xác suất của A ở lần quay thứ 10 giống hệt lần quay thứ 1 — đều là 1/N.
Gambler’s Fallacy – Ngụy Biện Phổ Biến Nhất Khi Xem Vòng Quay
Trong tâm lý học và lý thuyết xác suất, hiện tượng người ta cho rằng “nếu kết quả X vừa xảy ra nhiều lần, lần sau X ít có khả năng xảy ra hơn” được gọi là Gambler’s Fallacy (Ngụy biện của con bạc).
Wikipedia định nghĩa đây là niềm tin sai lầm rằng một sự kiện xảy ra ít thường xuyên hơn dự kiến trong quá khứ thì nhiều khả năng xảy ra hơn trong tương lai — hoặc ngược lại — dù các sự kiện đó hoàn toàn độc lập với nhau.
Nguồn: Wikipedia – Gambler’s fallacy
Ví dụ lịch sử nổi tiếng nhất: năm 1913 tại sòng Monte Carlo, bóng roulette rơi vào ô đen 26 lần liên tiếp. Các con bạc ồ ạt đặt cược vào đỏ vì tin rằng đỏ “đến lượt” — và thua rất nhiều tiền. Mỗi vòng quay hoàn toàn độc lập; không có vòng quay nào “nợ” kết quả nào cả.
Với vòng quay may mắn dùng Math.random(): nếu bạn quay 20 lần và tên A trúng 8 lần thay vì 4 lần như kỳ vọng, đó là biến động thống kê bình thường — không phải dấu hiệu hệ thống bị can thiệp. Theo Statistics By Jim, “random processes don’t have a memory of previous events” — quy trình ngẫu nhiên không có bộ nhớ về các sự kiện trước.
Nguồn: Statistics By Jim – Gambler’s Fallacy
Biến động này sẽ giảm dần khi số lần quay tăng lên — đây là nội dung của Luật số lớn (Law of Large Numbers): với đủ nhiều lần thử, tỷ lệ thực tế hội tụ về xác suất lý thuyết.
Hoạt Ảnh Quay Có Ảnh Hưởng Đến Kết Quả Không?
Không. Đây là điểm quan trọng cần hiểu rõ.
Trong các vòng quay trên web, kết quả được tính toán trước ngay tại thời điểm nhấn nút — sau đó hoạt ảnh mới chạy để “diễn” đến đúng ô đó. Bánh xe không thực sự “quay rồi dừng ngẫu nhiên” theo nghĩa vật lý.
Quy trình thực tế:
- Người dùng nhấn Quay.
Math.random()chạy, chọn ra chỉ số kết quả.- Hệ thống tính góc quay cần thiết để bánh dừng đúng ô đó.
- Hoạt ảnh chạy với easing (tốc độ giảm dần) để trông tự nhiên.
- Bánh dừng, kết quả hiển thị.
Điều này có nghĩa: tốc độ quay nhanh hay chậm, hoạt ảnh dài hay ngắn — đều không ảnh hưởng đến kết quả. Kết quả đã được quyết định từ bước 2.
Math.random() Khác Gì crypto.getRandomValues()?
Theo tài liệu MDN về Web Crypto API, Crypto.getRandomValues() cho phép lấy các giá trị ngẫu nhiên mạnh về mặt mật mã học (“cryptographically strong random values”). Đây là API thuộc nhóm CSPRNG, được seeded từ các nguồn entropy ngoại vi như hàm random của nền tảng hệ điều hành hay thiết bị /dev/urandom trên Unix.
Nguồn: MDN Web Docs – Crypto.getRandomValues()
So sánh thực tế:
| Math.random() | crypto.getRandomValues() | |
|---|---|---|
| Loại | PRNG | CSPRNG |
| Dùng cho | Ứng dụng thông thường | Mật mã học, bảo mật |
| Seed | Tự động từ trình duyệt | Entropy từ hệ điều hành |
| Có thể đoán trước? | Rất khó trong thực tế | Không thể về mặt thực tiễn |
| Phù hợp vòng quay? | ✓ Đủ dùng | Quá mức cần thiết |
Với mục đích vòng quay may mắn thông thường, sự khác biệt giữa hai loại này không có ý nghĩa thực tế. Cả hai đều cho kết quả không thể đoán trước trong điều kiện sử dụng bình thường.
Tóm Tắt
- Vòng quay web dùng
Math.random()— PRNG tiêu chuẩn của JavaScript, seed tự động từ trình duyệt, người dùng không thể kiểm soát. - Mỗi mục trong danh sách có xác suất bằng nhau: 1/N.
- Mỗi lần quay hoàn toàn độc lập — kết quả trước không ảnh hưởng kết quả sau.
- Kết quả được tính trước khi hoạt ảnh chạy — tốc độ quay không ảnh hưởng kết quả.
- Gambler’s Fallacy là ngụy biện phổ biến — vòng quay không “nhớ” lịch sử.
- Với mục đích thông thường,
Math.random()đủ ngẫu nhiên và công bằng.
Câu Hỏi Thường Gặp
Nếu danh sách có 2 người, mỗi người có đúng 50% không?
Về lý thuyết đúng. Trong thực tế, với số lần quay ít, bạn có thể thấy tỷ lệ lệch — ví dụ quay 10 lần mà một người trúng 7 lần. Đây là biến động thống kê bình thường, không phải lỗi. Tỷ lệ sẽ tiệm cận 50/50 khi số lần quay đủ lớn (Luật số lớn).
Tại sao đôi khi cùng một tên trúng liên tiếp nhiều lần?
Vì mỗi lần quay độc lập hoàn toàn. Xác suất tên A trúng 3 lần liên tiếp với danh sách 5 người là (1/5)³ = 0,8% — thấp nhưng hoàn toàn có thể xảy ra. Đây là bản chất của random, không phải dấu hiệu hệ thống bị lỗi hay can thiệp.
Vòng quay có “nhớ” kết quả các lần trước không?
Không, trừ khi bật tùy chọn “Xóa tên sau khi quay trúng”. Khi tắt tùy chọn đó, mỗi lần quay là một lần gọi Math.random() hoàn toàn mới — không lưu trạng thái hay lịch sử nào để điều chỉnh kết quả tiếp theo.
Có thể dùng vòng quay này cho xổ số tiền thật không?
Về mặt kỹ thuật thì được, nhưng về mặt pháp lý thì xổ số tiền thật tại Việt Nam chịu sự quản lý của nhà nước và yêu cầu giấy phép riêng. VQMM là công cụ random kỹ thuật, phù hợp cho các hoạt động nội bộ, giáo dục, và minigame không có giá trị tiền thật. Xem thêm: Vòng quay may mắn có hợp pháp tại Việt Nam không?
Math.random() khác gì crypto.getRandomValues()?
Math.random() là PRNG tiêu chuẩn — đủ cho ứng dụng thông thường nhưng không đủ cho bảo mật. crypto.getRandomValues() là CSPRNG — mạnh hơn, dùng cho mật mã học. Với vòng quay chọn người hay chọn quà thông thường, cả hai đều cho kết quả không thể đoán trước. Tham khảo: MDN – Crypto.getRandomValues().
Nguồn Tham Khảo
- MDN Web Docs. Math.random(). Mozilla. developer.mozilla.org
- MDN Web Docs. Crypto.getRandomValues(). Mozilla. developer.mozilla.org
- Wikipedia. Gambler’s fallacy. en.wikipedia.org
- Frost, Jim. Gambler’s Fallacy: Overview & Examples. Statistics By Jim. statisticsbyjim.com