模擬「35 選 7」樂透選號:從 1~35 隨機抽取 7 個不重複號碼,由小至大排序後顯示於 7 個編輯框。
Lottery。IDC_NUM1~IDC_NUM7) 與 1 個 Button (IDC_PICK, Caption: 選號)。ClassWizard 為 7 個 Edit 綁定 int 型別成員變數:
m_num1, m_num2, ..., m_num7。
void CLotteryDlg::OnPick()
{
int pool[35], pick[7];
for (int i=0; i<35; i++) pool[i] = i+1; // 1~35
// 隨機抽樣 (Reservoir Sampling 變體)
for (int i=0; i<7; i++)
{
int idx;
do {
idx = rand() % 35;
} while (pool[idx] == 0); // 已抽中則重抽
pick[i] = pool[idx];
pool[idx] = 0; // 標記已用
}
// 氣泡排序 (7 筆資料效能足夠)
for (int pass=0; pass<7; pass++)
for (int i=0; i<7-pass-1; i++)
if (pick[i] > pick[i+1])
{
int tmp = pick[i];
pick[i] = pick[i+1];
pick[i+1] = tmp;
}
// 指派給編輯框變數
m_num1 = pick[0]; m_num2 = pick[1]; m_num3 = pick[2];
m_num4 = pick[3]; m_num5 = pick[4]; m_num6 = pick[5];
m_num7 = pick[6];
UpdateData(FALSE); // 變數 → 控件
}
在 OnInitDialog 呼叫 srand((unsigned)time(NULL)),確保每次執行序列不同。
| 方法 | 優點 | 適用場景 |
|---|---|---|
| Fisher-Yates Shuffle | O(N) 一次洗牌,無重複檢查 | 大範圍抽樣 (如 49 選 6) |
| std::random_shuffle (C++11) | 標準庫、均勻分布 | 現代 C++ 專案 |
| 密碼學亂數 (CryptGenRandom) | 不可預測、適合實際博弈 | 正式發行版本 |
Read Only、置中、大字體。OpenClipboard/SetClipboardData。