I am learning Ruby and improving every day. I have question on how I can play a game with multiple words
Below RSPEC test passed because the game is played with one word
fit "is lost with a different set of incorrect guesses" do
guesses = ["ALPHA", "BETA", "GAMMA"]
input = StringIO.new(guesses.join("\n"))
game = Game.new(answers: ["RUBY"], input: input, output: output,
max_attempts: 3)
game.start
game_output_lines = output.string.split("\n").map(&:strip)
aggregate_failures do
expect(game_output_lines.size).to eq 9
expect(game_output_lines[2]).to eq "The answer is not ALPHA."
expect(game_output_lines[3]).to eq "Try again. Attempts left:
2"
expect(game_output_lines[4]).to eq "The answer is not BETA."
expect(game_output_lines[5]).to eq "Try again. Attempts left:
1"
expect(game_output_lines[6]).to eq "The answer is not GAMMA."
expect(game_output_lines[7]).to eq "You lost."
expect(game_output_lines[8]).to eq "Your final score: 0/1."
end
Below is the test that is failing because I have to play with multiple words. For clarity sake, once the "expect(game_output_lines[7]).to eq "You lost." I want to be able to replay the game so that "expect(game_output_lines[8]).to match(/^2/2. Guess a word from an anagram [OMEGA] {5}$/)" below will be possible
it "can be played with multiple words" do
guesses = ["ALPHA", "BETA", "GAMMA", "MEGA", "OMEGA"]
input = StringIO.new(guesses.join("\n"))
game = Game.new(answers: ["DELTA", "OMEGA"], input: input,
output: output,
max_attempts: 3)
game.start
game_output_lines = output.string.split("\n").map(&:strip)
aggregate_failures do
expect(game_output_lines.size).to eq 14
expect(game_output_lines[2]).to eq "The answer is not ALPHA."
expect(game_output_lines[3]).to eq "Try again. Attempts left:
2"
expect(game_output_lines[4]).to eq "The answer is not BETA."
expect(game_output_lines[5]).to eq "Try again. Attempts left:
1"
expect(game_output_lines[6]).to eq "The answer is not GAMMA."
expect(game_output_lines[7]).to eq "You lost."
expect(game_output_lines[8]).to match(/^2\/2. Guess a word from
an anagram [OMEGA]{5}$/)
expect(game_output_lines[9]).to eq "The answer is not MEGA."
expect(game_output_lines[10]).to eq "Try again. Attempts left:
2"
expect(game_output_lines[11]).to eq "Correct! The answer is
OMEGA."
expect(game_output_lines[12]).to eq "So far you have correctly
guessed 1 out of 2."
expect(game_output_lines[13]).to eq "Your final score: 1/2."
end
Below is the main code. The code is good for the first test but fails for the second test.
class Game
def initialize(answers:, input: $stdin, output: $stdout,
max_attempts: 3)
#answers = answers
#correct_answers = 0
#input = input
#max_attempts = 3
#output = output
end
def start
output.puts "Let's play a game. You will have to guess 1
anagram."
output.puts "1/1. Guess a word from an anagram #{answers[-1]}"
evaluate_user_guesses
end
def evaluate_user_guesses
guess = nil
current_attempt = 1
max_attempts_count = 3
guess_counts = 1
scores = 1
while guess != answers[-1] && current_attempt <= max_attempts
guess = input.gets.to_s.strip
if guess == answers[-1]
output.puts "Correct! The answer is #{answers[-1]}."
else
output.puts "The answer is not #{guess}."
end
if guess == answers[-1] && current_attempt <= max_attempts
output.puts "So far you have correctly guessed #
{guess_counts} out of #
{scores}."
return output.puts "Your final score: #{guess_counts}/#
{scores}."
elsif guess != answers[-1] && current_attempt < max_attempts
output.puts "Try again. Attempts left: #{max_attempts_count
-= 1}"
else
output.puts "You lost."
end
current_attempt += 1
end
output.puts "Your final score: #{guess_counts -= 1}/#
{scores}."
end
private
attr_reader :answers, :correct_answers, :input, :max_attempts,
:output
end
How can i make the second test pass?
Thanks
answers is an array which can contain multiple elements, but you only ever take answers[-1] into account, i.e. the last element:
if guess == answers[-1] # <- compares guess to last element
output.puts "Correct! The answer is #{answers[-1]}."
Instead, you have to compare guess to all elements in answers, e.g. via include?:
if answers.include?(guess)
output.puts "Correct! The answer is #{guess}."
In addition, you probably want to delete the correct guess from answers so the player can't "guess" the same word over and over again:
if answers.include?(guess)
output.puts "Correct! The answer is #{guess}."
answers.delete(guess)
You still have to adjust some other parts of your code, but this sould point you in the right direction.
Related
I tried to rewrite the "if/else statement" in the following piece of code by replacing it with a "case" statement, and I am deadly stuck with it for a few hours - what am I missing?
puts "Welcome to 'Guess My Number!'"
print "What is your name?"
input = gets
name = input.chomp
puts "Welcome, #{name.upcase!}!"
puts "I've got a random number between 1 and 100!"
puts "Can you guess it?"
target = rand(100) + 1
num_guesses = 0
guessed_it = false
until num_guesses == 10 || guessed_it
remaining_guesses = 10 - num_guesses
puts "You've got #{remaining_guesses.to_s} guesses left!"
print "Make a guess, put down a number: "
guess = gets.chomp.to_i
num_guesses = num_guesses + 1
end
puts case verification
when guess < target
then "Ooops. Your guess was LOW."
when guess > target
then "Ooops. Your guess was HIGH."
when guess < -1
then puts "Oooops. You have entered a number lower that 1!"
when guess > 100
then puts "Oooops. You have entered a number higher than 100!"
when guess =~ /^([w])/
then puts "Ooops. Looks like you have entered a non numeric
value!"
when guess == String
then puts "Oooops! Looks like you have entered a non numeric
value"
when guess == target
then puts "Good job, #{name}!"
puts "You guessed my number in #{num_guesses} guesses!"
guessed_it = true
end
unless guessed_it
puts "Sorry, you didn't get my number. My number was #{target}."
end
The "case statement" was used to replace and enhance the logic of the following if else statement:
if guess < target
puts "Ooops. Your guess was LOW."
elsif guess > target
puts "Ooops. Your guess was HIGH."
elsif guess == target
puts "Good job, #{name}!"
puts "You guessed my number in #{num_guesses} guesses!"
guessed_it = true
end
Your problem is that you're using the form of case with the optional condition, but you're using when clauses as if you were using the condition-less case.
puts case
when guess < target
"Ooops. Your guess was LOW."
should work.
Further explanation:
using case without a condition, the earliest when branch with a truthy expression is executed. This is what you want here.
But you were using case with verification. In this case, all branches are compared to verification, and the first branch where verification === branch condition is true is executed.
Since in your example I'm guessing verification is always nil, and all your branches' conditions are always true or false, no branch will ever get executed.
You can use a case statement like so:
class String
def green;"\e[32m#{self}\e[0m";end
def yellow;"\e[33m#{self}\e[0m";end
def cyan;"\e[36m#{self}\e[0m";end
def bg_blue;"\e[44m#{self}\e[0m";end
def bold;"\e[1m#{self}\e[22m";end
def underline;"\e[4m#{self}\e[24m";end
def border(num);"\n#{'-' * num}\n#{self}\n#{'-' * num}\n";end
end
puts;puts "Welcome to 'Guess My Number!'".bold.bg_blue;puts
print 'What is your name? '.green
name = gets.chomp
puts "\nWelcome, #{name.upcase!}!\n".cyan.underline
puts "I've got a random number between 1 and 100!\nCan you guess it?".border(44)
target = rand(100) + 1
num_guesses = 0
guessed_it = false
until num_guesses == 10 || guessed_it
remaining_guesses = 10 - num_guesses
puts "\nYou've got #{remaining_guesses} guesses left!\n"
puts;print 'Make a guess, put down a number: '
guess = gets.chomp
case guess.to_i
when (1...target)
puts 'Ooops. Your guess was LOW'.yellow.border(26)
when (target + 1..100)
puts 'Ooops. Your guess was HIGH'.yellow.border(26)
when target
puts; puts; puts
puts "Good job, #{name}!".bold.green
puts 'You guessed my number in ' + "#{num_guesses} guesses!".cyan
puts; puts; puts
guessed_it = true
else
puts "Oooops. You didn't enter a number from 1 to 100".yellow.border(47); puts
end
num_guesses += 1
end
unless guessed_it
puts;puts;puts "Sorry, you didn't get my number. My number was #{target}.".yellow;puts
end
Thanks a lot to everybody! With your invaluable help I managed to regain patience in my soul and satisfaction from this small task :) My mistake is that I violated the rules of common sense by trying to run several pieces of code in a wrong sequence. I moved the case statement inside the until loop and now all I have to do is correct the mistakes in particular when/then statements. It works :)
until num_guesses == 10 || guessed_it
remaining_guesses = 10 - num_guesses
puts "You've got #{remaining_guesses.to_s} guesses left!"
print "Make a guess, put down a number: "
guess = gets.chomp.to_i
num_guesses = num_guesses + 1
puts case
when guess < target
then "Ooops. Your guess was LOW."
when guess > target
then "Ooops. Your guess was HIGH."
when guess < -1
then puts "Oooops. You have entered a number lower that 1!"
when guess > 100
then puts "Oooops. You have entered a number higher than 100!"
when guess =~ /^([w])/
then puts "Ooops. Looks like you have entered a non numeric value!"
when guess == String
then puts "Oooops! Looks like you have entered a non numeric value"
when guess == target
then puts "Good job, #{name}!"
puts "You guessed my number in #{num_guesses} guesses!"
guessed_it = true
end
end
unless guessed_it
puts "Sorry, you didn't get my number. My number was #{target}."
end
To calculate $totalNoOfGuesses you would add $noOfGuesses together from each game played, correct? How do I execute that in my code? I've tried several different options, but it doesn't work. Am I supposed to be creating an array or something?
def play_game
$noOfGuesses=0
$gameCount+=1
number = generate_number
loop do
print "\nEnter your guess and press the Enter key: "
reply = STDIN.gets
reply.chop!
reply = reply.to_i
$noOfGuesses+=1
Between this would be if reply > or <, too high or too low... reply = get.to_i
$noOfGuesses=0
$gameCount=0
$totalNoOfGuesses=0
$avgNoOfGuesses=0
answer = ""
loop do
Console_Screen.cls
print "Are you ready to play the Ruby Number Guessing Game? (y/n): "
answer = STDIN.gets
answer.chop!
break if answer == "y" || answer == "n"
end
if answer == "n"
Console_Screen.cls
puts "Okay, perhaps another time.\n\n"
else
loop do
SQ.play_game
Console_Screen.cls
print "It took you #{$noOfGuesses} attempt#{'s' if $noOfGuesses > 1}.\n"
print "You have played #{$gameCount} time#{'s' if $gameCount > 1}.\n"
print "It has taken you #{$totalNoOfGuesses} attempts in #{$gameCount} game#{'s' if $gameCount >1}.\n\n"
I am following tutorial and I can't figure out what I am doing wrong. It's outputting everything up to if down
puts "we are going down the cave" I can't get it to output the else statement or anything afterwards. I am just learning and the answer is probably really simple.
puts("Would you like to go up or down?")
user_input = gets()
down = "cave"
up = "mountain"
if down
puts "we are going down the cave"
else up
puts "we are going up the mountain"
puts("Pick a number between 1 and 100")
LOCATION = "cave"
NUMBER = gets()
if NUMBER == 100
puts "You've achieved enlightment in the #{LOCATION}! Spread joy around the world!"
elsif NUMBER >= 50 > 100
puts "There are #{NUMBER} goblins in the #{LOCATION}. WE MUST FIGHT!"
elsif NUMBER > 20 > 50
puts "There is still hope that we will make it to the #{LOCATION}. before the #{NUMBER} Snufflebums get us!"
else NUMBER <= 20
puts "We have conquered the Goon Squad of the #{LOCATION}.. It only took us #{NUMBER} years!!!"
end
end
down is "cave" and is always 'truthy' so if down is always, always true. You want to be testing the user_input, not the variable down
What I think you want is...
user_input = gets.chomp
# you need the chomp to remove the return character
down = "cave"
up = "mountain"
if user_input == down
puts "we are going down the cave"
elsif user_input == up
puts "we are going up the mountain"
end
# you need the end statement, otherwise everything that follows is part of the "else"
And remove the last end
I'm having a problem with my ruby script. If anyone could help, I'd really appreciate it. The problem is that the number is stuck between 1-2; where 2 is too high and 1 is too low. The guesses should be integers only.
#!/usr/bin/ruby
def highLow(max)
again = "yes"
while again == "yes"
puts "Welcome to the High Low game"
playGame(max)
print "Would you like to play again? (yes/no): "
again = STDIN.gets.chomp
if again == 'no'
puts "Have a nice day, Goodbye"
end
end
end
#This method contains the logic for a single game and call the feedback method.
def playGame(max)
puts "The game gets played now"
puts "I am thinking of a number between 1 and #{max}." #It show what chosen by user
randomNumber = rand(max)+ 1
print "Make your guess: "
guess = STDIN.gets.chomp
feedback(guess, randomNumber)
end
#Start while loop
#Logic for feedback method. It's ganna check the guess if it's high or low.
def feedback(guess, randomNumber)
count = 1
while guess.to_i != randomNumber
count = count + 1
if guess.to_i < randomNumber
print "That's too low. Guess again: "
else
print "That's too high. Guess again: "
end
guess = STDIN.gets.chomp
end
puts "Correct! You guessed the answer in #{count} tries!"
end
highLow(ARGV[0])
Change your last line to this:
highLow(ARGV[0].to_i)
The ARGV array contains all the passed in arguments as strings, so you have to cast it to integer.
So i have been learning ruby as of late and i am working on this code for practice purposes but i cannot seems to be able to solve this problem any help would be appreciate it.
This is are the guidelines i am following:
clear the screen
greet the player
explain the rules of the game to the player
generate a random number between 0 and x (x being a variable that can be set to any integer)
allow the player n number of guesses (n being a variable)
keep track of the guess history
don't count repeated guesses against the player
congratulate the player when he/she guesses correctly
alert the player when there is only one guess remaining
print the guess history at the end of the game
count number of games won IN A ROW
count number of games won in total
congratulate the play on 3 games won IN A ROW
ask if the player wants to play again
thank the player for playing games if the number of games played is greater than 2
please keep in my that this is work in progress and i have not completed all the guideline, however my questions is with one particular part of it.
here is the code:
guess = Array.new
puts guess.class
def ask()
puts "Please answer in a 'y' or 'n' only!"
puts "Would like to play again?"
end
def guess_check_against()
g = guess.last
unless guess.include?(g) != guess
count+=1
else
puts "sorry you have guessed that number before, Guess Again: "
guess << gets.to_i
count+=1
end
end
puts "what is your name?"
user= gets.chomp
puts "Hello #{user}!!"
max_user_attempts = 4
#attempt_counter = 0
directions = "\nLets play a guessing game! You have
#{max_user_attempts.to_s} guesses before you lose."
print directions
g = guess.last
win = 0
count = 0
play = true
while play == true
puts "Please tell me the max value of the random number: "
max= gets.to_i
num= rand(max)
puts "Ok. The random number is generated between 1 and " + max.to_s + "."
puts "Make your guess: "
guess << gets.to_i
guess_check_against()
#attempt_counter+=1
while guess != num && play != false
if g > num && #attempt_counter < max_user_attempts
print "That's too high. Guess again: "
guess << gets.to_i
guess_check_against()
#attempt_counter+=1
elsif g < num && #attempt_counter < max_user_attempts
print "That's too low. Guess again: "
guess << gets.to_i
guess_check_against()
count+=1
#attempt_counter+=1
else
break
end
end
if #attempts_counter >= max_user_attemtps
puts "Sorry! you lost! Try Again"
break
else #attempts_counter <= max_user_attempts
puts "Correct! You guessed the answer in " + count.to_s + " tries!"
win+=1
end
if win >= 3
puts "Congratulation! you have #{win} number of games in a row"
ask()
answer = gets.chomp!
elsif win < 3
ask()
answer = gets.chomp!
else
break
end
if answer == 'n'
play = false
break
end
if answer == 'y'
play = true
count = 0
end
end
puts "Ok. Goodbye!!"
and here is the error i keep receiving when i try to run this program:
guessing_game.rb:12:in `guess_check_against': undefined local variable or method `guess' for main:Object (NameError)
from guessing_game.rb:45:in `<main>'
when i try to use irb to run the same scenario it works completely fine.
i can not figure out what i am doing wrong, please help!!
The method definition
def guess_check_against()
g = guess.last
...
end
has its own scope, and the local variable
guess = Array.new
that you defined outside of it, is not accessible inside the method definition. guess is not defined inside the method definition. You can change the code so that the method takes that as an argument, and it will become accessible.