defmodule Games.GuessingGame do
use GenServer
@moduledoc """
Guess the number game
"""
def start() do
GenServer.start_link(__MODULE__, [], name: :guessing_game)
end
def current_score(pid) do
GenServer.call(pid, :current_score)
end
def play(pid) do
guess = prompt()
GenServer.call(pid, {:guess, guess})
end
@spec play_helper(String.t(), integer(), integer()) :: integer()
defp play_helper(answer, guess, attempts) do
cond do
guess == answer ->
IO.puts(IO.ANSI.green_background() <> "Correct! You win!!!" <> IO.ANSI.reset())
5
attempts == 0 ->
IO.puts(IO.ANSI.red_background() <> "You lose! the answer was #{answer}" <> IO.ANSI.reset())
attempts > 0 and guess < answer ->
IO.puts(IO.ANSI.cyan_background() <> "Too Low!" <> IO.ANSI.reset())
play_helper(answer, prompt(), attempts - 1)
attempts > 0 and guess > answer ->
IO.puts(IO.ANSI.magenta_background() <> "Too High!" <> IO.ANSI.reset())
play_helper(answer, prompt(), attempts - 1)
end
end
defp prompt() do
IO.gets(IO.ANSI.reset() <> "Guess a number between 1 and 10: ")
|> String.trim()
|> String.to_integer()
end
def init(_init_args) do
{:ok, 0}
end
def handle_call(:current_score, _from, score) do
{:reply, score, score}
end
def handle_call({:guess, guess}, _from, score) do
updated_score = score + play_helper(Enum.random(1..10), guess, 5)
{:reply, updated_score, updated_score}
end
end
I am trying to write the above guessing game. When playing first time, the prompt waits w/o timing out because the call hasn’t been made to GenServer yet. In the next attempt though it times out if response is not provided within 5 seconds.
I want the subsequent calls also to block until the user has provided an answer. I am not sure how to refactor this or use some option with GenServer for it to block.