Creating multiple objects from a model

Hi all,

I’m new to the programming world, so much of this stuff is still pretty
foreign to me.

I’ve created a ‘roll_dice.rb’ program that draws on the ‘die.rb’ model.
When the roll_dice program is run, the user is simply prompted to type
‘roll’ to roll the dice and get a result. Typing ‘quit’ exits the
program.

I’d like to expand the functionality of this program such that when the
program is run, the user is first prompted to enter in how many dice
they would like to roll. After answering, the user would then type
‘roll’ and receive back the same number of answers as number of dice.
i.e. :

How many dice would you like to roll?

2
Type ‘roll’ to roll your dice.
roll
3
2
Type ‘roll’ to roll your dice.
roll
6
4

The thing is, I’m not sure how to add that kind of functionality to my
program yet. Thoughts and suggestions are appreciated. Thanks!

Here is my current code (I’ve also included it as an attachment):

die.rb

Class Die
def rolled_dice
1 + rand(6)
end
end

roll_dice.rb

require_relative ‘die’

@die = Die.new

while true
puts “Type ‘roll’ to roll the dice.”
answer = gets.chomp
if answer == ‘roll’
puts @die.rolled_dice
elsif answer == ‘quit’
break
else
puts “Please type ‘roll’ or ‘quit’.”
end
end

On Tue, Sep 24, 2013 at 2:48 PM, Mike V. [email protected]
wrote:

The thing is, I’m not sure how to add that kind of functionality to my
program yet. Thoughts and suggestions are appreciated. Thanks!

You need to do two things:

  1. Add another prompt before the while loop which asks for number of
    dice, reads the user input and converts it to an integer value.
  2. Use the integer value inside the loop where you print out results
    of rolling dice to do so repeatedly (e.g. by using method
    Fixnum#times).

Does that help?

Kind regards

robert

You could use an Array of Dice, based on the number given by the user:

puts ‘Enter the number of dice to use’
number = Integer( gets )
@dice = Array.new( number, Dice.new )

ask about rolling, etc…

puts @dice.map { |die| die.rolled_dice }

On Tue, Sep 24, 2013 at 4:49 PM, Joel P. [email protected]
wrote:

You could use an Array of Dice, based on the number given by the user:

puts ‘Enter the number of dice to use’
number = Integer( gets )
@dice = Array.new( number, Dice.new )

ask about rolling, etc…

puts @dice.map { |die| die.rolled_dice }

The way Dice is implemented it does not make sense to have more than
one of them.

Kind regards

robert

Thanks Robert and Joel for your suggestions. It forced me to browse some
Ruby functionality online. In the end, I went with Robert’s suggestion.
Here is the code as it stands now:

The individual Die:

class Die
def roll_dice
1 + rand(6)
end
end

The program:

require_relative ‘die’

@die = Die.new

Ask user how many dice to roll

puts “How many dice would you like to roll?”

Store that value into a variable as an integer

number_of_dice = gets.chomp.to_i

Run a loop that allows to user to roll until they type quit

while true
puts “Please type ‘roll’ to roll the dice or ‘quit’ to quit.”
response = gets.chomp
if response == ‘roll’
rolling_dice = number_of_dice
puts

# Utilize number_of_dice variable to simulate multiple dice being
  rolled
while rolling_dice > 0
  puts @die.roll_dice
  rolling_dice -= 1
end

puts

elsif response == ‘quit’
break
else
puts “Please type ‘roll’ or ‘quit’.”
end
end

I’ve heard a little bit about the MVC structure. I recognize that the
command line output is my view, and for right now I’m not interested in
customizing that. However, I am curious to know if I’m following proper
form in terms of what code is in my controller (roll_dice.rb) and my
model (die.rb). Thoughts/comments/suggestions are always appreciated.

Thanks!

Robert K. wrote in post #1122292:

On Tue, Sep 24, 2013 at 4:49 PM, Joel P. [email protected]
wrote:

You could use an Array of Dice, based on the number given by the user:

puts ‘Enter the number of dice to use’
number = Integer( gets )
@dice = Array.new( number, Dice.new )

ask about rolling, etc…

puts @dice.map { |die| die.rolled_dice }

The way Dice is implemented it does not make sense to have more than
one of them.

Kind regards

robert

Fair point, I was thinking that if added complexity was required later -
e.g. dice maintaining their state - then an Array would be more
suitable.
As it stands there isn’t even a point in having a Die class, a single
method could do the job :slight_smile:

On Tue, Sep 24, 2013 at 10:09 PM, Joel P. [email protected]
wrote:

puts @dice.map { |die| die.rolled_dice }

The way Dice is implemented it does not make sense to have more than
one of them.

Fair point, I was thinking that if added complexity was required later -
e.g. dice maintaining their state - then an Array would be more
suitable.
As it stands there isn’t even a point in having a Die class, a single
method could do the job :slight_smile:

Absolutely. One could even wonder whether this problem warrants a
method of its own. :slight_smile:

There are two more remarks I forgot in my previous post:

  1. instead of if…elsif a case construct would also fit nicely.
  2. Endless loop can be done with loop and a block. Or we can place the
    loop body in the where condition. Better still use a loop which test
    the condition at the end

Ask user how many dice to roll

puts “How many dice would you like to roll?”

Store that value into a variable as an integer

number_of_dice = Integer(gets)

1 while puts “Please type ‘roll’ or ‘quit’.” or
case gets.chomp
when ‘roll’
number_of_dice.times { puts 1+rand(6) }
when ‘quit’
false
else
true
end

I admit, this is a bit weird way to do it. :slight_smile: A more conservative
approach might be

begin
puts “Please type ‘roll’ or ‘quit’.”
go = case gets.chomp
when ‘roll’
number_of_dice.times { puts 1+rand(6) }
when ‘quit’
false
else
true
end
end while go

Cheers

robert

On Tue, Sep 24, 2013 at 9:38 PM, Mike V. [email protected]
wrote:

end

Store that value into a variable as an integer

number_of_dice = gets.chomp.to_i

Disadvantage of #to_i vs. Integer() is that #to_i will happily convert
whatever it sees and you won’t notice errors - you end up wondering
why there is no output because the default value is 0. So better do
what Joel suggested (#chomp is not needed).

number_of_dice = Integer(gets)

while rolling_dice > 0
  puts @die.roll_dice
  rolling_dice -= 1
end

You can abbreviate the loop to

number_of_dice.times { puts @die.roo_dice }

command line output is my view, and for right now I’m not interested in
customizing that. However, I am curious to know if I’m following proper
form in terms of what code is in my controller (roll_dice.rb) and my
model (die.rb). Thoughts/comments/suggestions are always appreciated.

Generally for such a console application the term MVC is not used so
it feels a bit awkward here. But I think you got it about right.
Some things which are unusual:

  • Your model does not have state.
  • Your model does not notify anybody of state changes (well, since
    there is no state, it cannot change :-))
  • There are no events because the structure of interactions is fixed
    (opposed to graphical user interfaces where the user can click on this
    button or enter text in an input field or close the window or…).

Kind regards

robert