블랙잭

블랙잭

학습 연습 문제

소개

Case(다른 언어에서는 흔히 switch라고 불러요)는 if-else와 같은 제어 표현의 한 형태예요. 케이스를 사용하면 여러 개의 if-else-if 문을 이어서 쓸 수 있고, 흐름 제어를 하면서도 더 읽기 쉬운 코드를 만들 수 있어요.

케이스는 case 키워드와 그 뒤에 오는 선택적 표현식으로 정의돼요. 그다음 각 분기마다 when 키워드를 쓰고, 그 뒤에 케이스 표현식과 비교할 표현식을 적어요. when 키워드는 case 키워드보다 더 들여쓰면 안 돼요. when 키워드 뒤에는, 케이스 표현식이 when에 적은 표현식과 일치할 때 실행할 코드가 와요. 케이스에는 선택적으로 else 문을 쓸 수 있고, 이 코드는 어떤 케이스와도 일치하지 않을 때 실행돼요.

케이스 표현식이 평가된 다음, 각 when 표현식과 비교돼요. 이때 비교에는 케이스 동등 연산자(===)를 사용해요.

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

케이스 동등 연산자 (===)

케이스 동등 연산자(===)는 동등 연산자(==)와는 조금 달라요. 이 연산자는 오른쪽 값이 왼쪽 값이 나타내는 집합에 속하는지 확인해요. 즉, 두 피연산자를 어느 쪽에 두느냐가 중요해요. 어떻게 동작하는지는 왼쪽 값의 타입에 따라 달라요. 예를 들어 Range라면 오른쪽 값이 그 범위에 들어 있는지 확인하고, Object라면 오른쪽 값이 Object의 인스턴스인지 확인해요.

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

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

여러 표현식을 사용하는 케이스

케이스에서는 하나의 분기에 여러 표현식을 쉼표로 구분해서 나열할 수 있어요. 나열한 표현식 중 하나라도 일치하면 코드가 실행돼요. 하나의 분기에 여러 가능한 값을 두고 싶을 때 유용해요.

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

범위를 사용하는 케이스

케이스는 값이 범위 안에 있는지도 확인할 수 있어요. when 표현식에 범위를 쓰면 돼요.

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

케이스 표현식이 없는 케이스

케이스 표현식이 필요 없을 때는 생략할 수 있어요. 이렇게 하면 각 분기의 표현식을 참인지 여부로 평가해요. 그래서 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에서는 케이스 문을 한 줄로 쓸 수 있어요. 실행할 코드가 한 줄로 간단할 때 유용해요. 한 줄 when 문은 when <expression> then <statement> 형태로 써요. 그리고 else 문에서 사용할 때는 else <statement>로 써요.

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

타입과 함께 쓰는 케이스

케이스는 타입을 기준으로 일치 여부를 확인할 수도 있어요. 변수의 타입에 따라 다르게 동작하게 하고 싶을 때 유용해요.

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

지침

이 연습 문제에서는 블랙잭 게임의 첫 턴을 시뮬레이션해요.

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 other 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 두 장을 가지고 있으면 항상 스플릿해야 해요.
  • 블랙잭(두 카드의 값 합이 21)이고 딜러가 ace나 그림 카드, ten을 가지고 있지 않다면 자동으로 승리해요. 딜러가 그중 하나라도 가지고 있다면 스탠드하고, 다른 카드가 공개되기를 기다려야 해요.
  • 카드의 값 합이 [17, 20] 범위에 들어가면 항상 스탠드해야 해요.
  • 카드의 값 합이 [12, 16] 범위에 들어가면 항상 스탠드해야 해요. 단, 딜러가 7 이상을 가지고 있으면 항상 히트해야 해요.
  • 카드의 값 합이 11 이하이면 항상 히트해야 해요.

카드 세 장을 문자열 인자로 받는 Blackjack.first_turn 메서드를 구현해요. 메서드는 선택해야 할 결정을 문자열로 반환해야 해요.

Blackjack.first_turn("ace", "ace", "two")
# => "P"
GitHub에서 편집 링크가 새 창이나 탭에서 열려요
Ruby Exercism

블랙잭 문제를 시작해 볼 준비가 됐나요?

Exercism에 가입하고 Ruby 트랙을 개념 21개연습 문제 121개, 그리고 실제 사람의 멘토링과 함께 배우고 익혀 보세요. 모두 무료예요.