Os intervalos representam o conjunto de valores entre dois extremos.
Os tipos mais comuns que suportam intervalos são Int, Char e String.
Podem ser usados para muitas coisas, como criar rapidamente uma coleção, fatiar strings, verificar se um valor está dentro de um intervalo e iterar.
São criados com o operador de intervalo .. ou ... (inclusivo e exclusivo, respetivamente).
1..5 # A range containing 1, 2, 3, 4, 5
1...5 # A range containing 1, 2, 3, 4
A razão para existirem dois operadores de intervalo é permitir criar intervalos que incluem ou excluem o valor final, o que pode ser útil quando, por exemplo, trabalhas com índices que começam em zero.
Os intervalos também podem ser criados com o inicializador Range.
Range.new(1, 5) # A range containing 1, 2, 3, 4, 5
Quando crias um intervalo em Crystal com os operadores de intervalo .. ou ... e queres chamar um método ao intervalo, tens de envolver o intervalo em parênteses.
Isto acontece porque, caso contrário, o método será chamado sobre o segundo argumento do operador de intervalo.
(1..5).size # => 5
1..5.size # => Error: undefined method 'size' for Int32
Quando queres fatiar uma string, podes usar o operador de intervalo para obter uma substring. Ou seja, criando um intervalo com o índice inicial e final da substring.
"Hello World"[0..4] # => "Hello"
"Hello World"[6..10] # => "World"
Também podes usar índices negativos para obter a substring a partir do fim da string.
"Hello World"[-5..-1] # => "World"
"Hello World"[6..-4] # => "Wo"
Os intervalos têm, de facto, um conjunto de métodos que podes usar para trabalhar com eles. Por exemplo, estes métodos permitem obter a soma de todos os valores do intervalo ou verificar se o intervalo inclui um valor.
| Método | Descrição | Exemplo |
|---|---|---|
sum |
Devolve a soma de todos os valores do intervalo | (1..5).sum # => 15 |
size |
Devolve o tamanho do intervalo | (1..5).size # => 5 |
includes? |
Devolve true se o intervalo incluir o valor indicado; caso contrário, false
|
(1..5).includes?(3) # => true |
Um intervalo pode ser sem fim e sem início.
Um intervalo sem fim ou sem início tem o valor inicial ou final como nil, mas o nil pode ser omitido ao definir o intervalo.
Usar intervalos sem início e sem fim é útil quando queres, por exemplo, fatiar uma string desde o início ou até ao fim.
"Hello World"[0..] # => "Hello World"
"Hello World"[4..] # => "o World"
"Hello World"[..5] # => "Hello"
Se não for usado numa coleção, o intervalo sem fim pode dar origem a uma sequência sem fim, se não for usado com cuidado.
Os carateres podem ser usados em intervalos e permitem obter um intervalo de carateres entre dois carateres. Por exemplo, isto pode ser útil quando queres obter o alfabeto.
'a'..'z' # A range containing ['a', 'b', 'c', ..., 'z']
As strings também podem ser usadas em intervalos, o que permite obter um intervalo de strings entre duas strings.
Mas o seu comportamento é um pouco diferente do de Char quando se usam vários carateres num intervalo de strings.
O comportamento pode tornar-se confuso com intervalos de strings mais complexos, por isso usa-o com cuidado.
("aa".."az") # A range containing ["aa", "ab", "ac", ..., "az"]
Como entusiasta de xadrez, queres escrever a tua versão do jogo. Sim, já deve haver imensas implementações de xadrez disponíveis online, mas a tua vai ser única!
Começas por implementar um sistema básico de movimento para as peças.
O jogo de xadrez vai ser jogado num tabuleiro com oito casas de largura e oito casas de comprimento. As casas são identificadas por uma letra e um número.
O jogo vai ter de guardar as linhas do tabuleiro. As linhas são as filas do tabuleiro e estão numeradas de 1 a 8.
O jogo também vai ter de guardar as colunas do tabuleiro. As colunas são as filas verticais do tabuleiro e são identificadas pelas letras A a H.
Define as constantes Chess::RANKS e Chess::FILES, que guardam, respetivamente, o intervalo das linhas e das colunas.
Chess::RANKS
# => 1..8
Chess::FILES
# => 'A'..'H'
O jogo vai ter de verificar se uma casa é válida. Uma casa é válida se a linha e a coluna estiverem dentro dos intervalos das linhas e das colunas.
Define o método Chess.valid_square?, que recebe os argumentos rank, que contém um int com a linha, e file, que contém um char com a coluna.
O método deve devolver true se a linha e a coluna estiverem dentro do intervalo das linhas e das colunas, e devolver false caso contrário.
Chess.valid_square?(1, 'A')
# => true
O jogo vai ter de obter a alcunha do jogador. A alcunha é formada pelos dois primeiros carateres do primeiro nome do jogador e pelos dois últimos carateres do apelido. A alcunha deve ser escrita em maiúsculas.
Define o método Chess.nickname, que recebe os argumentos first_name, que contém uma string com o primeiro nome do jogador, e last_name, que contém uma string com o apelido do jogador.
O método deve devolver a alcunha do jogador como uma string em maiúsculas.
Chess.nickname("John", "Doe")
# => "JOOE"
O jogo vai ter de criar uma mensagem para uma jogada, a indicar que jogador se moveu para que casa. A mensagem deve usar a alcunha do jogador e a casa para onde ele se moveu. O jogo também tem de determinar se a jogada é válida, verificando se a coluna e a linha da casa estão dentro dos intervalos das colunas e das linhas.
Se a jogada for válida, a mensagem deve ser: "{nickname} moved to {square}"
Se a jogada for inválida, a mensagem deve ser: "{nickname} attempted to move to {square}, but that is not a valid square"
Define o método Chess.move_message, que recebe os argumentos first_name, que contém uma string com o primeiro nome do jogador, last_name, que contém uma string com o apelido do jogador, e square, que contém uma string com a casa para onde o jogador se moveu.
O método deve devolver a mensagem da jogada como uma string.
Chess.move_message("John", "Doe", "A1")
# => "JOOE moved to A1"
Inscreve-te no Exercism para aprenderes e dominares Crystal com 26 conceitos142 exercícios, e mentoria humana real, tudo grátis.