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
===)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
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
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
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
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
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
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
Neste exercício vamos simular o primeiro turno de um jogo de Blackjack.
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 |
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
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"
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:
Embora ainda não seja a ideal, vais seguir a estratégia que o teu amigo Alex está a desenvolver, que é a seguinte:
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"
Inscreve-te no Exercism para aprenderes e dominares Crystal com 26 conceitos142 exercícios, e mentoria humana real, tudo grátis.