No tienes acceso a esta clase

¡Continúa aprendiendo! Únete y comienza a potenciar tu carrera

Completando el proyecto con IEx y Mix

3/11
Recursos

Aportes 2

Preguntas 0

Ordenar por:

¿Quieres ver más aportes, preguntas y respuestas de la comunidad?

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