建立陣列 [1,2,...,N],從尾端往前隨機交換,取前 k 個即為不重複隨機組合,時間複雜度 O(N)。
<!DOCTYPE html>
<html><head><meta charset="utf-8"><title>大樂透機選</title><style>
body { font-family:sans-serif; padding:20px; }
input[type=text] { width:40px; text-align:center; margin:0 4px; font-size:1.2rem; }
button { padding:8px 16px; font-size:1rem; cursor:pointer; }
</style></head><body>
<h3>大樂透 / 雙色球機選</h3>
<div id="red"></div>
<div id="blue" style="margin-top:8px;"></div>
<button onclick="pick()">機選一注</button>
<script>
function pick() {
// 紅球 1-33 選 6
const redPool = Array.from({length:33}, (_,i)=>i+1);
const red = [];
for (let i = redPool.length-1, k=6; k>0; i--, k--) {
const r = Math.floor(Math.random() * (i+1));
red.push(redPool[r]);
redPool[r] = redPool[i];
}
red.sort((a,b)=>a-b); // 習慣按大小排序顯示
// 藍球 1-16 選 1
const blue = Math.floor(Math.random() * 16) + 1;
// 寫入輸入框
document.getElementById('red').innerHTML = red.map((n,i)=>
`<input type="text" readonly value="${n}" title="紅球 ${i+1}">`
).join('');
document.getElementById('blue').innerHTML =
`<input type="text" readonly value="${blue}" style="background:#cfe; border-color:#090;" title="藍球">`;
}
// 初始化一次
pick();
</script></body></html>
Math.random()*16+1,不受紅球影響。red.sort((a,b)=>a-b) 符合彩券慣例。| 錯誤寫法 | 問題 | 修正 |
|---|---|---|
Math.random()*33+1 重複呼叫 6 次 | 極高機率產生重複號碼 | 洗牌法或 Set 去重 |
藍球用同一個池 redPool | 藍球範圍錯誤(1-33)且可能與紅球衝突 | 獨立 1-16 隨機 |
for(i=1;i<=7;i++) 迴圈處理紅+藍 | 邏輯混淆,第 7 次迴圈 i=7 時紅球池已剩 27 個 | 紅、藍分開處理 |
function pickMultiple(n) {
const results = [];
for (let i=0; i<n; i++) {
const red = shufflePick(Array.from({length:33},(_,i)=>i+1), 6).sort((a,b)=>a-b);
const blue = Math.floor(Math.random()*16)+1;
results.push({red, blue});
}
return results;
}
function shufflePick(arr, k) {
const a = [...arr], res = [];
for (let i=a.length-1; k>0; i--, k--) {
const r = Math.floor(Math.random()*(i+1));
res.push(a[r]); a[r]=a[i];
}
return res;
}