BlackJack

BlackJack

Exercício de aprendizagem

Introdução

Case (muitas vezes chamado de switch em outras linguagens) é uma forma de expressão de controle, como o if-else. O case permite encadear várias instruções if-else-if e pode ser mais legível, sem deixar de oferecer controle de fluxo.

Um case é definido pela palavra-chave case, seguida de uma expressão opcional. Depois, para cada caso, usa-se a palavra-chave when, seguida de uma expressão que é comparada à expressão do case. A palavra-chave when não deve ficar indentada em relação à palavra-chave case. Depois da palavra-chave when vem o código que deve ser executado se a expressão do case corresponder à expressão do when. O case permite uma instrução else opcional, que é executada se nenhum outro caso corresponder.

A expressão do case é avaliada e depois comparada a cada expressão do when. A comparação é feita com o operador de igualdade de 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

Operador de igualdade de case (===)

O operador de igualdade de case (===) é um pouco diferente do operador de igualdade (==). Ele verifica se o lado direito é um membro do conjunto descrito pelo lado esquerdo. Isso significa que a posição de cada operando importa. O funcionamento depende do tipo do lado esquerdo: por exemplo, um Range verifica se o lado direito está no intervalo, e um Object verifica se o lado direito é uma instância do Object.

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

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

Case com múltiplas expressões

Os cases permitem corresponder a várias expressões em um único case, com cada valor possível separado por vírgula. O código é executado se qualquer uma das expressões corresponder. Isso pode ser útil quando você quer que um único case tenha vários valores possíveis.

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

Case com intervalos

Os cases também podem verificar se um valor está em um intervalo. Para isso, basta usar um intervalo como expressão do when.

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

Case sem expressão de case

Quando não há necessidade de uma expressão de case, é possível omiti-la. Assim, cada expressão de case é avaliada quanto à sua veracidade, o que faz com que se comportem como instruções if-else-if.

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

When em uma linha

O Ruby permite instruções case de uma linha. Isso pode ser usado quando você tem uma instrução simples de uma linha. A instrução when de uma linha é escrita como when <expression> then <statement>. E, quando usada na instrução else, ela é escrita como else <statement>.

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

Case com tipos

O case permite fazer correspondência com tipos. Isso é útil quando você quer comportamentos diferentes dependendo do tipo de uma variável.

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

Instruções

Neste exercício, vamos simular o primeiro turno de uma partida de Blackjack.

1. Calcule o valor de uma carta qualquer.

Você vai receber duas cartas e vai poder ver a carta virada para cima do dealer. Todas as cartas são representadas por uma string como "ace", "king", "three", "two" etc. Os valores de cada carta são:

carta valor carta valor
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

Normalmente, os ases podem valer 1 ou 11, mas, por simplicidade, vamos assumir que só podem valer 11.

Implemente o método Blackjack.parse_card, que recebe como argumento uma carta na forma de string. O método deve retornar o valor da carta como um número inteiro.

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

2. Dê nomes a faixas de valores.

A pontuação do jogador precisa ser categorizada em faixas de valores. A pontuação do jogador é calculada somando os valores das duas cartas do jogador. As faixas usadas são:

faixa valor
low [4, 11]
mid [12, 16]
high [17, 20]
blackjack [21]

Implemente o método Blackjack.card_range, que recebe como argumentos duas cartas na forma de strings. O método deve retornar o nome da faixa de valores em que as duas cartas se encaixam.

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

3. Implemente a lógica de decisão para o primeiro turno.

Dependendo das suas duas cartas e da carta do dealer, existe uma estratégia para o primeiro turno do jogo, na qual você tem as seguintes opções:

  • Parar (S)
  • Pedir carta (H)
  • Dividir (P)
  • Vitória automática (W)

Apesar de ainda não ser ideal, você vai seguir a estratégia que seu amigo Alex vem desenvolvendo, que é assim:

  • Se você tiver um par de ases, deve sempre dividi-los.
  • Se você tiver um Blackjack (duas cartas que somam 21), e o dealer não tiver um ás, uma figura ou um dez, você ganha automaticamente. Se o dealer tiver alguma dessas cartas, você vai ter que parar e esperar que a outra carta seja revelada.
  • Se suas cartas somarem um valor dentro da faixa [17, 20], você deve sempre parar.
  • Se suas cartas somarem um valor dentro da faixa [12, 16], você deve sempre parar, a menos que o dealer tenha um 7 ou mais, caso em que você deve sempre pedir carta.
  • Se suas cartas somarem 11 ou menos, você deve sempre pedir carta.

Implemente o método Blackjack.first_turn, que recebe como argumentos três cartas na forma de strings. O método deve retornar, como string, a decisão que você deve tomar.

Blackjack.first_turn("ace", "ace", "two")
# => "P"
Editar via GitHub O link abre em uma nova janela ou aba
Ruby Exercism

Tudo pronto para começar BlackJack?

Crie sua conta no Exercism para aprender e dominar Ruby com 21 conceitos121 exercícios e mentoria humana de verdade, tudo de graça.