Created
November 26, 2024 20:05
-
-
Save BSN4/b2acac15113d80e6edcb93f53f2ddd6f to your computer and use it in GitHub Desktop.
rock_paper_scissors_context.ex
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
defmodule RPS do | |
defmodule Score, do: defstruct player: 0, computer: 0 | |
defmodule Context do | |
defstruct [ | |
score: %Score{}, | |
rounds_to_play: 3, | |
valid_moves: [:rock, :paper, :scissors], | |
win_conditions: %{rock: :scissors, paper: :rock, scissors: :paper}, | |
io: IO | |
] | |
end | |
def play(rounds \\ 3) do | |
%Context{rounds_to_play: rounds} | |
|> Stream.iterate(&play_round/1) | |
|> Enum.at(rounds) | |
|> announce_winner() | |
|> maybe_play_again() | |
end | |
defp play_round(ctx) do | |
with {:ok, player} <- get_move(ctx), | |
computer = get_computer_move(ctx) do | |
ctx.io.puts("Computer chose: #{computer}") | |
winner = determine_winner(ctx, player, computer) | |
ctx.io.puts(format_result(winner, player, computer)) | |
update_score(ctx, winner) | |
else | |
{:error, msg} -> | |
ctx.io.puts(msg) | |
play_round(ctx) | |
end | |
end | |
defp get_move(ctx) do | |
case ctx.io.gets("Enter move (rock/paper/scissors): ") |> String.trim() |> String.downcase() do | |
"rock" -> {:ok, :rock} | |
"paper" -> {:ok, :paper} | |
"scissors" -> {:ok, :scissors} | |
_ -> {:error, "Invalid move"} | |
end | |
end | |
defp get_computer_move(ctx) do | |
Enum.random(ctx.valid_moves) | |
end | |
defp determine_winner(ctx, player, computer) do | |
cond do | |
player == computer -> :draw | |
ctx.win_conditions[player] == computer -> :player | |
true -> :computer | |
end | |
end | |
defp format_result(:draw, move, _), do: "Draw! Both threw #{move}" | |
defp format_result(:player, player_move, computer_move), do: "You won with #{player_move} against #{computer_move}" | |
defp format_result(:computer, player_move, computer_move), do: "Computer won with #{computer_move} against #{player_move}" | |
defp update_score(ctx, :player) do | |
%{ctx | score: %{ctx.score | player: ctx.score.player + 1}} | |
end | |
defp update_score(ctx, :computer) do | |
%{ctx | score: %{ctx.score | computer: ctx.score.computer + 1}} | |
end | |
defp update_score(ctx, :draw), do: ctx | |
defp announce_winner(ctx) do | |
%Score{player: p, computer: c} = ctx.score | |
ctx.io.puts("\nFinal Score - You: #{p}, Computer: #{c}") | |
ctx.io.puts(if p > c, do: "You win!", else: if(p < c, do: "Computer wins!", else: "Draw!")) | |
ctx | |
end | |
defp maybe_play_again(ctx) do | |
if String.starts_with?(ctx.io.gets("\nPlay again? (y/n): ") |> String.downcase(), "y") do | |
play(ctx.rounds_to_play) | |
else | |
ctx.io.puts("Thanks for playing!") | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment