I have a lesson file for an in-terminal tic-tac-toe game. my lib file works when I isolate it. (lib/move.rb)
def display_board(board)
puts " #{board[0]} | #{board[1]} | #{board[2]} "
puts "-----------"
puts " #{board[3]} | #{board[4]} | #{board[5]} "
puts "-----------"
puts " #{board[6]} | #{board[7]} | #{board[8]} "
end
def input_to_index(user_input)
index = user_input.to_i - 1
end
def move(arr,ind,char = "X")
arr[ind] = char
end
However, when I run my bin file (bin/move), a NoMethodError shows up referencing the "index = user_input.to_i -1"
#!/usr/bin/env ruby
require_relative '../lib/move.rb'
# Code your CLI Here
puts "Welcome to Tic Tac Toe!"
board = Array.new(9," ")
puts "Where would you like to go?"
input = gets.split
index = input_to_index(input)
input_to_index(input)
move(board,index,"X")
display_board(board)
I don't understand what's wrong and how to fix it.
//#input_to_index is meant to turn the input into an integer, and takes input 1-9 and outputs 0-8
Please help!
split divides string(read from user input, the gets method) into substrings based on a delimiter, returning an array of these substrings. to_i is a method of string that covert it to an integer value, which is not available to an array.
Try to change
gets.split
to
gets
Then the issue will go away.
Related
This is a program that ask input from the user about the characteristics of a gemstone then prints to the screen. Things like color, price and name. I have written it to an extend where the user enters all this and prints them out. Am now stuck where I should loop and enable the user to enter any number of gemstones. Like if he/she enters 3 gemstones then it should loop and allow the user to enter the characteristics of the 3 gemstone types. I would also like to sort the resulting output of gemstone names in alphabetical order. Appreciated
class GemStones
# input variables
name = ""
color = ""
price = 0
gemstoneNumber = 0
# output variable
gemstoneNumber = 0
# processing
print "How many gemstones do you want to enter? "
gemstoneNumber = gets
print "What is the name of the gemstone? "
name = gets
print "What is the color of the gemstone? "
color = gets
print "What is the price of the gemstone? "
price = gets
puts " You entered #{gemstoneNumber} The name is #{name}, the color is #{color} and price is
$ #{price}"
end
You should not wrap the code in class in the first place. There is no OOP in your code, hence the class is not needed as well. Also, gets returns a string, while for number you likely need an integer.
Here would be a [more-or-less] rubyish version of your code:
print "How many gemstones do you want to enter? "
# ⇓⇓⇓⇓⇓ get rid of trailing CR/LF
# ⇓⇓⇓⇓ convert to integer
gemstoneNumber = gets.chomp.to_i
gemstones =
1.upto(gemstoneNumber).map do |i|
puts
puts "Please enter data for the gemstone ##{i}:"
print "What is the name of the gemstone? "
name = gets.chomp # shave the trailing CR/LF off
print "What is the color of the gemstone? "
color = gets.chomp
print "What is the price of the gemstone? "
price = gets.chomp.to_f # convert to float
# in Ruby we normally use hashes to store
# the named values
{name: name, color: color, price: price}
end
puts "You entered #{gemstoneNumber} gemstones. They are:"
gemstones.each do |gemstone|
puts "Name: #{gemstone[:name]}. " \
"Color: #{gemstone[:color]}. " \
"Price: $#{gemstone[:price]}."
end
Alternatively, you might use the class instead of hash to store the gemstone info.
To sort the gemstones by the name:
puts "You entered #{gemstoneNumber} gemstones. They are:"
# ⇓⇓⇓⇓⇓⇓⇓ HERE
gemstones.sort_by { |gemstone| gemstone[:name] }.each do |gemstone|
puts "Name: #{gemstone[:name]}. " \
"Color: #{gemstone[:color]}. " \
"Price: $#{gemstone[:price]}."
end
The good documentation on enumerations might be found in the official ruby docs: https://ruby-doc.org/core/Enumerable.html#method-i-sort_by (and around.)
You can try this as well.
def gem_stones num
#gem_stones = []
num.times do |a|
print "Enter the name of gemstone #{a+1} "
name=gets.chomp
print "Enter the color of gemstone #{a+1} "
color = gets.chomp
print "Enter the price of gemstone #{a+1} "
price = gets.chomp.to_f
#gem_stones.push({name: name, color: color, price: price})
end
puts #gem_stones.sort_by {|a| a[:name]}.map{|gem| "Name: #{gem[:name]}, Color: #{gem[:color]}, Price: #{gem[:price]}"}.join("\n")
end
puts "Ener the number of gem stones you want to enter?"
num = gets.to_i
gem_stones num
im looking for a way to write code above the command line.
Like in chats, where the thing you've typed is displayed above the input line.
For example:
def output(arg1, arg2)
puts arg1 + ":" + arg2
end
puts "-" *30
print "What do you want to say? > "
written_line = gets.chomp
output(username, written_line)
what I want to display, if I type "My Name is Tim" is:
Tim: My Name is Tim
---------------------------------
What do you want to say? > _
Is there an Idea outside how to do it like this?
Thank you
Maybe you are looking for something like this?
def clear_line
print "\e[2K" # Clear entire line
end
def move_up(n)
print "\e[#{n}F" # Move to the beginning of n lines up
end
def positioning_to_output
move_up(2)
clear_line
end
def output(arg1, arg2)
positioning_to_output
puts arg1 + " :" + arg2
clear_line
puts "-" *30
end
username = "Jim Kirk"
4.times do
print "What do you want to say? > "
written_line = gets.chomp
output(username, written_line)
end
Tested on macOS, thanks to escapes sequeces found here
This seems to work correctly and display the results I want
Dir["/Users/ondrovic/RubyTest/**/*.txt"].each do |i|
puts i.green if File.readlines(i).grep(/test/).any?
end
Why when I try like this does it not populate info
print "Enter search dir"
src = gets
print "Enter search term"
trm = gets
puts "Looking in #{src} for #{trm}"
Dir["#{src}/**/*.txt"].each do |i|
puts i.green if File.readlines(i).grep(/"#{trm}"/).any?
end
I have also tried it this way
Dir[src + "/**/*.txt"].each do |i|
puts i.green if File.readlines(i).grep(/ + trm + /).any?
end
Working code
require 'colorize'
print "Enter search dir\n".green
src = gets.chomp
print "Enter search term\n".blue
trm = gets.chomp
puts "Looking in #{src} for #{trm}"
Dir["#{src}/**/*.txt"].each do |i|
puts i.green if File.readlines(i).grep(/#{trm}/).any?
end
The return value of the gets includes trailing newline:
>> gets
asdf
=> "asdf\n" # <----
>>
Remove it using String#chomp:
print "Enter search dir"
src = gets.chomp
print "Enter search term"
trm = gets.chomp
...
In addition to that, the pattern /"#{trm}"/ includes ". Remove them:
/#{trm}/
Alternatively, you can use Regexp::new:
Regexp.new(trm)
This is a piece of code:
def add(a, b)
a + b;
end
print "Tell number 1 : "
number1 = gets.to_f
print "and number 2 : "
number2 = gets.to_f
puts "#{number1}+#{number2} = " , add(number1, number2) , "\n"`
When I run it, my results are spread over several lines:
C:\Users\Filip>ruby ext1.rb
Tell number 1 : 2
and number 2 : 3
3.0+3.0 =
5.0
C:\Users\Filip>
Why doesn't puts() print in a single line, and how can keep the output on one line?
gets() includes the newline. Replace it with gets.strip. (Update: You updated your code, so if you're happy working with floats, this is no longer relevant.)
puts() adds a newline for each argument that doesn't already end in a newline. Your code is equivalent to:
print "#{number1}+#{number2} = ", "\n",
add(number1, number2) , "\n",
"\n"
You can replace puts with print:
print "#{number1}+#{number2} = " , add(number1, number2) , "\n"`
or better:
puts "#{number1}+#{number2} = #{add(number1, number2)}"
Because puts prints a string followed by a newline. If you do not want newlines, use print instead.
Puts adds a newline to the end of the output. Print does not. Try print.
http://ruby-doc.org/core-2.0/IO.html#method-i-puts
You might also want to replace gets with gets.chomp.
puts "After entering something, you can see the the 'New Line': "
a = gets
print a
puts "After entering something, you can't see the the 'New Line': "
a = gets.chomp
print a
How do I make \n actually work in my output? At the moment it just writes it all in 1 long block. Thanks for any help
Dir.chdir 'C:/Users/name/Music'
music = Dir['C:/Users/name/Music/*.{mp3, MP3}']
puts 'what would you like to call the playlist?'
#new = ''
playlist_name = gets.chomp + '.m3u'
music.each do |z|
#new += z + '\n'
end
File.open playlist_name, 'w' do |f|
f.write #new
end
Use "\n" instead of '\n'
I would like to share my experience with \n
I came to notice that "\n" works as-
puts "\n\n" // to provide 2 new lines
but not
p "\n\n"
also
puts '\n\n'
Doesn't works.
Hope will work for you!!
You can do this all in the File.open block:
Dir.chdir 'C:/Users/name/Music'
music = Dir['C:/Users/name/Music/*.{mp3, MP3}']
puts 'what would you like to call the playlist?'
playlist_name = gets.chomp + '.m3u'
File.open playlist_name, 'w' do |f|
music.each do |z|
f.puts z
end
end
Actually you don't even need the block:
Dir.chdir 'C:/Users/name/Music'
music = Dir['C:/Users/name/Music/*.{mp3, MP3}']
puts 'what would you like to call the playlist?'
playlist_name = gets.chomp + '.m3u'
File.open(playlist_name, 'w').puts(music)
For me it didn't work with adding "\n" to the end of an existing argument to puts, so as a workaround I called print on the next line with "\n" as an argument, although I suppose I could have just called puts again.
This did not produce the desired result:
puts "Coach says: #{coach_answer(user_input)}\n"
But this did:
puts "Coach says: #{coach_answer(user_input)}"
print "\n"