學習軌道
/
Ruby
Ruby
/
練習
/
二十一點
二十一點

二十一點

學習練習

簡介

Case 是一種控制運算式,就像 if-else 一樣(在其他語言中常被稱為 switch)。 Case 可以串接多個 if-else-if 敘述,而且在提供流程控制的同時,通常也更容易閱讀。

一個 case 是以關鍵字case定義,後面可選擇性地接一個運算式。 接著,每個分支都用關鍵字when,後面接一個運算式,該運算式會與 case 運算式比較。 when關鍵字不應相對於case關鍵字縮排。 when關鍵字後面,是要在 case 運算式符合 when 運算式時執行的程式碼。 Case 允許選擇性地加上else敘述;當沒有其他分支符合時,就會執行這個敘述。

case 運算式會先求值,再與每個when運算式比較。 比較時使用的是 case 相等運算子(===)。

value = 1
case value
when 1
  "One"
when 2
  "Two"
else
  "Other"
end

# This is the same as:
value = 1
if 1 === value
  "One"
elsif 2 === value
  "Two"
else
  "Other"
end

Case 相等運算子(===)

Case 相等運算子(===)和相等運算子(==)有點不同。 這個運算子會檢查右邊是不是左邊所描述集合中的一員。 這表示每個運算元放置的位置是有影響的。 實際運作的方式取決於左邊的型別,例如Range會檢查右邊是否在範圍內,而Object則會檢查右邊是不是Object的實例。

(1..3) == 1  # => false
(1..3) === 1 # => true

String == "foo"  # => false
String === "foo" # => true

搭配多個運算式的 Case

Case 可以在單一分支中比對多個運算式,每個可能的值以逗號分隔。 只要其中任何一個運算式符合,就會執行這段程式碼。 當你希望單一分支能有多個可能的值時,這就很有用。

case var
when 1, 2
  "One or two"
else
  "Other"
end

搭配範圍的 Case

Case 也可以檢查某個值是否落在範圍內。 做法是把範圍當作 when 運算式。

case var
when 1..3
  puts "One to three"
else
  puts "Other"
end

沒有 case 運算式的 Case

當不需要 case 運算式時,可以將它省略。 這麼做會讓每個 when 運算式改為判斷真值。 它們的行為也就會像 if-else-if 敘述一樣。

case
when 1 == 1
  "One is equal to one"
when 1 > 2
  "One is greater than two"
else
  "Other"
end

單行的 when

Ruby 允許單行的 case 敘述。 當你只有簡單的單行敘述時,就可以這麼寫。 單行 when 敘述的寫法是when <expression> then <statement>。 而在 else 敘述中使用時,寫法則是else <statement>。

case var
when 1 then "One"
when 2 then "Two"
else "Other"
end

搭配型別的 Case

Case 可以搭配型別進行比對。 當你想根據變數的型別而有不同的行為時,這就很有用。

case var
when Integer
  "Integer"
when String
  "String"
else
  "Other"
end

說明

在這個練習中,我們會模擬一場 Blackjack 遊戲的第一回合。

1. 計算任何一張牌的值。

你會拿到兩張牌,並且能看見莊家攤開的那張牌。 所有牌都用字串表示,例如「ace」、「king」、「three」、「two」等。每張牌的值如下:

牌 值 牌 值
ace 11 eight 8
two 2 nine 9
three 3 ten 10
four 4 jack 10
five 5 queen 10
six 6 king 10
seven 7 其他 0
Note

一般來說,ace 可以算作 1 或 11,但為了簡化,我們假設它只能算作 11。

實作Blackjack.parse_card方法,它接收一張以字串表示的牌作為引數。 這個方法應該把牌的值以整數回傳。

Blackjack.parse_card("ace")
# => 11

2. 為各種數值範圍命名。

玩家分數必須歸類到不同的數值範圍。 玩家分數的計算方式,是把兩張玩家牌的值相加。使用的範圍如下:

範圍 值
low [4, 11]
mid [12, 16]
high [17, 20]
blackjack [21]

實作Blackjack.card_range方法,它接收兩張以字串表示的牌作為引數。 這個方法應該回傳這兩張牌所屬範圍的名稱。

Blackjack.card_range("ten", "king")
# => "high"

3. 實作第一回合的決策邏輯。

根據你的兩張牌和莊家的牌,遊戲的第一回合有一套策略,你有以下選擇:

  • 停牌(S)
  • 要牌(H)
  • 分牌(P)
  • 自動獲勝(W)

雖然這個策略還不是最佳解,但你要採用你朋友 Alex 一直在開發的策略,內容如下:

  • 如果你拿到一對 ace,一定要分牌。
  • 如果你拿到 Blackjack(兩張牌加起來的值為 21),而且莊家沒有 ace、人頭牌或 ten,你就自動獲勝。 如果莊家確實有其中任何一張牌,你就必須停牌,等待另一張牌揭曉。
  • 如果你兩張牌的值加起來落在 [17, 20] 這個範圍,就一定要停牌。
  • 如果你兩張牌的值加起來落在 [12, 16] 這個範圍,就一定要停牌,除非莊家有 7 或更大的牌,這時你就一定要要牌。
  • 如果你兩張牌的值加起來是 11 或更低,就一定要要牌。

實作Blackjack.first_turn方法,它接收三張以字串表示的牌作為引數。 這個方法應該把你該採取的決定以字串回傳。

Blackjack.first_turn("ace", "ace", "two")
# => "P"
透過 GitHub 編輯 連結會在新視窗或分頁中開啟
Ruby Exercism

準備好開始 二十一點 了嗎?

註冊 Exercism,透過 21 個概念121 個練習 和真人引導來學習並精通 Ruby,全部免費。