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.