Increment variables within a method? - ruby

I'm trying to build a rock, paper, scissors game. Could someone please tell me or point me in the right direction of where I'm going wrong with this code?
I want the players_score and cpu_score variables to increment by 1 each time either one wins a round.
choice = ["rock", "paper", "Scissors"]
players_score = 0
cpu_score = 0
def win_lose(a,b,c,d)
if a == "rock" && b == "scissors"
c+=1
puts "YOU WIN!!"
elsif a == "scissors" && b == "rock"
d+=1
puts "YOU LOSE!!"
elsif a =="paper" && b == "rock"
c+=1
puts "YOU WIN!!"
elsif a =="rock" && b == "paper"
d+=1
puts "YOU LOSE!!"
elsif a == "scissors" && b == "paper"
c+=1
puts "YOU WIN!!"
elsif a == "paper" && b == "scissors"
d+=1
puts "YOU LOSE!!"
else a == b
puts "Its a Draw this time!!"
end
end
while players_score < 2 && cpu_score < 2
print "Lets play. Plese choose rock, paper or scissors: "
players = gets.chomp.downcase
puts "You have #{players}"
cpu = choice.sample.downcase
puts "Computer has #{cpu}"
win_lose(players, cpu, players_score, cpu_score)
puts "scores are player #{players_score} , cpu #{cpu_score}"
end

Return a value from win_lose, and use that to determine increment the variable, e.g.:
def win_lose(a,b,c,d)
if a == "rock" && b == "scissors"
c+=1
winner = 'player'
elsif a == "scissors" && b == "rock"
d+=1
winner = 'computer'
# [.. etc ..]
else a == b
winner = 'draw'
end
return winner
end
player_score = 0
cpu_score = 0
choice = ["rock", "paper", "Scissors"]
while players_score < 2 && cpu_score < 2
print "Lets play. Plese choose rock, paper or scissors: "
players = gets.chomp.downcase
puts "You have #{players}"
cpu = choice.sample.downcase
puts "Computer has #{cpu}"
winner = win_lose(players, cpu, players_score, cpu_score)
if winner == 'player'
player_score += 1
puts "YOU WIN!!"
elsif winner == 'computer'
cpu_score += 1
puts "YOU LOSE!!"
else
puts "It's a draw"
end
puts "scores are player #{players_score} , cpu #{cpu_score}"
end
As you can see, this also allows you to not repeat the same "YOU WIN!!" sentence over and over again. I moved that outside the win_lose function so that this function does only one thing: determine the winner or loser, rather than two things: determine the winner or loser, and inform them of this.
This distinction is perhaps not important for such a small program, but as your programs grow it will be critical to keep your program understandable.

Related

Ruby (Rock, Paper, Scissors)

Hey I am new to ruby and I have sat for a long time trying to find out what I've done wrong in this code, there isn't any error but it isn't giving me my desired output as a normal game of rock paper scissors.
Here is my code:
puts "Rock, Paper or Scissors"
choice = gets.chomp
cchoice = ["Rock", "Paper","Scissors"]
comp = rand(1..3)
won = false
puts "Computer chose #{cchoice[comp]}"
if (choice == "Rock")
if (comp == 2)
won = false
end
if (comp == 3)
won = true
end
elsif (choice == "Paper")
if (comp == 3)
won = false
end
if (comp == 1)
won = true
end
elsif (choice == "Scissors")
if (comp == 1)
won = false
end
if (comp == 2)
won = true
end
else
puts "I dont know what that means so-"
end
if (won)
puts "YOU WON!!!"
else
puts "You lost.."
end
Thanks for any help!
The rules of rock, paper, scissors can be expressed as a simple hash:
conditions = {
"Rock" => "Scissors",
"Paper" => "Rock",
"Scissors" => "Paper"
}
So you can simply check if one player won over the other with:
if conditions[player_1] == player_2
puts "Player one wins!"
elsif player_1 == player_2
puts "Its a draw!"
else
puts "Player two wins!"
end
This is far less complex then a tree of nested if/else statements.
conditions = {
"Rock": "Scissors",
"Paper": "Rock",
"Scissors": "Paper"
}
puts "Rock, Paper or Scissors"
choice = gets.chomp.capitalize
cchoice = conditions.keys.sample
puts "Computer chose #{ cchoice }"
if conditions[choice] == cchoice
puts "You won!"
elsif cchoice == choice
puts "Its a draw."
elsif conditions[cchoice] == choice
puts "You lost."
else
puts "#{choice} is not a valid option"
end
This covers the four potential outcomes which are:
win
loss
draw
bad input (this could also be handled with controll flow like break/throw/catch)
Also instead of rand you can use Array#sample to select a random element from the keys of the hash which avoids the need to use array indices.
Your random number generator generates numbers between 1-3, it should be between 0-2 since you are trying to index a list
comp = rand(0..2)
Also change the comparison in the if clause to reflect the above change,
Another thing you might have forgot is the draw condition (if both select the same thing)

How to have ruby pick randomly from an array [duplicate]

This question already has answers here:
How do I pick randomly from an array?
(7 answers)
Closed 4 years ago.
Im pretty new to programming and I'm trying to make a basic rock paper scissors program.
I've already made this program using 1 = rock, 2 = paper, 3 = scissors. but now I want to try doing it with actual words instead of numbers. How can I make ruby choose randomly from my array, mine?
Thanks!
mine = ["Rock", "Paper", "Scissors"]
mine.sample(1 + rand(mine.count))
puts 'Write your choice, Rock, Paper, or Scissors'
yours = gets.chomp.to_s
if yours == "Rock"
puts 'Your choice is Rock'
elsif yours == "Paper"
puts 'Your choice is Paper'
else yours == "Scissors"
puts 'Your choice is Scissors'
end
puts "--------------------------"
if mine == "Rock"
puts 'Computer: My choice is Rock'
elsif mine == "Paper"
puts 'Computer: My choice is Paper'
else mine == "Scissors"
puts 'Computer: My choice is Scissors'
end
print 'Computer: My choice was: '
print mine
puts
if mine == "Rock" && yours == "Paper"
puts "==========="
puts "Paper Wins!"
puts "==========="
elsif mine == "Paper" && yours == "Rock"
puts "==========="
puts "Paper Wins!"
puts "==========="
elsif mine == "Paper" && yours == "Scissors"
puts "=============="
puts "Scissors Wins!"
puts "=============="
elsif mine == "Scissors" && yours == "Paper"
puts "=============="
puts "Scissors Wins!"
puts "=============="
elsif mine == "Scissors" && yours == "Rock"
puts "=========="
puts "Rock Wins!"
puts "=========="
elsif mine == "Rock" && yours == "Scissors"
puts "=============="
puts "Rock Wins!"
puts "=============="
else
puts "======================"
puts "It's a tie! TRY AGAIN!"
puts "======================"
end
You can use sample:
[1, 2, 3].sample #=> 1
[1, 2, 3].sample(2) #=> [3, 1]
Documentation

RPS Showing Up As Draw Every time

Earlier I asked about adding points to a RPS game I created, that problem is fixed, but now I have a new problem.. Every time the user rolls for their item (rock, paper, or scissors) it's a draw. I've tried adding a percentage to the array 33.5% for two and 33% for one which adds to 100 and it still comes up as a draw every time.
def welcome
puts "Welcome to Rock, Paper, Scissors. To begin press 'S'.
To learn how to play press 'I'. To quit the game press 'Q'"
input = gets.chomp
if input =~ /s/i
start_game
elsif input =~ /i/i
instructions
else
exit
end
end
def start_game
start_points_P1 = 0
start_points_P2 = 0
choice = ['Rock', 'Paper', 'Scissors']
choice2 = ['Rock', 'Paper', 'Scissors']
player1 = choice.sample
player2 = choice2.sample
puts "Press 'R' to roll for Player 1"
input = gets.chomp!
puts "Player 1 has recieved #{player1}"
puts "Press 'E' to roll for Player 2!"
input = gets.chomp!
puts "Player 2 has recieved #{player2}"
if player1 == player2
puts "Draw!"
start_game
elsif player1 == 'Paper' && player2 == 'Scissors'
start_points_P2 += 10
puts "Player 2 has won with #{player2}. You now have #{start_points_P2} points and opponent has #{start_points_P1} points"
elsif player1 == 'Scissors' && player2 == 'Paper'
start_points_P1 += 10
puts "Player 1 has won with #{player1}. You know have #{start_points_P1} points and opponent has #{start_points_P2} points"
elsif player1 == 'Rock' && player2 == 'Paper'
start_points_P2 += 10
puts "Player 2 has won with #{player2}. You now have #{start_points_P2} points and opponent has #{start_points_P1} points"
elsif player1 == 'Paper' && player2 == 'Rock'
start_points_P1 += 10
puts "Player 1 has won with #{player1}. You know have #{start_points_P1} points and opponent has #{start_points_P2} points"
elsif player1 == 'Scissors' && player2 == 'Rock'
start_points_P2 += 10
puts "Player 2 has won with #{player2}. You now have #{start_points_P2} points and opponent has #{start_points_P1} points"
elsif player1 == 'Rock' && player2 == 'Scissors'
start_points_P1 += 10
puts "Player 1 has won with #{player1}. You know have #{start_points_P1} points and opponent has #{start_points_P2} points"
end
end
welcome
Am I missing something here, why does it keep showing up as a draw if I have set the players into separate arrays and only called .sample once?

Ruby Rock, Paper, Scissors

Im having an issue with the score updater for this rock, paper, scissors game I have to create for my ruby class. The purpose of this assignment is to have the user input a choice, the computer makes a random choice as well using "rand", and whoever wins the round has a score updated that is displayed at the end of each round. The problem im running into is that the counter only updates using the first if statement. The program works up to the point that it is able to randomly select the computer choice and it saves the users response as well. So all the code is fine up to where the score updater is used. Any assistance would be highly appreciated.
human_score = 0.0
comp_score = 0.0
while true
print "Lets play rock,paper,scissors", "\n"
print "Do you choose rock, paper, or scissors?", "\n"
choice = STDIN.gets.chomp
comp = rand(3)
if comp == 1
comp_choice = "rock"
elsif comp == 2
comp_choice = "paper"
else
comp_choice = "scissors"
end
print "Computer picked: ", comp_choice, "\n"
print "You picked: ", choice, "\n"
if human_choice = "rock" && comp_choice = "rock"
comp_score += 0.5
human_score += 0.5
print "The result is a tie", "\n"
elsif human_choice = "rock" && comp_choice = "paper"
comp_score += 1
print "Computer wins", "\n"
elsif human_choice = "rock" && comp_choice = "scissors"
human_score += 1
print "You win", "\n"
elsif human_choice = "paper" && comp_choice = "rock"
human_score += 1
print "You win", "\n"
elsif human_choice = "paper" && comp_choice = "paper"
comp_score += 0.5
human_score += 0.5
print "Its a tie", "\n"
elsif human_choice = "paper" && comp_choice = "scissors"
comp_score += 1
print "Computer wins", "\n"
elsif human_choice = "scissors" && comp_choice = "rock"
comp_score += 1
print "Computer wins"
elsif human_choice = "scissors" && comp_choice = "paper"
human_score += 1
print "You win"
else human_choice = "scissors" && comp_choice = "scissors"
human_score += 0.5
comp_score += 0.5
print "Its a tie"
end
print "The computers score is: ", comp_score, "\n"
print "Your score is: ", human_score, "\n"
end
You are reassigning the value of your variables instead of checking for equality.
Your version:
if human_choice = "rock" && comp_choice = "rock"
This sets the value of human_choice to "rock" and same with comp_choice. It will always be true.
Correct version:
if human_choice == "rock" && comp_choice == "rock"
Also, you are assigning the value read from the keyboard to choice
choice = STDIN.gets.chomp
and you are using human_choice to validate the cases.
Meditate on this:
human_score = 0.0
comp_score = 0.0
while true
puts "Lets play rock, paper, scissors"
puts "Do you choose rock, paper, or scissors?"
human_choice = STDIN.gets.chomp
comp_choice = %w[scissors rock paper][rand(3)]
puts "Computer picked: #{ comp_choice }"
puts "You picked: #{ human_choice }"
msg = case [human_choice, comp_choice]
when ['rock', 'rock'], ['paper', 'paper'], ['scissors', 'scissors']
comp_score += 0.5
human_score += 0.5
'The result is a tie'
when ['rock', 'scissors'], ['paper', 'rock'], ['scissors', 'paper']
human_score += 1
'You win'
when ['paper', 'scissors'], ['scissors', 'rock'], ['rock', 'paper']
comp_score += 1
'Computer wins'
end
puts msg
puts "The computer's score is: #{ comp_score }"
puts "Your score is: #{ human_score }"
end
It's written using idiomatic Ruby.

Ruby - rock paper scissor game using While, if/else statements, player vs computer

$player_count = 0
$computer_count = 0
what_to_include = %w{r p s}
paper = "p"
rock = "r"
scissors = "s"
def computer_input
computer = rand(3)
if computer == 0
computer = "p"
elsif computer == 1
computer = "r"
else
computer = "s"
end
end
while true
puts "Player Score: #{$player_count}, \tComputer Score: #{$computer_count}"
print "Choose rock (r), paper (p), or scissors (s): "
player_input = gets.chomp.downcase
if player_input == rock && computer_input == scissors
puts "Player chose rock. \nComputer chose scissors."
puts "Rock beats scissors, player wins the round."
$player_count += 1
elsif player_input == scissors && computer_input == paper
puts "Player chose scissors. \nComputer chose paper."
puts "Scissors beat paper, player wins the round."
$player_count += 1
elsif player_input == paper && computer_input == rock
puts "Player chose paper. \nComputer chose rock"
puts "Paper beats rock, player wins the round."
$player_count += 1
elsif computer_input == rock && player_input == scissors
puts "Player chose scissors. \nComputer chose rock."
puts "Rock beats scissos, Computer wins the round"
$computer_count += 1
elsif computer_input == scissors && player_input == paper
puts "Player chose paper. \nComputer chose scissors."
puts "Scissors beats paper, Computer wins the round"
$computer_count += 1
elsif computer_input == paper && player_input == rock
puts "Player chose rock. \nComputer chose paper."
puts "Paper beats rock, Computer wins the round"
$computer_count += 1
# elsif player_input == computer_input
# puts "Player chose #{player_input},\n Computer chose #{computer_input}"
# puts "Tie, choose again" #tried with this but returns r, s, p instead of word
elsif player_input == rock && computer_input == rock ||
player_input == paper && computer_input == paper ||
player_input == scissors && computer_input == scissors
puts "Player chose rock. \nComputer chose rock."
puts "Tie, choose again"
end
if player_input.include?("abcdefghijklmnoqtuvxzy")
puts "Invalid entry, try again."
end
if $player_count == 2
puts "Player wins!"
break
elsif $computer_count == 2
puts "Computer wins!"
break
end
end
ok, I am new to this, and i understand there is a better way of writing a rock paper scissors with less typing and better methods. I'm just not there yet. so bear with me.
The code works but sometimes when i enter "r", "p", "s" it returns nothing, or "Invalid entry, try again." I have tried entering ranges
if player_input = ["a".."o"].to_s in case the player's input was anything else than the commands for the game. but still. I tried the include? method
can anyone tell me how to work only the r, p, s. and give "Invalid entry, try again" for everything else? in this code.
Loop with Conditional Break
One way to do this is with a loop that breaks only when you have valid input. For example:
loop do
print "Choose rock (r), paper (p), or scissors (s): "
player_input = gets.chomp.downcase
break if player_input =~ /^[rps]$/
puts "Invalid entry, try again."
end
There are certainly other ways to do this, and more idiomatic ways, too. However, this should address your specific question without too much refactoring.
The =~ is testing for a regular expression in Ruby. Anything in between (2) slashes... /^[rps]$/ is a regular expression.
http://www.ruby-doc.org/core-2.1.3/Regexp.html
^ Good information there on regular expressions.
Here's a more compact and Ruby-like way to write the game.
ENTRY_TO_SYM = { 'p'=>:PAPER, 'r'=>:ROCK, 's'=>:SCISSORS }
VALID_ENTRIES = ENTRY_TO_SYM.keys
COMPUTER_CHOICES = ENTRY_TO_SYM.values
# WINNERS and LOSERS from the player's perspective, the first value of each
# pair being the player's choice, the second, the computer's choice.
WINNERS = [[:SCISSORS, :PAPER], [:PAPER, :ROCK], [:ROCK, :SCISSORS]]
LOSERS = WINNERS.map { |i,j| [j,i] }
.
class RockPaperScissors
def initialize
#player_score = #computer_score = #ties = 0
end
def play(winning_score)
while #player_score < winning_score && #computer_score < winning_score
puts "Player score: #{#player_score}, " +
"Computer score: #{#computer_score}, Ties: #{#ties}"
player = player_choice
computer = COMPUTER_CHOICES.sample
puts "\nPlayer chooses #{player.to_s}"
puts "Computer chooses #{computer.to_s}"
case player_outcome [player, computer]
when :WIN
puts "#{player.to_s} beats #{computer.to_s}, player wins the round"
#player_score += 1
when :LOSE
puts "#{computer.to_s} beats #{player.to_s}, computer wins the round"
#computer_score += 1
else
puts "Tie, choose again"
#ties += 1
end
end
puts "\nFinal score: player: #{#player_score}, " +
"computer: #{#computer_score} (ties: #{#ties})"
puts (#player_score == 2) ? "Player wins!" : "Yea! Computer wins!"
end
.
private
def player_choice
loop do
print "Choose rock (r), paper (p) or scissors (s): "
choice = gets.chomp.downcase
return ENTRY_TO_SYM[choice] if ENTRY_TO_SYM.key?(choice)
puts "That entry is invalid. Please re-enter"
end
end
def player_outcome(plays)
return :WIN if WINNERS.include?(plays)
return :LOSE if LOSERS.include?(plays)
:TIE
end
end
.
RockPaperScissors.new.play(3)
A few things to note:
I've relegated the getting of a valid entry from the player to a separate method, where I use Kernel#loop (generally preferred to while true, etc.) for looping.
I've used symbols to represent both choices and outcomes.
I used the method Array#sample to obtain the computer's random choice.
I've used arrays to represent winning and losing pairs of choices (from the player's perspective).
Using too much || and if/elsif is really weird for this problem. You can do something much simpler like this:
# I inserted the logic here in this method, so we can always
# call the game
def rock_scissors_paper(user_choice)
options = ["rock", "scissors", "paper"]
computer_choice = options.sample
computer_index = options.index(computer_choice)
user_index = options.index(user_choice)
puts "The computer went with #{computer_choice}"
# Example:
# If user chooses Rock (0 - 1) and computer paper (2), computer WINS
# because options[-1] is... paper (whenever this is equal, computer wins)
# If user chooses Paper (2 - 1) and computer rock (0), user WINS (ELSE)
# And so on.
# Pay careful attention to how we checking against VALUES (-1 is the last guy!)
if options[user_index - 1] == options[computer_index]
puts "Computer wins the game!"
elsif computer_choice == user_choice
puts "It's a draw"
else
puts "You win the game"
end
end
# Display options to the users
puts "Rock, scissors, paper?"
user_choice = gets.chomp.downcase
# Run method
rock_scissors_paper(user_choice)
so i think the issue was that you needed to define the player like you did with the computer. i redid the assignment using the same things as you and it now seems to work. $player_count = 0
$computer_count = 0
def computer_input
computer = rand(3)
if computer == 0
computer = "p"
elsif computer == 1
computer = "r"
else
computer = "s"
end
end
def player_input
if player == "r"
player = "r"
elsif player == "p"
player = "p"
else player == "s"
player = "s"
end
end
while true
puts "Player Score: #{$player_count}, \tComputer Score: #{$computer_count}"
puts "Choose rock (r), paper (p), or scissors (s) "
player_input = gets.chomp
if player_input == "r" && computer_input == "s"
puts "Player chose rock. \nComputer chose scissors."
puts "Rock beats scissors, player wins the round."
$player_count += 1
elsif player_input == "s" && computer_input == "p"
puts "Player chose scissors. \nComputer chose paper."
puts "Scissors beat paper, player wins the round."
$player_count += 1
elsif player_input == "p" && computer_input == "r"
puts "Player chose paper. \nComputer chose rock"
puts "Paper beats rock, player wins the round."
$player_count += 1
elsif computer_input == "r" && player_input == "s"
puts "Player chose scissors. \nComputer chose rock."
puts "Rock beats scissos, Computer wins the round"
$computer_count += 1
elsif computer_input == "s" && player_input == "p"
puts "Player chose paper. \nComputer chose scissors."
puts "Scissors beats paper, Computer wins the round"
$computer_count += 1
elsif computer_input == "p" && player_input == "r"
puts "Player chose rock. \nComputer chose paper."
puts "Paper beats rock, Computer wins the round"
$computer_count += 1
elsif player_input == computer_input
puts "Tie, go again!"
else
puts "Invalid Entry"
end
if $player_count == 2
puts "Player wins!"
break
elsif $computer_count == 2
puts "Computer wins!"
break
end
end
Hope this helps!!

Resources