C 語言程式設計教學:(案例) 花旗骰 (Craps)

PUBLISHED ON JUL 11, 2018 — PROGRAMMING

我們先暫停一般的教學文,來做一個好玩的小東西,這篇文章不影響本系列文的教學,讀者可自行視需求選讀。

如果已經熟悉這個主題,想直接觀看程式碼,可到這裡

遊玩方式

Craps (花旗骰) 是一種使用骰子 (dice) 的賭博遊戲,由於其規則簡單,常出現在基礎的程式設計教材中。一般的程式設計教材僅使用其規則,但沒有娛樂的成份,本文加入一點選邊站的功能。

本文的 Craps 玩法如下:

  • 玩家選擇 passno pass
  • 由電腦自動擲骰
  • 第一輪是 come-out roll
    • 若擲出 2、3、12,算是 *no pass*,遊戲結束 (Craps)
    • 若擲出 7,算是 *pass*,遊戲結束 (Natural)
    • 若擲出其他數字,這個數字就是我們的 point
  • 第二輪開始是 point roll
    • 若擲出 *point*,算是 *pass*,遊戲結束 (Hit)
    • 若擲出 7,算是 *no pass*,遊戲結束 (Seven-out)
    • 若擲出其他數字,則重新再擲
  • 若玩家的選擇和遊戲結果相同,則玩家勝;反之則負

一開始 no pass 的機率大一點,但隨著遊戲進行,兩邊的機率會趨於一致,所以這個遊戲還算公平。

程式展示

我們的程式是終端機程式,這類程式易於實作,適合初學者,也是我們目前為止學會的程式類型。

直接執行程式時代表我們選擇 *pass*:

$ ./craps
Come-out roll: 6 + 4 = 10
Got 5 + 6 = 11. Try again...
Got 2 + 6 = 8. Try again...
Got 3 + 5 = 8. Try again...
Got 4 + 5 = 9. Try again...
Got 5 + 6 = 11. Try again...
Got 2 + 1 = 3. Try again...
Got 1 + 2 = 3. Try again...
Got 6 + 3 = 9. Try again...
Hit: 4 + 6 = 10
The player wins

我們在這裡不採用互動式的 scanf 函式取得使用者輸入,而直接從命令列參數來操作程式,這是承襲 Unix 文化的思維。

我們也可以選擇 *no pass*:

$ ./craps wrong
Come-out roll: 2 + 6 = 8
Got 3 + 2 = 5. Try again...
Got 6 + 4 = 10. Try again...
Seven-out: 1 + 6 = 7
The player wins

本程式還提供寧靜模式 (quiet mode),僅提供最少量的訊息:

$ ./craps -q
lose

由於程式內部實作的緣故,如果要批次賭搏,每次間隔要至少一秒:

$ for i in `seq 1 10`; do ./craps -q wrong; sleep 1; done
lose
lose
win
lose
win
lose
lose
win
lose
lose

抽象思維

由於本實作的程式碼略長,我們會先用虛擬碼 (pseudocode) 來展示其觀念。虛擬碼是一種半結構化的語言,用來表示程式實作的高階抽象概念 (可看這裡)。本遊戲的虛擬碼如下:

Pass and NotPass are two game result symbols.
gameStart and gameOver are two game state symbols.

bet <- choose from either Pass or NotPass

result <- Pass
state <- gameStart

// Come-out roll.
comeOut <- roll two dices
if comeOut == 2 or comeOut