Why is my Ruby code not executing as I expect it to? - ruby

I'm learning Ruby through the book Learn to Program by Chris Pine. In the book, there's an exercise which says:
Write a Deaf Grandma program. Whatever you say to grandma (whatever you type in), she should respond with HUH?! SPEAK UP, SONNY!, unless you shout it (type in all capitals). If you shout, she can hear you (or at least she thinks so) and yells back, NO, NOT SINCE 1938! To make your program really believable, have grandma shout a different year each time; maybe any year at random between 1930 and 1950. (This part is optional, and would be much easier if you read the section on Ruby's random number generator at the end of the methods chapter.) You can't stop talking to grandma until you shout BYE.
Hint: Don't forget about chomp! 'BYE'with an Enter is not the same as 'BYE' without one!
Hint 2: Try to think about what parts of your program should happen over and over again. All of those should be in your while loop.
I have written my code and it doesn't work as expected. Basically, when I input information, it follows the order in which the code was written. For example if I input "HELLO" it'll reply "HUH?! SPEAK UP, SONNY! but really it should be writing back "NO, NOT SINCE 1938!".
When I input 'BYE' nothing will come up unless I follow the order in which the code was written in (I hope that makes sense).
I have tried a lot of things, like not using the break (for the loop). I have tried to write it as one long piece of code without any ifs or else's.
Here is the code I have written:
puts 'Go speak to Grandma, she\'s in the kitchen!'
speaking = gets.chomp
if speaking == speaking.downcase
puts 'HUH?! SPEAK UP, SONNY!'
gets.chomp
while speaking == 'BYE'
puts 'BYE! COME AGAIN SOON!'
gets.chomp
break
end
else speaking == speaking.upcase
puts 'NO, NOT SINCE 1983!'
gets.chomp
end
I expect when I write HELLO to get the appropriate answer of 'NO, NOT SINCE 1983!'. Also, I expect the conversation to keep going because I have used gets.chomp on all pieces of the code. Sp why is the code stopping?

Problem in the code is that if ... else condition not wrapped within loop, so it would no be executed repeatedly.
Hint 2: Try to think about what parts of your program should happen
over and over again. All of those should be in your while loop
To make loop works you need wrap all repeatable lines within loop.
In your case loop should break only when input will be BYE
puts 'Go speak to Grandma, she\'s in the kitchen!'
speaking = gets.chomp
until speaking == 'BYE'
if speaking == speaking.upcase
puts 'NO, NOT SINCE 1983!'
else
puts 'HUH?! SPEAK UP, SONNY!'
end
# Get input before next loop
speaking = gets.chomp
end
puts 'BYE! COME AGAIN SOON!'
You don't need to check for downcase explicitly, only you care about is "does input contains only upper case characters"

Related

How can I stop Ruby if/elsif statement from looping?

I am teaching myself Ruby by making a small game in order to test out how I feel about the language. My code was going rather smoothly until I encountered a problem in which the first decision of the game loops instead of progressing forwards.
This code is what I have been using for a short part in the Exposition of my game.
def getup_or_sleep?
puts"Cole";
puts"----";
puts"Will you get up or go back to sleep?";
decision = gets
if decision == "sleep";
puts"Cole";
puts"----";
puts"You decide to go back sleep. It is far too early.";
elsif decision == "get up";
Exposition.stretch
else;
Exposition.getup_or_sleep?
end
This is the expected result I was hoping to achieve:
Cole
Will you get up or go back to sleep?
If player chooses 'sleep'
1)Cole
You decide to go back to sleep, it is far too early.
*I plan to make a new method to direct the user to, but I first want to fix this issue.
**if player chooses 'get up'
->>> to stretch method which is inside of the same class.
I'm new to coding so I may be confused on a few things. Thanks in advance! =)
Your method calls itself recursively because it all conditions fail, and it always falls back to the else branch.
This happens because gets reads input from the user and returns the input including the invisible newline character that is added when the user hits the enter key. But your conditions do not include such new line characters.
A common Ruby idiom is to call gets.chomp to get user input, where the chomp removes the newline character from the input.
Just change this line decision = gets to
decision = gets.chomp
to fix your issue.
Apart from that, your code isn't following Ruby idioms, for example, Ruby does not require a ; at the end of a line, or you usually add a whitespace between a method name and its argument, like in puts "Cole". Therefore, I suggest formatting your code like this:
def getup_or_sleep?
puts 'Cole'
puts '----'
puts 'Will you get up or go back to sleep?'
decision = gets.chomp
if decision == 'sleep'
puts 'Cole'
puts '----'
puts 'You decide to go back sleep. It is far too early.'
elsif decision == 'get up'
Exposition.stretch
else
Exposition.getup_or_sleep?
end
end
Or with a case block and some duplication extracted into a method:
def greeting
puts 'Cole'
puts '----'
end
def getup_or_sleep?
greeting
puts 'Will you get up or go back to sleep?'
case gets.chomp
when 'sleep'
greeting
puts 'You decide to go back sleep. It is far too early.'
when 'get up'
Exposition.stretch
else
Exposition.getup_or_sleep?
end
end

Sample ruby program keeps running with errors, can't figure them out [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
Alright, I have tried my best to get this code to just run without spitting out errors, but to no avail. Hopefully you can help me out.
require 'launchy'
#def linebreak(breakline)
def program()
puts "Welcome to test program v1. Would you like to continue? ENTER y for Yes or n for no"
user_input_1 = gets.chomp
if user_input_1 == "y"
puts "How would you like to proceed CRASH | TEXTMAKER | UNDECIDED // CASE SENSITIVE"
user_input_2 = gets.chomp
if user_input_2 == "CRASH"
while true Launchy.open("http://google.com")
elsif user_input_2 = "TEXTMAKER"
while true out_file.puts("test program v1")
else
puts "You have not entered a method."
elsif user_input_1 == "n"
abort
else
puts "That is not a valid command. Please run the script again."
end
end
Alright there's a few problems, but don't worry everything can be
fixed!
Let's start with what you did well
Good job using your booleans in most cases, most beginners don't seem
to grasp that == means equal, and = means something completely
different
Good job with the puts and using it properly, there are other
methods which I will cover later, that will look much better in your
case.
Now let's cover what can be fixed
As I stated above in most cases you used your Boolean correctly
however you seem to have missed one. elsif user_input_2 = "TEXTMAKER" you need a == to show that it is equal.
Your while loop doesn't seem to make any sense because you don't ever really set anything as true. In Ruby it is highly
recommended to never use a while loop, of course there are times
that you have to, but only after you've tried everything else.
elsif; else; elsif never use an elsif after an else. elsif is to provide an exception, in your case there's more then
one option so use the elsifs before the else, you'd be better using a case statement here.
Not to sound like an ass, but your indentation is horrible. You'd find a lot more problems with good indentation, in Ruby that's two
spaces, here's the style guide:
https://github.com/bbatsov/ruby-style-guide
Never have your users options be case sensitive, if somebody else is going to use your program, just assume they are the dumbest people in the world and make it super easy for them. user_input_2.gets.chomp.upcase this will set it so that no matter how they enter their text, it will always be upper case.
You're missing an end this will become clear once you've used proper indentation
Alright let's rewrite this thing:
require 'launchy'
def program #<= you don't need the parentheses
print "Welcome to the test program version 1, to continue type 'c' to exit type 'e': "
user_input = gets.chomp.upcase
if user_input == "C"
program_choices
elsif user_input == "E"
puts "Exiting.."
exit
#if you really want to use abort
#abort("Exiting..")
#you won't need to use exit if you use abort
else
puts "Invalid input, try again"
program #<= this is a loop known as recursion, don't use it to much
end
end
def program_choices
print "Pick an option, the choices include CRASH | TEXTMAKER | UNDECIDED: "
user_input = gets.chomp.upcase
case user_input #<= this is how you start a case statement
when "CRASH"
Launchy.open("http://google.com")
when "TEXTMAKER"
write_test_data
when "UNDECIDED"
puts "You really need to make up your mind.." #<= have some fun with it, that's the point of programming.
program_choices
else
puts "Invalid input, try again"
program_choices
end
end
def write_test_data
x = "Test file version 1"
if File.exist?("path/to/test/file.txt")
File.open("path/to/test/file.txt", "a"){ |s| s.write(x) }
else
new_test_file = File.new("path/to/test/file.txt")
new_test_file.puts(x)
end
end
And bam! Your program is up and running! If you have any questions about anything don't hesitate to ask, programming can be very tricky, and it can be very hard. Keep it up and you'll get there!
I see plenty of problems.
This isn't valid:
while true Launchy.open("http://google.com")
Neither is this:
while true out_file.puts("test program v1")
I can't tell you how to fix this, though, since it's not at all clear what you're trying to do.
An if block may only have one else, and it must come after all elsifs.
Here:
elsif user_input_2 = "TEXTMAKER"
You're assigning a new value to user_input_2. I'm guessing you meant to use the equality operator, which is ==.
Your def block doesn't have an end. This became obvious after I edited your code to use proper indentation. You'll save yourself a lot of trouble by using sensible indentation and whitespace.

Test for repeated gets.chomp input in Ruby

I am working in Ruby, and I am trying to test for a user's input (the variable kid) being the same three times.
I want my method speak to be called on endlessly until the user enters "BYE" three separate times when asked the three separate questions.
Right now, if the user inputs "BYE" even only for one question the entire conversation between the terminal and user ends.
Is there a way to have the program test for "BYE" being said three times, and only once said three separate times, have the conversation end?
kid = gets.chomp
unless kid == "BYE"
speak
end
I don't know if there is a really simple solution or only a complex one, but any answers help.
You need to keep track of how many times the user has input "BYE". When that number reaches 3 you exit:
byecount = 0
while kid = gets.chomp
case kid
when "BYE"
#increase the count of bye
byecount +=1
puts byecount
break if byecount == 3
else
#reset our count
byecount = 0
speak
end
end
The code resets to 0 on a non "BYE" answer.
I find a case statement to be very handy in situations like this when dealing with different user input, especially coupled with regular expressions.
I suggest looking for a ruby tutorial about "loops" and "control flow".
I think the Ruby Primer lesson at rubymonk.com may have what you need.
This example may also be helpful:
times = 0 # keep track of iterations
while times < 10 # repeatedly, while this condition is true
puts "hello!" # output "hello!"
times += 1 # increase count of iterations
end

When using rand() to generate numbers how can I verify that 'if' and 'else' statements guarantee me a correct answer?

I am attempting an exercise from a book that doesn't show any example code for a correct answer, so I'm not sure where I may have strayed. I've written what I felt was a good bit of code, but now I'm not sure if my code will return my statement for a correct guess.
The code:
prng = rand(10)
puts "What's your guess (1-9)?"
user_guess = gets.chomp
if user_guess == prng
puts "You guessed correctly!"
else
puts "Try again!"
end
I feel as though my if statement might be the issue here, because when I run the code it always returns my else statement. I've also tried narrowing the range of numbers so that my guess is more likely correct and I still didn't trigger the if statement's puts.
Any help is appreciated!
rand(10) returns an integer. gets returns a string. A string (in ruby) is never equal to an integer.
You need to either convert your input to an integer (gets.chomp.to_i) or your integer to a string: (rand(10).to_s) before you compare them.
Edit: If you need to debug further, you should check what the values actually are:
puts "The answer was #{prng.inspect} and you guessed #{user_guess.inspect}"

Simple Word Game Loop

# Guessing Game
# 1.0
# by Proto
words = ["cat", "snake", "wolf", "giraffe", "elephant"]
picked = words.sample
puts "Welcome to the guessing game! I'm thinking of an animal.
It's a #{picked.length} letter word. Can you guess what it is?"
try = gets.chomp
while try != picked
puts "Try again."
try = gets.chomp
if try == picked
puts "You win!"
break
end
end
It works but only sometimes and I get no errors from running it. The problem is that if I get the guess right on the first try, the game doesn't seem to enter the loop at all (it doesn't tell me "You win!"), it just exits the program. But that result is inconsistent. If i immediately restart and get it right sometimes it will tell me that I won. Sometimes it works, sometimes it doesn't. There seems to be something wrong with my loop or syntax, but I can't see it. Any help appreciated. Thanks.
Remove the if block and put the "You win!" statement outside the while statement. Reason being, eventually, in your current logic the player will win, and only then the logic breaks, so you might as well move it out.
while try != picked
puts "Try again."
try = gets.chomp
end
puts "You win!"
The reason the "You win!" is not printed in your existing code is that the loop is never entered when try == picked initially, because that is the condition in the while loop.
The above changes take care of that scenario as well.

Resources