Rock Paper Scissors Genserver
Mix.install([
{:kino, github: "livebook-dev/kino", override: true},
{:kino_lab, "~> 0.1.0-dev", github: "jonatanklosko/kino_lab"},
{:vega_lite, "~> 0.1.4"},
{:kino_vega_lite, "~> 0.1.1"},
{:benchee, "~> 0.1"},
{:ecto, "~> 3.7"},
{:math, "~> 0.7.0"},
{:faker, "~> 0.17.0"},
{:utils, path: "#{__DIR__}/../utils"},
{:tested_cell, git: "https://github.com/BrooklinJazz/tested_cell"}
])
Navigation
Rock Paper Scissors Genserver
So far we’ve created synchronous rock paper scissors game where each player needs to enter their guess into the same function at the same time.
Now, we’re going to use message passing to create a real-time rock paper scissors game with two players and a game server.
flowchart
P1[Player1]
P2[Player2]
G[GameServer]
G --> P1
G --> P2
The Game
server will store the current round, and the pids of the two players. Each Player
will store their win/loss/tie ratio.
flowchart
P1[Player1]
P2[Player2]
G[GameServer]
P1S[State]
P2S[State]
GS[State]
P1 --> P1S
P1 --> P2S
G --> GS
P1S --> P1W[wins]
P1S --> P1L[loses]
P1S --> P1T[ties]
P2S --> P2W[wins]
P2S --> P2L[loses]
P2S --> P2T[ties]
We’ll use message passing to have each Player
submit their choice to the Game
server. Once both players submit their
choice the Game
server should update the current round and send both players a message back to let them know if they won, lost, or tied.
flowchart
P1[Player1]
P2[Player2]
G[GameServer]
P1 --rock--> G
P2 --paper--> G
G --lose--> P1
G --win--> P2
The Player
server should then update it’s own win/lose/state.
We should be able to start a Player
server with Player.new/1
.
{:ok, player_pid} = Player.new()
The Game
module should be able to start a new game process and accept the two player processes for
player1 and player2.
{:ok, player1_pid} = Player.new()
{:ok, player2_pid} = Player.new()
{:ok, game_pid} = Game.start(player1_pid, player2_pid)
The Player
module should be able to choose either :rock
, :paper
, or :scissors
. This should
send a message to the Game
server.
Player.choose(game_pid, player1_pid, :rock)
:ok
When both players submit their choice, the Game
should update
it’s state, and send a message back to each player which should cause them to update their own state.
We should be able to see the current Game
information through the Game.stats/1
function.
And the current Player
information through the Player.stats/1
function.
Game.choose(game_pid, player1_pid, :rock)
:ok
Game.choose(game_pid, player2_pid, :scissors)
:ok
Game.stats(game_pid)
%{round: 2}
Player.stats(player1_pid)
%{wins: 1, ties: 0, loses: 0}
Player.stats(player2_pid)
%{wins: 0, ties: 0, loses: 1}
In the Elixir cell below, create the Game
and Player
GenServer modules.
defmodule Game do
end
defmodule Player do
end
Commit Your Progress
Run the following in your command line from the project folder to track and save your progress in a Git commit.
$ git add .
$ git commit -m "finish rock paper scissors genserver exercise"