トラック
/
Ruby
Ruby
/
演習
/
ブラックジャック
ブラックジャック

ブラックジャック

学習演習

はじめに

Case(他の言語ではしばしばswitchと呼ばれます)は、if-elseのような制御式の一種です。 caseでは複数のif-elsif文をつなげて書くことができ、制御フローを保ったまま、より読みやすく書けます。

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では、複数の式を1つの分岐で一致させることができ、それぞれの値をカンマで区切って書きます。 いずれかの式が一致すれば、そのコードが実行されます。 1つの分岐に複数の値を指定したいときに便利です。

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の式が不要なときは、省略できます。 省略すると、各whenの式が真かどうかで評価されます。 そのため、if-elsif文と同じように動作します。

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

1行のwhen

Rubyでは、case文を1行で書くことができます。 これは、単純な1行の文を書きたいときに使えます。 1行の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

説明

この演習では、ブラックジャックの最初のターンをシミュレーションします。

1. カードの値を計算する

2枚のカードを受け取り、ディーラーの表向きのカードを見ることができます。 カードはすべて、"ace"、"king"、"three"、"two"などの文字列で表されます。 各カードの値は次のとおりです:

card value card value
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

一般に、エースは1または11の値を取ることができますが、ここでは簡単のため、11の値しか取らないものとします。

カードを文字列として受け取るメソッドBlackjack.parse_cardを実装してください。 このメソッドは、カードの値を整数として返すようにします。

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

2. 値の範囲に名前を付ける

プレイヤーのスコアは、値の範囲に分類する必要があります。 プレイヤーのスコアは、プレイヤーの2枚のカードの値を合計して計算します。 使用する範囲は次のとおりです:

range value
low [4, 11]
mid [12, 16]
high [17, 20]
blackjack [21]

2枚のカードを文字列として受け取るメソッドBlackjack.card_rangeを実装してください。 このメソッドは、2枚のカードが該当する値の範囲の名前を返すようにします。

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

3. 最初のターンの判断ロジックを実装する

手持ちの2枚のカードとディーラーのカードに応じて、ゲームの最初のターンには戦略があります。選択肢は次のとおりです:

  • スタンド(S)
  • ヒット(H)
  • スプリット(P)
  • 自動勝利(W)

まだ最適ではありませんが、友人のAlexが開発を進めている次の戦略に従います:

  • エースのペアを持っている場合は、必ずスプリットします。
  • ブラックジャック(2枚のカードの合計が21になる場合)で、ディーラーがエース、絵札、10のいずれも持っていない場合は、自動的に勝ちになります。 ディーラーがそれらのカードのいずれかを持っている場合は、スタンドして、もう1枚のカードが公開されるのを待ちます。
  • カードの合計が[17, 20]の範囲にある場合は、必ずスタンドします。
  • カードの合計が[12, 16]の範囲にある場合は、ディーラーが7以上でない限り、必ずスタンドします。ディーラーが7以上の場合は、必ずヒットします。
  • カードの合計が11以下の場合は、必ずヒットします。

3枚のカードを文字列として受け取るメソッドBlackjack.first_turnを実装してください。 このメソッドは、取るべき判断を文字列として返すようにします。

Blackjack.first_turn("ace", "ace", "two")
# => "P"
GitHubで編集する リンクは新しいウィンドウまたはタブで開きます
Ruby Exercism

ブラックジャックを始める準備はできましたか?

Exercismに登録すれば、21個のコンセプト121個の演習、そして本物の人間によるメンタリングとともに、Rubyを学んでマスターできます。すべて無料です。