case(在其他語言中常被稱為 switch)是一種和 if-else 類似的控制運算式。case可以串接多個 if-else-if 敘述,通常更好讀,也能寫出更強大的結構。
case由關鍵字case定義,後面可以選擇性地接一個運算式。接著,每個分支會使用關鍵字when,後面接一個要和 case 運算式比較的運算式。when關鍵字的縮排不應比case關鍵字多。when關鍵字後面,就是當 case 運算式符合 when 運算式時要執行的程式碼。case 也可以加上選用的else敘述,當其他分支都不符合時就會執行。
case 運算式會先求值,然後和每個 when 運算式比較。比較時使用的是 case 涵蓋運算子(===)。
case 1
when 1
puts "One"
when 2
puts "Two"
else
puts "Other"
end
# => One
# This is the same as:
tmp = 1
if 1 === tmp
puts "One"
elsif 2 === tmp
puts "Two"
else
puts "Other"
end
===)case 涵蓋運算子(===)和等號運算子(==)有點不同。這個運算子會檢查右邊是不是左邊所描述集合的成員。也就是說,每個運算元放在哪一側是有影響的。實際的行為取決於左邊的型別,例如Range會檢查右邊是否落在該範圍內,而Object則會檢查右邊是不是Object的實例。
(1..3) == 1 # => false
(1..3) === 1 # => true
String == "foo" # => false
String === "foo" # => true
一個分支可以比對多個運算式,只要用逗號分隔每個可能的值。只要其中任何一個運算式符合,就會執行對應的程式碼。當單一分支可能對應多個值時,這就很方便。
case 1
when 1, 2
puts "One or two"
else
puts "Other"
end
case 也能檢查某個值是否落在某個範圍內。只要把範圍當成 when 運算式就可以了。
case var
when 1..3
puts "One to three"
else
puts "Other"
end
當不需要 case 運算式時,可以將它省略。這麼做之後,每個 when 運算式都會改以真假值來判斷,行為就像 if-else-if 敘述一樣。
case
when 1 == 1
puts "One is equal to one"
when 1 > 2
puts "One is greater than two"
else
puts "Other"
end
Crystal 允許單行的 case 敘述,適合用來處理簡單的單行敘述。單行的 when 敘述寫成when <expression> then <statement>.,用在 else 敘述時則寫成else <statement>。
case var
when 1 then puts "One"
when 2 then puts "Two"
else puts "Other"
end
case 也可以搭配型別來比對,比對時會使用is_a?運算子來檢查變數的型別。舉例來說,這讓聯合型別中的每個型別都能有自己的分支。
case var
when Int32
puts "Int32"
when String
puts "String"
else
puts "Other"
end
case 可以使用隱式物件。舉例來說,這讓 when 運算式可以是對 case 運算式的方法呼叫。再根據這個方法回傳的是真值還是假值,決定這個分支符不符合。
case 1
when .odd?
puts "Odd"
when .even?
puts "Even"
end
在這個練習中,我們會模擬一局 Blackjack 遊戲的第一回合。
你會拿到兩張牌,並且能看到莊家的明牌。 所有牌都以字串表示,例如「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 | other | 0 |
一般來說,ace 可以取 1 或 11 的值,但為了簡化,我們假設 ace 只能取 11 的值。
實作Blackjack.parse_card方法,它會接受一張牌作為字串引數。
這個方法應該以整數回傳該張牌的值。
Blackjack.parse_card("ace")
# => 11
玩家的分數必須被歸類到不同的值範圍中。 玩家的分數是將兩張玩家牌的值相加而得。 所使用的範圍如下:
| 範圍 | 值 |
|---|---|
| low | [4, 11] |
| mid | [12, 16] |
| high | [17, 20] |
| blackjack | [21] |
實作Blackjack.card_range方法,它會接受兩張牌作為字串引數。
這個方法應該回傳這兩張牌所屬的值範圍名稱。
Blackjack.card_range("ten", "king")
# => "high"
根據你的兩張牌和莊家的牌,遊戲的第一回合有一套策略,你有以下選項:
雖然還不是最佳策略,但你要遵循你朋友 Alex 一直在開發的策略,內容如下:
實作Blackjack.first_turn方法,它會接受三張牌作為字串引數。
這個方法應該以字串回傳你應該採取的決策。
Blackjack.first_turn("ace", "ace", "two")
# => "P"