| 玩家 \ 電腦 | 石頭(0) | 剪刀(1) | 布(2) |
|---|---|---|---|
| 石頭(0) | 平 | 贏 | 輸 |
| 剪刀(1) | 輸 | 平 | 贏 |
| 布(2) | 贏 | 輸 | 平 |
數學公式:`(player - computer + 3) % 3` → 0:平, 1:贏, 2:輸
#include#include #include #include int str_to_choice(const char *s) { if (strcmp(s, "石頭") == 0) return 0; if (strcmp(s, "剪刀") == 0) return 1; if (strcmp(s, "布") == 0) return 2; return -1; } const char *choice_to_str(int c) { static const char *names[] = {"石頭", "剪刀", "布"}; return (c >= 0 && c <= 2) ? names[c] : "未知"; } int judge(int player, int computer) { int diff = (player - computer + 3) % 3; return diff; // 0:平, 1:贏, 2:輸 } void print_menu() { puts("*******************************"); puts("**** 1. Start Game ************"); puts("**** 0. Exit ******************"); puts("*******************************"); } int main() { srand((unsigned)time(NULL)); int choice = 1; while (choice) { print_menu(); printf("Choice: "); if (scanf("%d", &choice) != 1) { while(getchar()!='\n'); continue; } if (choice == 0) { puts("Bye!"); break; } if (choice != 1) { puts("Invalid!"); continue; } int win = 0, lose = 0, draw = 0; for (int round = 1; round <= 3; round++) { char input[10]; printf("Round %d - 石頭/剪刀/布: ", round); scanf("%s", input); int player = str_to_choice(input); if (player == -1) { puts("Invalid input!"); round--; continue; } int computer = rand() % 3; int result = judge(player, computer); printf("You: %s | Computer: %s -> ", choice_to_str(player), choice_to_str(computer)); if (result == 0) { puts("Draw"); draw++; } else if (result == 1) { puts("You Win!"); win++; } else { puts("You Lose!"); lose++; } if (win == 2) { puts(">>> You win the game! <<<"); break; } if (lose == 2) { puts(">>> You lose the game! <<<"); break; } } if (win < 2 && lose < 2) { if (draw == 3) puts(">>> All draws! <<<"); else if (win > lose) puts(">>> You win the game! <<<"); else puts(">>> You lose the game! <<<"); } } return 0; }
| 原始問題 | 改進 |
|---|---|
| `srand` 在迴圈內重複呼叫 | 移至 `main` 開頭單次呼叫 |
| 巨大的 `if-else` 判斷勝負 | 數學公式 `(p-c+3)%3` 簡化 |
| 字串比較重複 `strcmp` | 封裝 `str_to_choice` 函式 |
| 輸入緩衝區未清理 | `scanf` 失敗時清空緩衝區 |
| 魔術數字 0/1/2 分散 | 常數陣列 `choice_to_str` 集中管理 |
剪刀石頭布是條件判斷、隨機數、字串處理、迴圈控制的綜合練習。引入**數學公式簡化勝負邏輯**、**函式封裝輸入轉換**、**單次 `srand`** 等優化,能大幅提升程式碼品質與可維護性。三戰兩勝制增加了狀態管理的練習價值。