Percursos
/
Clojure
Clojure
/
Exercícios
/
Jogos de cartas
Jogos de cartas

Jogos de cartas

Exercício de aprendizagem

Introdução

Em Clojure, as listas são coleções, tal como as listas noutras linguagens. À semelhança de outras linguagens da família Lisp, o Clojure usa parênteses para representar listas.

As listas em Clojure podem ser criadas de duas formas. A função list pode criar uma lista, ou podes fazer quote a uma lista literal.

As listas são especiais porque o Clojure as trata como chamadas. Espera que a chamada comece com um operador, que geralmente é uma função. Os restantes itens da lista são considerados operandos, ou seja, tornam-se nos argumentos da função.

É este tratamento especial que o Clojure dá às listas que faz com que não possamos criar uma lista literal diretamente. Usar quote numa lista, ou o seu atalho ', indica que a lista não deve ser avaliada.

Ao contrário de algumas linguagens modernas, as listas em Clojure são heterogéneas, ou seja, podem conter vários tipos de itens, por exemplo, '(2 "a" "b" 3). Ao contrário de outros Lisps, uma lista vazia em Clojure é avaliada como verdadeira e não é equivalente a nil ou false.

Instruções

A Elyse está mesmo ansiosa por jogar um pouco de póquer (e outros jogos de cartas) durante a próxima viagem a Vegas. Como é grande fã de «auto-monitorização», quer criar umas pequenas funções que a ajudem nas tarefas de registo e pediu-te ajuda para pensar nelas.

1. Registar as rondas de póquer

A Elyse gosta especialmente de póquer e quer registar quantas rondas joga, bem como quais são essas rondas. Cada ronda tem o seu próprio número, e cada mesa mostra o número da ronda que está a ser jogada. A Elyse escolhe uma mesa e senta-se para jogar a primeira ronda. Tenciona jogar três rondas.

Implementa uma função rounds que recebe o número da ronda atual e devolve uma única list com essa ronda e as duas seguintes que aí vêm:

(rounds 27)
;;=> (27 28 29)

2. Manter todas as rondas no mesmo sítio

A Elyse jogou algumas rondas na primeira mesa, depois fez uma pausa e jogou mais algumas rondas numa segunda mesa... mas acabou com uma lista diferente para cada mesa! Quer juntar as duas listas, para poder registar todas as rondas de póquer no mesmo sítio.

Implementa uma função concat-rounds que recebe duas listas e devolve uma única list composta por todas as rondas da primeira list, seguida de todas as rondas da segunda list:

(concat-rounds '(27 28 29) '(35 36))
;;=> (27 28 29 35 36)

3. Encontrar rondas anteriores

A falar de algumas das rondas anteriores de póquer, outro jogador comenta como duas delas se desenrolaram de forma semelhante. A Elyse não tem a certeza se jogou essas rondas ou não.

Implementa uma função contains-round? que recebe dois argumentos: uma lista de rondas jogadas e um número de ronda. A função devolve true se a ronda estiver na lista de rondas jogadas, e false se não estiver:

(contains-round? '(27 28 29 35 36) 29)
;;=> true

(contains-round? '(27 28 29 35 36) 30)
;;=> false

4. Calcular a média dos valores das cartas

A Elyse quer experimentar um novo jogo chamado Black Joe. É parecido com o Black Jack, em que o objetivo é que as cartas da tua mão somem um valor alvo, mas no Black Joe o objetivo é que a média dos valores das cartas seja 7. A média obtém-se somando todos os valores das cartas e dividindo essa soma pelo número de cartas na mão.

Implementa uma função card-average que devolva o valor médio de uma mão de Black Joe.

(card-average '(5 6 7))
;;=> 6.0

5. Médias alternativas

No Black Joe, a rapidez é importante. A Elyse vai tentar encontrar uma forma mais rápida de calcular a média.

Pensou em duas formas de obter um número parecido com a média:

  • Calcular a média do primeiro e do último número da mão.
  • Usar a mediana (a carta do meio) da mão.

Implementa a função approx-average?, dado hand, uma lista com os valores das cartas na tua mão.

Devolve true se uma or ambas das estratégias acima referidas resultarem num número igual à média real.

Nota: O comprimento de todas as mãos é ímpar, para facilitar o cálculo da mediana.

(approx-average? '(1 2 3))
;;=> true

(approx-average? '(2 3 4 8 8))
;;=> true

(approx-average? '(1 2 3 5 9))
;;=> false

6. Mais técnicas de cálculo de médias

Intrigada com os resultados da sua experiência com médias, a Elyse pergunta-se se calcular a média das cartas nas posições pares em vez da média das cartas nas posições ímpares daria o mesmo resultado. Está na hora de outra função de teste!

Implementa uma função average-even-odd? que devolve um Boolean que indica se a média das cartas nos índices pares é igual à média das cartas nos índices ímpares.

(average-even-odd? '(1 2 3))
;;=> true

(average-even-odd? '(1 2 3 4))
;;=> false

7. Regras das rondas bónus

Em cada 11.ª mão do Black Joe há uma mão bónus com uma regra bónus: se a última carta que tiras for um Valete, duplicas o seu valor.

Implementa uma função maybe-double-last que recebe uma mão e verifica se a última carta é um Valete (11). Se a última carta for um Valete (11), duplica o seu valor antes de devolver a mão.

(maybe-double-last '(5 9 11))
;;=> '(5 9 22)

(maybe-double-last '(5 9 10))
;;=> '(5 9 10)
Editar via GitHub A ligação abre numa nova janela ou separador
Clojure Exercism

Estás pronto para começar Jogos de cartas?

Inscreve-te no Exercism para aprenderes e dominares Clojure com 12 conceitos105 exercícios, e mentoria humana real, tudo grátis.