Thanks Joe.
Slowly but surely figuring out those idioms. I’m also reading Sandy
Metz’ book,
which is helping me get a handle on some fundamental OOP concepts. I
still find myself falling
back on clunky code.
I have 4 problems (at least those that I’m aware of!)
1- Class variables. I can’t find a way to maintain a record of the state
of the ‘marker’ to determine whether the point has been established
(and the value of that point) without using class variables.
2- PitBoss. I feel like this is the key. I’m creating an instance of
PitBoss with every roll. If I instantiate
him one time, will that solve my problem? Can’t wrap my mind around
that.
3- Memory. Does the Ruby interpreter collect garbage automatically.
Every time I go through that loop in
Craps::Croupier.play, aren’t I using up more of the heap?
4- Please feel free to blast away at my evaluate_roll method. I’m sure
there’s a way to make it better.
Here’s the code:
module Craps
runs the game
class Croupier
def self.play
while true
puts
puts 'Roll the dice? Y or N'
ans=gets.chomp.upcase
if ans== 'Y'
pit_boss=Craps::PitBoss.new
pit_boss.say_something
Craps::Croupier.new.round(pit_boss)
elsif ans == 'N'
puts 'OK, bye!'
break
else
puts 'Invalid input.'
end
end
end
def round (pit_boss)
die = Craps::Die.new
puts "#{die} = #{die.score}" #shows each die and dice total
pit_boss.evaluate_roll(die.score)
end
end
class PitBoss #evaluates each roll
@@marker = "OFF" #hate to use a class var here, but can't figure
out how to otherwise keep track of the marker
@@point_value = nil
POINTS = {
2 => 2,
3 => 3,
4 => 4,
5 => 5,
6 => 6,
8 => 8,
9 => 9,
10 => 10,
11 => 11,
12 => 12
}
def self.marker_state #reader- don't really need this at this phase
@@marker
end
def self.marker_state=(val) #writer- don't really need this at this
phase
@@marker=val
end
def say_something
puts “Hi from the Pit Boss”
end
def evaluate_roll(score)
if @@marker == "ON" #if the point is already established by 'come
out roll’
if score == @@point_value
puts "You hit the point!"
@@marker = "OFF"
@@point_value = 0
:won
elsif score == 7
puts "You 7'd out!"
@@marker = "OFF"
@@point_value = 0
:lost
else
POINTS[score]
end
else # if this is the 'come out roll and @@marker is "OFF"'
if [2,3,12].include?(score)
puts "Craps!"
:lost
elsif [7,11].include?(score)
puts "Shooter wins! "
:won
else
@@marker="ON"
@@point_value= score
puts "The point is now set to #{@@point_value}"
end
end
end
end
class Die
#The die only passes the score back to round, which then passes it to
the PitBoss class
#to evaluate the roll.
def self.roll_dice
rand(1..6)
end
attr_reader :first_dice, :second_dice
def initialize
@first_dice, @second_dice = Die.roll_dice, Die.roll_dice
end
def score
self.first_dice + self.second_dice
end
def to_s
"You rolled #{self.first_dice} and #{self.second_dice}"
end
end
end
Craps::Croupier.play
Joe Gain wrote in post #1183309:
Hi Lazlo,
yes, that’s right, logically it’s the same. Because ruby’s dynamic you
find this kind of logic a lot: Can I call the method I want to on this
object? Is this object null? etc.
The logical “or” operator ‘||’ is often used to ensure that an object
exists and if it doesn’t create a default object.
It’s slightly related to what James wrote above. If objects know how to
print themselves, by having a public to_s method, you get to use all the
methods (like puts), which expect objects to have such a method.
Sounds kind of a bit stupid, but it’s a very powerful technique.