carolineartz
1/20/2014 - 7:27 AM

Working off your previous Die class from Die Class 1, implement a new Die class which takes an array of strings as its input. When Die#roll

Working off your previous Die class from Die Class 1, implement a new Die class which takes an array of strings as its input. When Die#roll is called, it randomly returns one of these strings. If Die.new is passed an empty array, raise an ArgumentError. It should work like this:

die = Die.new(['A', 'B', 'C', 'D', 'E', 'F’]) die.sides # still returns the number of sides, in this case 6 die.roll # returns one of ['A', 'B', 'C', 'D', 'E', 'F'], randomly

Just to reiterate, in the previous exercise you passed in a number of sides, sides, and the labels were assumed to be the integers 1..sides. Now we're passing in a list of arbitrary labels. We could use this to represent a Dreidel or Boggle dice, for example.

#######################################PSEUDOCODE###################################

# INPUT, OUTPUT & PSEUDOCODE:
# Initialize =>       INPUT: array of strings (labels)
#                     OUTPUT: new Die object
#                       a. raises argument error if passed an empty array
#                       b. Creates instance variabel for labels
# Die#sides   =>      INPUT: none
#                     OUTPUT: number of sides
#                        a. calculate and return size of labels array
# Die#roll    =>      INPUT: none
#                     OUTPUT: random item from array of labels
#                       a.  select random element from label array
#                       b. return element

###################################INITIAL CODE#####################################

class Die
  def initialize(labels)
    raise ArgumentError.new("cannot pass empty array") if labels.empty?
    @labels = labels
  end

  def sides
   return @labels.length
  end

  def roll
    return @labels[rand(self.sides)]
  end
end


####################################REFACTORED CODE#################################

class Die
  def initialize(labels)
    raise ArgumentError.new("cannot pass empty array") if labels.empty?
    @labels = labels
  end

  def sides
   @labels.length
  end

  def roll
    @labels[rand(self.sides)]
  end
end

###################################DRIVER CODE######################################

sides = ('a'..'z') #labels for sides

some_die = Die.new(sides.to_a)
p some_die.sides == sides.to_a.length #true if Die#sides outputs the correct number of sides
p sides.cover?(some_die.roll) #true if roll outcome is covered by side labels

# #need unit testing framework e.g., rspect, TEST::UNIT -> assert_raise ?

###################################REFLECTION#######################################

# I found this challenge quite manageable thanks to the previous Die class and a productive pair
# session with Michael. Once things were on paper, modeling methods from the first Die class, teh
# main question was whether one/both attr_accessor could replace the side methods as the attr_reader
# could for Die class 1. Michael was helpful in gaining a deeper understanding the attr_accessor methods.
# Ultimately, we decided #sides functions outside the scope of the attr_accessors. I don't think much 
# refactoring is needed, but we removed the unneeded explicit returns to tidy things up.