Blackjack

Blackjack

Ejercicio de aprendizaje

Introducción

case (al que a menudo se hace referencia como switch en otros lenguajes) es una forma de expresión de control como if-else. case permite encadenar varias instrucciones if-else-if, puede ser más legible y permite construcciones potentes.

Un case se define con la palabra clave case seguida de una expresión opcional. Después, para cada caso se usa la palabra clave when seguida de una expresión que se compara con la expresión del case. La palabra clave when no debe ir indentada respecto a la palabra clave case. Después de la palabra clave when va el código que debe ejecutarse si la expresión del case coincide con la expresión del when. case permite una instrucción else opcional que se ejecuta si no coincide ningún otro caso.

La expresión del case se evalúa y luego se compara con cada expresión del when. La comparación se hace con el operador de subsunción de 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 subsunción de case (===)

El operador de subsunción de case (===) es un poco distinto del operador de igualdad (==). El operador comprueba si el lado derecho es un miembro del conjunto descrito por el lado izquierdo. Esto significa que sí importa dónde se coloca cada operando. Cómo funciona esto depende del tipo del lado izquierdo; por ejemplo, un Range comprobaría si el lado derecho está en el rango, o un Object comprobaría si el lado derecho es una instancia del Object.

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

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

case con varias expresiones

Los case permiten hacer coincidir varias expresiones en un solo caso, con cada valor posible separado por una coma. Ejecutará el código si coincide alguna de las expresiones. Esto puede ser útil para un solo caso con varios valores posibles.

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

case con rangos

Los case también pueden comprobar si un valor está en un rango. Esto se consigue usando un rango como expresión del when.

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

case sin expresión de case

Cuando no se necesita una expresión de case, es posible omitirla. Al hacerlo, cada expresión del when se evalúa por su valor de verdad. Y hace que se comporten como instrucciones 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 en una sola línea

Crystal permite instrucciones case de una sola línea. Esto se puede usar cuando tienes una instrucción simple de una sola línea. El when de una sola línea se escribe como when <expression> then <statement>. Y cuando se usa en la instrucción else, se escribe como else <statement>.

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

case con tipos

case permite hacer coincidencias con tipos. La comparación usará el operador is_a? para comprobar el tipo de la variable. Por ejemplo, esto permite una rama para cada tipo de un tipo unión.

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

Objeto implícito

case permite usar un objeto implícito. Esto permite, por ejemplo, que una expresión del when sea una llamada a un método sobre la expresión del case. Según si el método devuelve un valor verdadero o falso, el caso coincidirá o no.

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

Instrucciones

En este ejercicio vamos a simular el primer turno de una partida de Blackjack.

1. Calcula el valor de cualquier carta.

Recibirás dos cartas y podrás ver la carta boca arriba del crupier. Todas las cartas se representan mediante un string como «ace», «king», «three», «two», etc. Los valores de cada carta son:

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 other 0
Note

Normalmente, las cartas «ace» pueden tomar el valor de 1 o de 11, pero, por simplificar, supondremos que solo pueden tomar el valor de 11.

Implementa el método Blackjack.parse_card, que toma una carta como argumento de tipo string. El método debe devolver el valor de la carta como número entero.

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

2. Nombra los rangos de valores.

La puntuación del jugador se tiene que clasificar en rangos de valores. Las puntuaciones del jugador se calculan sumando los valores de las dos cartas del jugador. Los rangos que se utilizan son:

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

Implementa el método Blackjack.card_range, que toma dos cartas como argumentos de tipo string. El método debe devolver el nombre del rango de valores al que pertenecen las dos cartas.

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

3. Implementa la lógica de decisión para el primer turno.

En función de tus dos cartas y de la carta del crupier, existe una estrategia para el primer turno de la partida, en la que tienes las siguientes opciones:

  • Plantarse (S)
  • Pedir (H)
  • Dividir (P)
  • Ganar automáticamente (W)

Aunque todavía no es óptima, vas a seguir la estrategia que tu amigo Alex ha ido desarrollando, que es la siguiente:

  • Si tienes una pareja de cartas «ace», siempre debes dividirlas.
  • Si tienes un blackjack (dos cartas que suman un valor de 21) y el crupier no tiene un «ace», una figura ni un «ten», ganas automáticamente. Si el crupier tiene alguna de esas cartas, tendrás que plantearte y esperar a que se revele la otra carta.
  • Si tus cartas suman un valor dentro del rango [17, 20], siempre debes plantearte.
  • Si tus cartas suman un valor dentro del rango [12, 16], siempre debes plantearte a menos que el crupier tenga un 7 o más, en cuyo caso siempre debes pedir.
  • Si tus cartas suman 11 o menos, siempre debes pedir.

Implementa el método Blackjack.first_turn, que toma tres cartas como argumentos de tipo string. El método debe devolver como string la decisión que debes tomar.

Blackjack.first_turn("ace", "ace", "two")
# => "P"
Editar en GitHub El enlace se abre en una ventana o pestaña nueva
Crystal Exercism

¿Listo para empezar Blackjack?

Regístrate en Exercism para aprender y dominar Crystal con 26 conceptos142 ejercicios y mentoría humana real, todo gratis.