# Higher lower game in Ruby

I finished the Ruby chapter in Seven Languages in Seven Weeks. It tries to make you familiar with the core concepts of several languages rather quickly. Dutifully I did all exercises, but most likely they can be improved to be more Ruby-like. I'll post my code samples one by one, so I can apply things learned in previous questions to later questions.

Day 1

Write a program that picks a random number. Let a player guess the number, telling the player whether the guess is too low or too high.

range = (0..10)
to_guess = range.min + rand(range.max - range.min)
guessed = false

while !guessed
puts "Guess a number, between #{range.min} and #{range.max}"
guess = gets
int = guess.to_i
if int == to_guess
puts 'Correct!'
guessed = true
else
puts int > to_guess ? 'Lower' : 'Higher'
end
end


class Range
def size
self.end - self.begin
end
end

range = 0..10
to_guess = range.begin + rand(range.size)
guessed = false

until guessed
puts "Guess a number, between #{range.begin} and #{range.end}"
guess = gets
int = guess.to_i
if int == to_guess
puts 'Correct!'
guessed = true
else
puts int > to_guess ? 'Lower' : 'Higher'
end
end


A couple of minor things:

First of all the convention in the ruby world is to use 2 spaces for indentation, not 4. It doesn't really matter much, but it's generally easier to use the style conventions that everyone uses unless you have a reason not to.

range = (0..10)


You don't actually need the parentheses here. Parentheses are not part of range syntax - the reason you usually see ranges wrapped in parentheses is that you can't call methods on ranges without them (because 0..10.foo would be interpreter as 0..(10.foo)).

to_guess = range.min + rand(range.max - range.min)


You should use begin and end or first and last instead of min and max. In ruby 1.8.7 min and max are inherited from Enumerable and will iterate the entire range in order to find the minimum/maximum, making them O(n). Only in 1.9 (in 1.9.2 at least) they're overridden to work in O(1) time. begin and end work in O(1) time in all ruby versions.

I would also consider putting this into its own method as it seems like it might come in handy more than once.

while !guessed


I would write that as until guessed as that reads a bit nicer to me.

One thing I noticed is that you have a throwaway variable, guess, in between gets and int. You can reduce some of that by simply using guess = gets.to_i and if guess == to_guess.

Also, you could use break instead of the guessed variable and while/until condition:

loop do
# ...
if guess == to_guess
puts 'Correct!'
break
end
puts int > to_guess ? 'Lower' : 'Higher'
end


But that is more a matter of preference, as both methods have their merits.