So the task was:

To build from scratch, the game Rock Paper Scissors in ruby from what I have learnt from the course so far.

This is the first time I have essentially started with a blank editor and written my own code to achieve a game that is RPS. I started by writing some psuedo code of how I thought it worked logically.

  • User chooses an option of P/R/S
  • comp selects one at random
  • a comparison is made
  • the result is output
  • play again?

There were a couple of things I was unsure of at the start but for the most part I was confident I could do it without having to refer to the solution video and the solution code which I’ll post at the end of this post.

I was unsure of two things:

  1. How to get the computer to randomly select one of the three options
  2. How I would take a letter from the user using the gets.chomp method and compare it to the computers random value.

For my first problem I simply googled ‘how do I randomly select an array element in ruby’ and stackoverflow held the answer using the .sample method on the array.

The second problem I assigned user input using gets.chomp to a variable called ans and then ran a conditional statement on its value and depending on the statement assigned a new variable called users_choice to position in the objects array that held the 3 options. Hopefully the code will make this a little clearer.

 1 require 'pry'
 2 
 3 def say(msg)
 4   puts "--- #{msg} ---"
 5 end
 6 
 7 objects = %w(Paper Rock Scissors)
 8 again = 'y'
 9 
10 while again == 'y'
11 
12   puts "Choose One: (P/R/S)"
13   ans = gets.chomp
14   ans.upcase!
15 
16     while ans != 'P' && ans != 'R' && ans != 'S'
17       puts "Choose One: (P/R/S)"
18       ans = gets.chomp
19     end
20 
21     if ans == "P"
22       users_choice = objects[0]
23     elsif ans == "R"
24       users_choice = objects[1]
25     else
26       users_choice = objects[2]
27     end
28     
29 
30   comp = objects.sample
31   say("You chose #{users_choice}")
32   say("Computer chose #{comp}")
33 
34 
35     if users_choice == comp  
36       puts "You picked #{users_choice} and computer picked #{comp}"
37       puts "its a draw!"
38     elsif
39       users_choice == "Paper" && comp == "Rock"
40       puts "#{users_choice} covers #{comp}"
41       puts "You win!"
42     elsif users_choice == "Paper" && comp == "Scissors"
43       puts "#{comp} cuts #{users_choice}"
44       puts "You lose!"
45     elsif users_choice == "Rock" && comp == "Paper"
46       puts "#{comp} covers #{users_choice}"
47       puts "You lose!"
48     elsif users_choice == "Rock" && comp == "Scissors"
49       puts "#{users_choice} blunts #{comp}"
50       puts "You win!"
51     elsif users_choice == "Scissors" && comp == "Paper"
52       puts "#{users_choice} cuts #{comp}"
53       puts "You win!"
54     elsif users_choice == "Rock" && comp == "Scissors"
55       puts "#{comp} blunts #{users_choice}"
56       puts "You lose!"
57     end
58 
59 puts "Play again? (Y/N)"
60 again = gets.chomp
61 
62 end

…and there we have it, a fully working ruby program that I built from scratch! This feels like a real landmark and I’m going to celebrate with a lovely cuppa before checking the solution code in case it puts my effort to shame.

The solution

I’ll concentrate on sections of the solution which do the same thing differently:

I stored the options in an array whereas the solution uses a hash in a constant. Also I used a while loop to check the user input matched the required input whereas the solution uses begin end until:

CHOICES = {'p' => 'Paper', 'r' => 'Rock', 's' => 'Scissors'}

loop do
  
  # player picks
  begin 
    puts "Pick one: (p/r/s)"
    player_choice = gets.chomp.downcase
  end until CHOICES.keys.include?(player_choice)

end

Next, the computers choice is declared in a similar way to how I did it using the sample method:

computer_choice = CHOICES.keys.sample

The above uses the keys method which returns an array of keys then uses the sample method to get a key chosen at random.

Now that the player and computer choices are known, the comparison can begin and this is the biggest difference between the two solutions. The solution still uses an if else but it uses fewer steps than I did and extracts a large part into a method. I much prefer this version to mine where I effectively hard coded each outcome.

def display_winning_message(winning_choice)
  case winning_choice
  when 'p'
    puts "Paper wraps Rock!"
  when 'r'
    puts "Rock smashes Scissors!"
  when 's'
    puts "Scissors cuts Paper!"
  end
end

if player_choice == computer_choice
  puts "It's a tie!"
elsif (player_choice == 'p' && computer_choice == 'r') || 
(player_choice == 'r' && computer_choice == 's') || 
(player_choice == 's' && computer_choice == 'p')
  display_winning_message(player_choice)
else
  display_winning_message(computer_choice)
  puts "Computer won!"
end

Finally the player is asked if he/she wants to play again:

puts "Play again? (y/n)"
break if gets.chomp.downcase != 'y'

The solution code in full:

puts "Welcome to Paper Rock Scissors"

CHOICES = {'p' => 'Paper', 'r' => 'Rock', 's' => 'Scissors'}

loop do
  
  # player picks
  begin 
    puts "Pick one: (p/r/s)"
    player_choice = gets.chomp.downcase
  end until CHOICES.keys.include?(player_choice)

  # computer picks
  computer_choice = CHOICES.keys.sample

def display_winning_message(winning_choice)
  case winning_choice
  when 'p'
    puts "Paper wraps Rock!"
  when 'r'
    puts "Rock smashes Scissors!"
  when 's'
    puts "Scissors cuts Paper!"
  end
end

if player_choice == computer_choice
  puts "It's a tie!"
elsif (player_choice == 'p' && computer_choice == 'r') || 
(player_choice == 'r' && computer_choice == 's') || 
(player_choice == 's' && computer_choice == 'p')
  display_winning_message(player_choice)
  puts "YOU WIN!!"
else
  display_winning_message(computer_choice)
  puts "Computer won!"
end

puts "Play again? (y/n)"
break if gets.chomp.downcase != 'y'

end

puts "Good Bye o/"

Thanks to:

Brandon who is one of the immensely helpful teaching assistants at Tealeaf for checking my code, suggesting little improvements and assuring me the different solutions doesn’t always mean a better solution and to Vic for checking my grammar!