I am trying to build a mastermind game, and I am hoping to have my code instance its own objects containing information about the place and color of the step in the passcode. This is so I can vary the length of the passcode without hard coding it. Is there a way to keep track of these objects, seeing as I am not personally assigning a variable? Can my program assign the instances their own variable names, and if so how would I do that?
#Builder for password objects
class ColorPicks
attr_reader :color, :place
def initialize(color, place)
@color = color
@place = place
end
end
# Determines how long the password should be
module StartUp
def self.how_many
@how_many
end
def HowManyColors
p "How long should the computer's code be?"
@how_many = gets.chomp.to_i
end
end
#Instances the password objects from ColorPicks
class Printer
include StartUp
@@i = StartUp.how_many
@@place = 1
COLORS = {1 => 'red', 2 => 'blue', 3 => 'green'}
def self.code_maker
for a in 1..@@i do
number_of_colors = COLORS.length
random_number = rand(number_of_colors)
ColorPicks.new(COLORS[random_number], @@place)
@@place = 1
end
end
end
PS. Sorry, I am new to programming.
CodePudding user response:
References to objects are stored in variables, like the instance variable @color
in your ColorPicks
class. Only the instance itself can access the instance variable directly. Other objects can only access it indirectly via method calls, e.g. attr_reader :color
creates a color
method that returns the object, @color
is referring to.
If you want to store a variable number of objects, you typically use a collection like Array
, Hash
or Set
. Instead of assigning every single object to a separate variable, you add the objects to the collection and just assign the collection to a variable, e.g.
class CodeGenerator
COLORS = %w[red green blue]
attr_reader :code
def initialize(size)
@code = Array.new(size) { COLORS.sample }
end
end
Example usage:
generator = CodeGenerator.new(5)
generator.code
#=> ["blue", "green", "red", "blue", "red"]
The object returned by generator.code
is the array we assigned to @code
in initialize
. To access individual objects in the collection, you can use Array#[]
: (note that arrays are zero based in Ruby)
generator.code[0] #=> "blue"
generator.code[1] #=> "green"
In the above example, I'm using plain strings to keep the code simple. The concept however applies to all objects, i.e. you could just as well add instances of ColorPicks
instead of strings. You also don't have to use the Array.new
constructor to build an array. It's perfectly fine to start with an empty array and to add your items in a loop one after another, e.g.:
def initialize(size)
@code = []
(1..size).each do |i|
@code << ColorPicks.new(COLORS.sample, i)
end
end
CodePudding user response:
You could write some variant the following, where all instances created are saved to an array held by a class instance variable.
class ColorPicks
@instances = []
class << self
attr_reader :instances
end
attr_reader :color, :place
def initialize(color, place)
self.class.instances << self
@color = color
@place = place
end
end
Note that @instances
is a class instance variable and its getter is created in ColorPick
's singleton class.
Create an instance.
stefan = ColorPicks.new("blue", "Bremen")
#=> <ColorPicks:0x00007fba7bb29958 @color="blue", @place="Bremen">
Then,
stefan.color
#=> "blue"
stefan.place
#=> "Bremen"
We can now see the instances of ColorPicks
that have been created:
ColorPicks.instances
#=> [#<ColorPicks:0x00007fba7bb29958 @color="blue", @place="Bremen">]
Now create a second instance. cary = ColorPicks.new("blue", "Victoria") #=> #<ColorPicks:0x00007fba7babc7e0 @color="blue", @place="Victoria">
Then,
cary.color
#=> "violet"
cary.place
#=> "Victoria"
Now,
ColorPicks.instances
#=> [#<ColorPicks:0x00007fba7bb29958 @color="blue", @place="Bremen">,
#=> #<ColorPicks:0x00007fba7babc7e0 @color="Violet", @place="Victoria">]