Excelente clase!!!
0:00/18:30
Excelente clase!!!
Les comparto mi solución para aceptar palabras.
El juego considera aciertos y fallos por letra, no por palabra. Es decir, si ingresas una palabra con 5 letras, de las cuales ninguna está en la palabra a adivinar, entonces se te agotarían los intentos y pierdes el juego.
Una mejora sería no incluir letras repetidas en las listas ¨misses¨ y ¨matches¨, que actualmente ocurre cuando ingresas una palabra que tiene letras repetidas, como por ejemplo ¨Cachapa¨.
El código:
defmodule Hangman do
@moduledoc """
The famous Hangman game
"""
@doc """
Starts the game
"""
def start_game do
state = %{word: "hangman", misses: [], matches: [], limit: 5, mask: "_", completed?: false}
format_response(state)
end
@doc """
Lets the user to take a guess
"""
def take_a_guess(
guess_value,
%{limit: limit, completed?: false, matches: matches, misses: misses} = state
)
when limit > 0 do
repeated_values = matches ++ misses
guess_as_list =
guess_value
|> String.downcase()
|> String.graphemes()
|> Enum.filter(&(&1 not in repeated_values))
case guess_as_list do
[] ->
format_response(state, :err)
_ ->
guess_as_list
|> guess(state)
|> format_response()
end
end
def take_a_guess(_, state), do: format_response(state)
## Helpers
defp format_response(%{limit: limit, completed?: false} = state) when limit > 0 do
{mask_word(state), state}
end
defp format_response(%{limit: limit, word: word} = state) when limit > 0 do
{"You won, word was: #{word}", state}
end
defp format_response(%{word: word} = state) do
{"Game over, word was: #{word}", state}
end
defp format_response(state, :err) do
{"Please don't use repeated letters", state}
end
defp mask_word(%{matches: [], word: word, mask: mask} = _state) do
String.replace(word, ~r/./, mask)
end
defp mask_word(%{matches: matches, word: word, mask: mask} = _state) do
String.replace(word, ~r/[^#{to_string(matches)}]/, mask)
end
defp guess(guess_value, state) do
Enum.reduce(guess_value, state, fn curr, acc ->
%{word: word, matches: matches, misses: misses, limit: limit} = acc
if String.contains?(word, curr) do
matches = [curr | matches]
completed? = word |> String.graphemes() |> Enum.all?(&(&1 in matches))
%{acc | matches: matches, completed?: completed?}
else
%{acc | misses: [curr | misses], limit: limit - 1}
end
end)
end
end
quote do
end
Juan David Gaviria Agudelo
Excelente clase!!!
Ernesto Gabriel Mejía Montero
Les comparto mi solución para aceptar palabras.
El juego considera aciertos y fallos por letra, no por palabra. Es decir, si ingresas una palabra con 5 letras, de las cuales ninguna está en la palabra a adivinar, entonces se te agotarían los intentos y pierdes el juego.
Una mejora sería no incluir letras repetidas en las listas ¨misses¨ y ¨matches¨, que actualmente ocurre cuando ingresas una palabra que tiene letras repetidas, como por ejemplo ¨Cachapa¨.
El código:
defmodule Hangman do @moduledoc """ The famous Hangman game """ @doc """ Starts the game """ def start_game do state = %{word: "hangman", misses: [], matches: [], limit: 5, mask: "_", completed?: false} format_response(state) end @doc """ Lets the user to take a guess """ def take_a_guess( guess_value, %{limit: limit, completed?: false, matches: matches, misses: misses} = state ) when limit > 0 do repeated_values = matches ++ misses guess_as_list = guess_value |> String.downcase() |> String.graphemes() |> Enum.filter(&(&1 not in repeated_values)) case guess_as_list do [] -> format_response(state, :err) _ -> guess_as_list |> guess(state) |> format_response() end end def take_a_guess(_, state), do: format_response(state) ## Helpers defp format_response(%{limit: limit, completed?: false} = state) when limit > 0 do {mask_word(state), state} end defp format_response(%{limit: limit, word: word} = state) when limit > 0 do {"You won, word was: #{word}", state} end defp format_response(%{word: word} = state) do {"Game over, word was: #{word}", state} end defp format_response(state, :err) do {"Please don't use repeated letters", state} end defp mask_word(%{matches: [], word: word, mask: mask} = _state) do String.replace(word, ~r/./, mask) end defp mask_word(%{matches: matches, word: word, mask: mask} = _state) do String.replace(word, ~r/[^#{to_string(matches)}]/, mask) end defp guess(guess_value, state) do Enum.reduce(guess_value, state, fn curr, acc -> %{word: word, matches: matches, misses: misses, limit: limit} = acc if String.contains?(word, curr) do matches = [curr | matches] completed? = word |> String.graphemes() |> Enum.all?(&(&1 in matches)) %{acc | matches: matches, completed?: completed?} else %{acc | misses: [curr | misses], limit: limit - 1} end end) end end quote do end