I was looping some music notes and wanted it to stop looping when I enter. However, the loop cycle stops when it encounters the code:
stop = gets
if stop == "\n"
puts "You have stopped listening, どうして?"
break
end`
that only intended to break when receive the 'enter' input
Here is the full code:
a=0
loop do
if a+=1
puts "♪"
sleep(0.1)
end
if a+=2
puts " ♫"
sleep(0.2)
end
if a+=3
puts" ♪"
sleep(0.3)
end
if a+=4
puts" ♫"
sleep(0.4)
end
if a+=5
puts" ♪"
sleep(0.5)
end
if a+=6
puts" ♪"
sleep(0.6)
end
if a+=7
puts" ♪"
sleep(0.5)
end
if a+=8
puts"♪"
sleep(0.4)
end
stop = gets
if stop == "\n"
puts "You have stopped listening, どうして?"
break
end
end
I know the loop stopped after a+=8 because it ran into the break command, thus, I tried isolate the code block containing break but it was not the way.
I assume that you want to keep printing those music notes until the user hits enter.
You are facing two problems:
you can't gather any input while your program is sleep-ing
calling gets will block (i.e. pause) your program until input is available
In order to gather input via gets while still printing your notes (and occasional sleeping) in a loop, I would probably utilize a separate thread to perform both tasks concurrently:
music_thread = Thread.new do
loop do
puts "♪"
sleep(0.1)
puts " ♫"
sleep(0.2)
puts " ♪"
sleep(0.3)
puts " ♫"
sleep(0.4)
puts " ♪"
sleep(0.5)
puts " ♪"
sleep(0.6)
puts " ♪"
sleep(0.5)
puts "♪"
sleep(0.4)
end
end
gets
music_thread.exit
puts "You have stopped listening, どうして?"
In the above (simplified) code a new Thread is created which just prints notes in a loop indefinitely. The main thread then reads a line of input via gets, which will block the main thread at that point until the user hits enter (the music thread will keep running). Once gets returns, the main thread stops music_thread via exit, prints a message and the program is finished.
Related
I have the following:
text_counter = 0
MAXTEXT_COUNTER = 10
puts "hello, this will start"
loop do
puts "hello"
text_counter += 1
sleep(2)
if text_counter >= MAXTEXT_COUNTER
break
end
end
sleep(7200)
print "ended test"
Once the break has happened, how can I get it to start again from the top?
I'm now thinking I could nest this loop in an until loop with the condition of text_counter == 1000. This would break, then sleep for 2 hours, then start again until it hits 1000.
It looks like you need a loop within a loop where you repeat one N times, the other M times:
MAXTEXT_COUNTER = 10
puts "hello, this will start"
loop do
MAXTEXT_COUNTER.times do
puts "hello"
sleep(2)
end
print "ended test"
sleep(7200)
end
The outer loop is perpetual. The inner one runs a certain number of times and stops using the times method.
You're looking for next
It functions similarly to break, but returns control back to the top of the loop. It's great for creating flat control flow.
For example
0.upto(100) do |i|
if i % 7 == 0
puts "#{i} is a multiple of 7"
next
end
puts i
end
There is a retry keyword which repeats the loop from top, just what you've asked.
Or you can wrap your loop into a method and continuously call that method.
Hey guys i need to do a program that simulates a coinflip and give out head or number.I did that
a = rand(1..2)
if a == 1 then
puts "HEAD!"
else
puts "NUMBER!"
end
enter = gets
if enter == "\n"
a = rand(1..2)
if a == 1 then
puts "HEAD!"
else
puts "NUMBER!"
end
end
but how can i include everytime you press enter it should continue and continue simulating coinflip like ... HEAD (enter) HEAD (enter) NUMBER (enter) and so on.
You need some kind of loop, not just an if. Here's a short way to do it:
loop do
puts ['HEAD', 'NUMBER'].sample
break if gets != "\n"
end
Or if you're ok with stopping by pressing CTRL-C:
loop do
puts ['HEAD', 'NUMBER'].sample
gets
end
Using a post-loop test (i.e., do the gets and possibly break after printing the flip result) is more appropriate here, as it avoids the code duplication. Also see this popular Ruby style guide:
https://github.com/bbatsov/ruby-style-guide#loop-with-break
https://github.com/bbatsov/ruby-style-guide#infinite-loop
Basically in my search for code which will loop, and terminate upon user input, i managed to find code here, and after some alteration, produced this:
#desired destination method, however loop persists!!
def desired_method
print "method entered"
end
Thread.new do
while line = STDIN.gets
break if line.chomp == "" # code detects user input
end
desired_method
end
# program will loop here until user presses enter
loop do
puts "foo"
sleep 1
end
This code is brilliant, and will enter the method 'desired_method' when i hit enter, however the loop persists!! printing 'foo' perpetually after "method entered"!!. I have done some research prior to posting this question on how to kill threads, which i believe may hold the answer. My attempts included naming the thread and using the 'thread.exit' function to kill it, however these techniques have remained unsuccessful.
Can anyone illustrate how i might enter the 'desired_method' method without the persisting "foo" print?
Thanks in advance, and greatly appreciated.
An easy solution here is to use semaphore, signalling between threads with a variable access to both places:
# This will be out stop flag, for signalling between threads.
#time_to_stop = false
def desired_method
print "method entered"
# Here we want the loop in the other thread to stop.
#time_to_stop = true
end
Thread.new do
while line = STDIN.gets
break if line.chomp == "" # code detects user input
end
desired_method
end
# program will loop here until user presses enter
loop do
puts "foo"
sleep 1
# only continue if the stop flag is not set.
break if #time_to_stop
end
Hope this helps.
I'm trying to find a way to terminate a loop when the user hits 'x'+Enter. I want the loop to just keep running in the background until the user cancels it.
Something along these lines:
while gets.chomp != 'x'
puts 'looping...'
sleep 1
end
I'm a beginner with programming and have searched far and wide for how to do this so any help would be deeply appreciated.
You have to use threads for this:
Thread.new do
while line = STDIN.gets
break if line.chomp == 'x'
end
exit
end
# whatever you want to do in the background
# (or rather in the foreground, actually)
loop do
puts "foo"
sleep 1
end
The problem is that STDIN.gets blocks, so you can't do something else at the same time without parallelizing the program by using a background thread that only checks for input.
I have a while loop consistently listening to incoming connections and outputting them to console. I would like to be able to issue commands via the console without affecting the output. I've tried:
Thread.new do
while true
input = gets.chomp
puts "So I herd u sed, \"#{input}\"."
#Commands would be in this scope
end
end
However, that seems to pause my entire script until input is received; and even then, some threads I have initiated before this one don't seem to execute. I've tried looking at TCPSocket's select() method to no avail.
Not sure where are the commands you want to "continue running" in your example. Try this small script:
Thread.new do
loop do
s = gets.chomp
puts "You entered #{s}"
exit if s == 'end'
end
end
i = 0
loop do
puts "And the script is still running (#{i})..."
i += 1
sleep 1
end
Reading from STDIN is done in a separate thread, while the main script continues to work.
Ruby uses green threads, so blocking system calls will block all threads anyway. An idea:
require 'io/wait'
while true
if $stdin.ready?
line = $stdin.readline.strip
p "line from stdin: #{line}"
end
p "really, I am working here"
sleep 0.1
end