I can't get this program to respond properly to user input. Various looping techniques either only run the block once or run the block infinitely no matter what the user inputs (I've tried case and while as well). Here's the most recent method I've tried:
work_summary = []
begin
# code that runs a sprint and adds results to the work_summary array
puts "Would you like to add a sprint, Y/N?"
sprint = gets.to_s
end until sprint == "N"
print work_summary, "\n"
Ruby never objects to my syntax with any of the various methods, but it also never works.
You need
sprint = gets.chomp
gets returns string with trailing "\n".
http://web.njit.edu/all_topics/Prog_Lang_Docs/html/ruby/syntax.html#begin
Begin is typically used for exception handling. I think you're looking for a while loop.
Here is an example
work_summary = []
while true
puts "Would you like to add a sprint?"
sprint = gets.chomp
if sprint == "N"
break
elsif sprint == "Y"
puts "What's your time?"
time = gets.chomp
work_summary << time
else
puts "I didn't understand your request. Enter Y or N"
end
end
I found two possibility over here which is suitable for you
First one is
while true
puts "Would you like to add a sprint?"
sprint = gets.chomp
if sprint == "N"
break
elsif sprint == "Y"
puts "What's your time?"
time = gets.chomp
work_summary << time
else
puts "Wrong request. Enter Y or N"
end
end
Here Lopp will run until break Doesn't get executed
Second thing you can Modify 1 Line in your code which is
sprint = gets.chomp
this will extract last special character of your string which is generated by gets and work fine in your case
Related
How do I put a message (string) for a specific answer (user input) and another message for another answer? For e.g.
puts "Did You Like My Program?"
feedback = gets
if feedback = "Yes"
puts "We're Glad!"
elsif feedback = "No"
puts "We Will Try To Improve!"
end
What should I change, add, or modify?
Your problem is that, when you compare, you have to use ==, not =.
When you input on command line, you always use Enter. It produces \n at the end of the string. So you need to remove it with chomp.
Also, to filter user input, I suggest this variant:
feedback = nil
until %w[y n].include?(feedback)
puts 'Did You Like My Program? Y/N'
feedback = gets.chomp.downcase
end
if feedback == 'y'
puts "We're Glad!"
else
puts "We Will Try To Improve!"
end
Brief explanation:
The code uses Array#include? and String#downcase.
%w[y n] is equal to ["y", "n"].
The until-loop executes the code while the condition is false.
I have a program that displays a numbered list and asks the user to input either a number or name from the list, and loops a block until the user enters "exit", after which it ends.
I want to add a line or two that puts an error message like, "Sorry, I don't seem to understand your request" if the user inputs something that is not on the list (name/number) and is not the word "exit".
I can't seem to figure it out. Any advice? My current code is below.
def start
display_books
input = nil
while input != "exit"
puts ""
puts "What book would you more information on, by name or number?"
puts ""
puts "Enter list to see the books again."
puts "Enter exit to end the program."
puts ""
input = gets.strip
if input == "list"
display_books
elsif input.to_i == 0
if book = Book.find_by_name(input)
book_info(book)
end
elsif input.to_i > 0
if book = Book.find(input.to_i)
book_info(book)
end
end
end
puts "Goodbye!!!"
end
Seems that you should add an elsif statement in this if:
if book = Book.find_by_name(input)
book_info(book)
elsif input != 'exit'
puts "Sorry, I don't seem to understand your request"
end
A good template for an interpreter is to build around Ruby's very capable case statement:
loop do
case (gets.chomp.downcase)
when 'list'
display_books
when /\Afind\s+(\d+)/
if book = Book.find($1.to_i)
book_info(book)
end
when /\Afind\s+(.*)/
if book = Book.find_by_name($1)
book_info(book)
end
when 'exit'
break
else
puts "Not sure what you're saying."
end
end
Although this involves regular expressions, which can be a bit scary, it does give you a lot of flexibility. \A represents "beginning of string" as an anchor, and \s+ means "one or more spaces". This means you can type in find 99 and it will still work.
You can create a whole command-line interface with it if you take the time to specify the commands clearly. Things like show book 17 and delete book 17 are all possible with a bit of tinkering.
I'm having trouble summing an array. Here's my existing code:
pageArray = Array.new
puts "How many pages long is the book you're reading?"
pageArray << gets.chomp
puts "Are you reading any other books right now?"
yn = gets.chomp
while yn != "no" do
puts "How many pages long is your next book?"
pageArray << gets.chomp
puts "Are you reading any other books right now?"
yn = gets.chomp
end
pageSum = pageArray.reduce(:+)
puts pageSum
When I go through and enter the values 100 and 50, the final return is "10050," rather than "150." Am I missing something obvious?
The code could be written more clearly, and more Ruby-like. Here's some untested code that is more idiomatic:
page_array = []
puts "How many pages long is the book you're reading?"
page_array << gets.chomp
loop do
puts 'Are you reading any other books right now?'
yn = gets.chomp.downcase
break if yn == 'no'
puts 'How many pages long is your next book?'
page_array << gets.chomp.to_i
end
page_sum = page_array.reduce(:+)
puts page_sum
Notice:
variables in Ruby are in snake_case, notInCamelCase.
loop do will loop forever. Simply break when you've received the break value.
you should fold the case of the value used as a break to catch variations in 'y' and 'Y'.
take the time to format your code so it's easily read, even for quick tests. It's amazing how often code we think is just a test actually gets put into production, so do it right the first time.
You are entering strings and concatenating them.
Use gets.chomp.to_i
You need to change the string you get from gets to an int.
pageArray << gets.chomp.to_i
I am trying to make a number guessing game in Ruby but the program exits after I type in yes when I want to play again. I tried using the catch and throw but it would not work. Could I please get some help.
Here is my code.
class Game
def Play
catch (:start) do
$a=rand(11)
puts ($a)
until $g==$a
puts "Guess the number between 0-10."
$g=gets.to_i
if $g>$a
puts "The number you guessed is too high."
elsif $g==$a
puts "Correct you won!!!"
puts "Would you like to play again?"
$s=gets()
if $s=="yes"
$c=true
end
if $c==true
throw (:start)
end
elsif $g<$a
puts "The number you guessed is too low."
end
end
end
end
end
Game.new.Play
Edit: Here's my new code after trying suggestions:
class Game
def Play
catch (:start) do
$a=rand(11)
puts ($a)
while $s=="yes"
until $g==$a
puts "Guess the number between 0-10."
$g=gets.chomp.to_i
if $g>$a
puts "The number you guessed is too high."
elsif $g==$a
puts "Correct you won!!!"
puts "Would you like to play again?"
$s=gets.chomp
if $s=="yes"
throw (:start)
end
elsif $g<$a
puts "The number you guessed is too low."
end
end
end
end
end
end
Game.new.Play
Your first problem is here:
$s=gets()
if $s=="yes"
$c=true
end
The gets method will read the next line including the new line character '\n', and you compare it to only "yes":
> gets
=> "yes\n"
The idiomatic way to fix this in Ruby is the chomp method:
> gets.chomp
=> "yes"
That said, your code has two other deficiencies.
You may come from a language such as PHP, Perl, or even just Bash scripting, but Ruby doesn't require the dollar sign before variables. Using a $ gives a variable global scope, which is likely not what you want. In fact, you almost never want a variable to have global scope.
Ruby uses three types of symbol prefixes to indicate scope - # for instance, ## for class, and $ for global. However the most common type of variable is just local which doesn't need any prefix, and what I would suggest for your code.
I have always been told that it is very bad practice to use exceptions for control structure. Your code would be better served with a while/break structure.
When you do gets(), it retrieves the full line with a '\n' in the end. You need to trim the new line character by using:
$g=gets.chomp.to_i
Same for other gets
Based on your updated code (where you fixed the newline problem shown by others), your new problem is that you have wrapped all your game inside while $s=="true". The very first time your code is run, $s is nil (it has never been set), and so you never get to play. If you used local variables instead of global variables (s instead of $s) this would have become more obvious, because the code would not even have run.
Here's one working way that I would re-write your game.
class Game
def play
keep_playing = true
while keep_playing
answer = rand(11) # Make a new answer each time
puts answer if $DEBUG # we don't normally let the user cheat
loop do # keep going until I break from the loop
puts "Guess the number between 0-10."
guess = gets.to_i # no need for chomp here
if guess>answer
puts "The number you guessed is too high."
elsif guess<answer
puts "The number you guessed is too low."
else
puts "Correct you won!!!",
"Would you like to play again?"
keep_playing = gets.chomp.downcase=="yes"
break
end
end
end
end
end
Game.new.play
I know this doesn't really answer your question about why your code isn't working, but after seeing the code you posted I just had to refactor it. Here you go:
class Game
def initialize
#answer = rand(11)
end
def play
loop do
guess = get_guess
display_feedback guess
break if guess == #answer
end
end
def self.play_loop
loop do
Game.new.play
break unless play_again?
end
end
private
def get_guess
puts "Guess the number between 0-10."
return gets.chomp.to_i
end
def display_feedback(guess)
if guess > #answer
puts "The number you guessed is too high."
elsif guess < #answer
puts "The number you guessed is too low."
elsif guess == #answer
puts "Correct you won!!!"
end
end
def self.play_again?
puts "Would you like to play again?"
return gets.chomp == "yes"
end
end
Game.play_loop
wordList = ['1930', '1931', '1932', '1933', '1934', '1935', '1936', '1937', '1938', '1939', '1940']
wordLen = wordList.length
wordRand = rand(wordLen)
year = wordList[wordRand]
Very much a newb here... The behavior of year is such that every time I run the program, it selects a random string from wordList. The problem is that it takes that particular randomly-selected number and sets it as equal to year. So, for every instance of the program, year is the same string from the list each time I call it. How can I get it to select a different number each time?
puts 'Why hello there, dear! Grandma is, SO, happy to see you!'
response = gets.chomp
while response != 'BYE'
if response == response.upcase
puts 'NO, NOT SINCE ' + year + '!'
response = gets.chomp
else
puts 'WHAT? SPEAK UP, SONNY!'
response = gets.chomp
end
end
if response == 'BYE'
puts 'OKAY, BYE DEAR!!'
end
edit: added context
You appear to only be generating one value for year, then repeatedly using it in your loop. If you want different numbers, put the call to rand within the loop.