Comparing Beginner’s RPS Code to Advanced RPS Code
Table of Contents
Beginner’s Code
Beginner’s Code Pros
- Simple
- Easy to understand
- Short
Beginner’s Code Cons
- Unorganized
- Lacks modularization
- Many
if
/elsif
/else
statements
Beginner’s Analysis
It is common for beginners to use many repetitive statements when coding a simple Ruby app.
In this case, using many if
/elsif
/else
statements is typical beginner code formatting when programming a rock-paper-scissors game.
The beginner’s code might also show redundancy by programming more than what needs to be coded (this situation is different for advanced Ruby programmers).
Most beginners’ code lacks modularization and a solid code structure; thus making it very unorganized.
While beginners’ code might look simple and easy to understand, it is not always the most efficient.
In this particular case, the advanced code is longer and more confusing, though it has more modularization and professionalism attached to it (in some cases, it will actually run faster than the beginner’s code).
What Beginner’s Code Looks Like
% ruby beginner-rps.rb
options = ["rock", "paper", "scissors"]
computer_choice = options[rand(options.length)]
puts "What's your choice?"
puts "rock, paper, or scissors"
user_input = gets.chomp.downcase # read user input and convert to lower case
loop do
if (user_input == "rock" || user_input == "paper" || user_input == "scissors")
if (user_input == computer_choice)
puts "We got the same, let's keep playing!"
elsif (user_input == "rock" && computer_choice == "scissors")
puts "computer choice is: " + computer_choice + " , you win! :)"
elsif (user_input == "rock" && computer_choice == "paper")
puts "computer choice is: " + computer_choice + " ,computer wins :("
elsif (user_input == "paper" && computer_choice == "scissors")
puts "computer choice is: " + computer_choice + " ,computer wins :("
elsif (user_input == "paper" && computer_choice == "rock")
puts "computer choice is: " + computer_choice + " , you win! :)"
elsif (user_input == "scissors" && computer_choice == "rock")
puts "computer choice is: " + computer_choice + " ,computer wins :("
elsif (user_input == "scissors" && computer_choice == "paper")
puts "computer choice is: " + computer_choice + " , you win! :)"
else
puts "Invalid choice, enter Rock, Paper, or Scissors"
puts "What's your choice?"
user_input = gets.chomp.downcase
end
end
break
end
Advanced Code
Advanced Code Pros
- Organized
- Modularized
- Structured
Advanced Code Cons
- Long
- Hard to understand
Advanced Analysis
An advanced coder’s code could be longer or shorter than a beginner’s code.
Advanced code usually has seldom repetition and more subtle programming.
Advanced coders tend to shy away from many if
, elsif
, & else
statements. This is primarily due to the way an advanced coder thinks. One might replace multiple elsif
s with a case
statement –adding more structure and organization to the code–.
Subtlety is usually painted all over advanced ruby code. While this does make the code harder to understand, it certainly adds more structure professionalism to the code.
What Advanced Code Looks Like
% ruby advanced-rps.rb
#!/usr/bin/env ruby
=begin
|====================================|
| Req Ruby Ver | Req Ruby Gems Ver |
|--------------|---------------------|
| >= v2.0.0 | >= v2.6.0 |
|====================================|
=end
class PlayRockPaperScissorsGame
module RockPaperScissors
VERSION = "2.9.1"
end
# import the colorize gem
require "colorized_string"
ColorizedString.colors # import colors; ex: red, green, blue from colorize gem
ColorizedString.modes # import modes; ex: bold, italic, underline from colorize gem
module Constants
NTRY_TO_SYM = { # define entry to symbol (key to value)
'p' => :PAPER , 'paper' => :PAPER ,
'r' => :ROCK , 'rock' => :ROCK ,
's' => :SCISSORS, 'scissors' => :SCISSORS
}
VALID_ENTRIES = NTRY_TO_SYM.keys
COMPUTER_CHOICES = NTRY_TO_SYM.values
WINNERS = [
# format: player choice, computer choice
[:SCISSORS, :PAPER ],
[:PAPER , :ROCK ],
[:ROCK , :SCISSORS]
]
LOSERS = WINNERS.map { |player_choice,computer_choice| [computer_choice,player_choice] } # this will take the original WINNERS array and flip the symbols, thus returning a loss for the user/player
INIT_STRINGS = [
ColorizedString["You are about to enter a rock-paper-scissors best of 3 match."].colorize(:green),
ColorizedString["Press the return/enter key to continue..."].colorize(:green) ,
""
]
end
protected_methods :Constants
class << self # define a self calling method within the parent class
def continue(str1,str2,str3)
puts str1
print str2
gets # press enter or return to continue
puts str3
end
end
continue(Constants::INIT_STRINGS[0], Constants::INIT_STRINGS[1], Constants::INIT_STRINGS[2])
def initialize # initialize variables
@player_score = @computer_score = @ties = 0
end
def play(winning_score)
while @player_score < winning_score && @computer_score < winning_score
puts ColorizedString["Player score: #{@player_score}, "].colorize(:blue) +
ColorizedString["Computer score: #{@computer_score}, Ties: #{@ties}."].colorize(:blue)
player = PrivateMethods.player_choice
computer = Constants::COMPUTER_CHOICES.sample # chooses a "random" option
puts ColorizedString["\nPlayer chooses #{player.to_s.downcase}."].colorize(:blue)
puts ColorizedString["Computer chooses #{computer.to_s.downcase}."].colorize(:blue)
case PrivateMethods.player_outcome [player, computer]
when :WIN
puts ColorizedString["#{player.to_s.capitalize} beats #{computer.to_s.downcase}, player wins the round."].colorize(:red)
@player_score += 1 # @player_score = @player_score + 1
when :LOSE
puts ColorizedString["#{computer.to_s.capitalize} beats #{player.to_s.downcase}, computer wins the round."].colorize(:red)
@computer_score += 1
else
puts ColorizedString["Tie, choose again"].colorize(:red)
@ties += 1
end
end
puts ColorizedString["\nFinal score: player: #{@player_score}, "].colorize(:blue) +
ColorizedString["computer: #{@computer_score} (ties: #{@ties})."].colorize(:blue)
case PrivateMethods.final_outcome(@player_score, @computer_score)
when :WIN
puts ColorizedString["Player wins!"].colorize(:red)
when :LOSE
puts ColorizedString["Computer wins!"].colorize(:red)
else
puts ColorizedString["It's a tie!"].colorize(:red)
end
gets
end
module PrivateMethods
class << self
def player_choice
loop do
print ColorizedString["Choose: Rock (r), Paper (p), or Scissors (s): "].colorize(:green)
choice = gets.chomp.downcase
if Constants::NTRY_TO_SYM.key?(choice)
return Constants::NTRY_TO_SYM[choice]
elsif choice != Constants::VALID_ENTRIES
puts ColorizedString["That entry is invalid. Please re-enter."].colorize(:red)
else
return nil
end
end
end
def player_outcome(plays)
# plays = [player_choice, computer_choice]
return :WIN if Constants::WINNERS.include?(plays)
return :LOSE if Constants::LOSERS.include?(plays)
return :TIE if !:WIN | !:LOSE
end
def final_outcome(pl,co)
return :WIN if pl > co
return :LOSE if pl < co
# there will never be a tie for the final outcome due to the code in the play() method
end
end
end
private_methods :PrivateMethods
end
PlayRockPaperScissorsGame.new.play(2) # call the play method and pass in 3 (0, 1, 2) for the winning score