Blackjack

Blackjack

Exercício de aprendizagem

Introdução

case (muitas vezes designado por switch noutras linguagens) é uma forma de expressão de controlo, tal como o if-else. O case permite encadear várias instruções if-else-if, pode ser mais legível e permite construir coisas poderosas.

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 com a expressão do case. A palavra-chave when não deve estar indentada em relação à palavra-chave case. A seguir à 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 cláusula else opcional, que é executada se nenhum outro caso corresponder.

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

Operador de subsunção do case (===)

O operador de subsunção do case (===) é um pouco diferente do operador de igualdade (==). O operador verifica se o lado direito é um membro do conjunto descrito pelo lado esquerdo. Isto significa que a posição de cada operando é importante. 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 várias expressões

Os case permitem corresponder a várias expressões num único caso, com cada valor possível separado por uma vírgula. O código é executado se alguma das expressões corresponder. Isto pode ser útil para um único caso com vários valores possíveis.

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

Case com intervalos

Os case também podem verificar se um valor está num 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 é precisa uma expressão de case, é possível omiti-la. Ao fazê-lo, cada expressão do when passa a ser avaliada quanto ao seu valor de verdade. E faz com que se comportem como instruções 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

When numa só linha

O Crystal permite instruções case numa só linha. Podes usá-lo quando tens uma instrução simples de uma só linha. A forma numa só linha escreve-se como when <expression> then <statement>. E, quando usada na cláusula else, escreve-se como else <statement>.

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

Case com tipos

O case permite fazer correspondência com tipos. A comparação usa o operador is_a? para verificar o tipo da variável. Por exemplo, isto permite um ramo para cada tipo de um tipo união.

case var
when Int32
  puts "Int32"
when String
  puts "String"
else
  puts "Other"
end

Objeto implícito

O case permite usar um objeto implícito. Isto permite, por exemplo, que a expressão do when seja uma chamada de método sobre a expressão do case. Consoante o método devolva um valor verdadeiro ou falso, o caso corresponderá ou não.

case 1
when .odd?
  puts "Odd"
when .even?
  puts "Even"
end

Instruções

Neste exercício vamos simular o primeiro turno de um jogo de Blackjack.

1. Calcular o valor de qualquer carta.

Vais receber duas cartas e vais 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 outra 0
Note

Normalmente, os ases podem valer 1 ou 11, mas, por uma questão de simplicidade, vamos assumir que só podem valer 11.

Implementa o método Blackjack.parse_card, que recebe como argumento uma carta sob a forma de string. O método deve devolver o valor da carta como um número inteiro.

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

2. Nomear intervalos de valores.

A pontuação do jogador tem de ser categorizada em intervalos de valores. As pontuações do jogador calculam-se somando os valores das duas cartas do jogador. Os intervalos usados são:

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

Implementa o método Blackjack.card_range, que recebe duas cartas como argumentos, sob a forma de strings. O método deve devolver o nome do intervalo de valores em que as duas cartas se enquadram.

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

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

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

  • Ficar (S)
  • Pedir carta (H)
  • Dividir (P)
  • Ganhar automaticamente (W)

Embora ainda não seja a ideal, vais seguir a estratégia que o teu amigo Alex está a desenvolver, que é a seguinte:

  • Se tiveres um par de ases, tens sempre de os dividir.
  • Se tiveres um Blackjack (duas cartas cuja soma dá 21) e o dealer não tiver um ás, uma figura ou um dez, ganhas automaticamente. Se o dealer tiver alguma dessas cartas, tens de ficar e esperar que a outra carta seja revelada.
  • Se a soma das tuas cartas estiver no intervalo [17, 20], deves ficar sempre.
  • Se a soma das tuas cartas estiver no intervalo [12, 16], deves ficar sempre, a não ser que o dealer tenha um 7 ou mais, caso em que deves pedir carta sempre.
  • Se a soma das tuas cartas for 11 ou menos, deves pedir carta sempre.

Implementa o método Blackjack.first_turn, que recebe três cartas como argumentos, sob a forma de strings. O método deve devolver, como string, a decisão que deves tomar.

Blackjack.first_turn("ace", "ace", "two")
# => "P"
Editar via GitHub A ligação abre numa nova janela ou separador
Crystal Exercism

Estás pronto para começar Blackjack?

Inscreve-te no Exercism para aprenderes e dominares Crystal com 26 conceitos142 exercícios, e mentoria humana real, tudo grátis.