Powered by AppSignal & Oban Pro
Would you like to see your link here? Contact us

Rock Paper Scissors Genserver

rock_paper_scissors_genserver.livemd

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

Return Home Report An Issue

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"