5
\$\begingroup\$

I am learning Ruby and would like to know how I am doing as far as writing the actual code.

Please keep in mind that this is my first Ruby script program, but I am trying to learn ruby in a very short period of time.

I would like to know about nitpicks in the language that every Ruby writer should now, nuances in syntax, and other Ruby specific ... things.

$randomNumber = rand(10) + 1

def guessRandomNumber   
    puts "Guess a number between 1 and 10"
    guess = gets
    if Integer(guess) == $randomNumber 
        puts "Right on, good guess"
    elsif Integer(guess) < $randomNumber 
        puts "too low"
        puts "please, guess again"
        guessRandomNumber
    elsif Integer(guess) > $randomNumber 
        puts "too high"
        puts "please, guess again"
        guessRandomNumber
    else
        puts "is that even a number? please, guess again"
        guessRandomNumber
    end
end

guessRandomNumber

puts "bye"
gets
\$\endgroup\$
7
\$\begingroup\$

Global variables

Don't use global variables(like $bar). It is always bad practice because you can mutate the global variable from anywhere. The alternative is: RANDOM_NUMBER = rand(1..10), notice that you can pass range as an argument of rand. rand(10) + 1 can return 11 so it isn't correct.

Style

Huge percentage of the Ruby community follow the style guide and this is the most popular one Ruby style guide.

Style issues:

  • Use snake case for the names of methods and variables.
  • Use double quotes only if you use interpolation or special symbols like \n.

About the implementation

IMO will be more readable like this:

def guess_random_number
  puts 'Guess a number between 1 and 10'

  random_number = rand(1..10)

  while random_number != (guess_number = gets.to_i)
    if guess_number < random_number
      puts "too low \nplease, guess again"
    else
      puts "too high \nplease, guess again"
    end
  end

  puts "Right on, good guess \nbye"
end

guess_random_number

You see there is no need to expose the variable in the global scope.

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ How will that work of the user enters letters instead of numbers? \$\endgroup\$ – Malachi May 21 '16 at 17:57
  • 1
    \$\begingroup\$ @Malachi gets.to_i will return 0 if the input is not a number (as I already explained in my answer) \$\endgroup\$ – janos May 21 '16 at 18:37
  • \$\begingroup\$ You forgot to mention that while loops are frowned upon. \$\endgroup\$ – 13aal May 22 '16 at 1:17
  • \$\begingroup\$ @13aal - This is the most readable solution that I can think of, recursion isn't that intuitive. But I don't really like the iterative style of programming. I will be happy if a see more functional solution. \$\endgroup\$ – Kamen Kanev May 22 '16 at 15:34
  • 1
    \$\begingroup\$ @13aal Still interested in your version if you had time to do it. \$\endgroup\$ – Marc-Andre Jun 16 '16 at 15:18
2
\$\begingroup\$

Disclaimer: I don't really know Ruby.

Instead of converting guess to Integer in every if/elseif, it would be better to do that once:

guess = Integer(gets)

In any case, Integer(somestring) works only if somestring is actually an integer, and your script currently doesn't handle that case. (The else statement is unreachable.)

To correct that, you could add proper input validation. Or, alternatively, you could use the to_i function, which tries to interpret the leading characters as an integer, and if it fails, returns 0 instead.

guess = gets.to_i

With this change, and the unreachable else case removed, the program becomes:

$randomNumber = rand(10) + 1

def guessRandomNumber   
    puts "Guess a number between 1 and 10"
    guess = gets.to_i
    if guess == $randomNumber 
        puts "Right on, good guess"
        return
    end
    if guess < $randomNumber 
        puts "too low"
    else
        puts "too high"
    end
    puts "please, guess again"
    guessRandomNumber
end

guessRandomNumber

puts "bye"

This could be still better. Reading user input repeatedly until some condition is a common pattern. Using recursion for the repeated prompt is usually considered bad form, as it can lead to excessive deep call stacks until overflow. Although in this particular example that's unrealistic to happen, for the sake of good habits, I recommend to rewrite this in an iterative way.

| improve this answer | |
\$\endgroup\$
2
\$\begingroup\$

You could put multiple different methods to obtain your resolution, for example, a prompt method that requires input to ask the question. A check_num method to check the numbers that requires arguments pertaining to the numbers, a restart method that will be called if the number is incorrect, and a begin_game method that will be called to start the game. This uses recursion and yes, it can get a little tricky when you use recursion. It is possible that it will eventually cause a stack overflow error however with this simple little program, it isn't that likely. This is also a more OOP way of writing it, which is what Ruby is all about. Here's my take on it:

RAND_NUM = rand(1..10) #<= Turn the number into a constant

def prompt(input) #<= Prompt method that requires an argument
  print input
  gets.chomp.to_i #<= Turn the output into a Integer
end

def check_num(num, num2) #<= Check the number against another number
  if num != num2 #<= If the number does not equal the other number
    restart 
  else
    puts 'Good guess, later..'
    exit #<= Exit if the numbers match
  end
end       

def restart #<= Restart method, basically the same as the begin_game, but causes recursion
  num = prompt('Enter a number between 1 - 10: ')
  check_num(RAND_NUM, num)
end  

def begin_game
  num = prompt('Enter a number between 1 - 10: ')
  check_num(RAND_NUM, num)
end

begin_game

Now when this is run:

Enter a number between 1 - 10: 1
Good guess, later..

Enter a number between 1 - 10: 1
Enter a number between 1 - 10: 2
Enter a number between 1 - 10: 3
Good guess, later..

Enter a number between 1 - 10: 1
Enter a number between 1 - 10: 2
Enter a number between 1 - 10: 3
Enter a number between 1 - 10: 4
Enter a number between 1 - 10: 5
Enter a number between 1 - 10: 6
Enter a number between 1 - 10: 7
Enter a number between 1 - 10: 8
Enter a number between 1 - 10: 9
Good guess, later..
| improve this answer | |
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.