If you’re going to keep state in a local variable, then you need to keep
looping within that method, because otherwise the value will be lost as
soon
as you return from it.
A much more common Ruby idiom for keeping state is to use an instance
variable:
class Game
def initialize
@state = 0
@playing = true
end
def playing?
@playing
end
def next_action
case @state
when 0
puts "Nephlen".blue
...
@state = 1
...
end
end
end
g = Game.new
while g.playing?
g.next_action
end
This lets you create multiple game instances each with independent state
(useful for a multi-player server!) and also makes unit testing much
easier.
A neat trick to avoid the big case statement is to use dynamic method
dispatch:
class Game
def initialize
@state = :startup
end
def next_action
send(@state) # calls the method name in the @state instance
variable
end
def startup
puts "Hello!"
puts "Moving to dungeon entrance"
@state = :dungeon
end
def dungeon
puts "You are in a deep dungeon. Go N/S/E/W?"
case gets
when /^n/i
@state = :field
when /^s/i
@state = :tunnel
when /^e/i
@state = :monster
when /^w/i
@state = :monster
else
puts "Invalid selection"
end
end
def monster
puts "You have been eaten by a monster!"
end
... etc
end
For security reasons, make sure that an untrusted party can’t set the
@state
variable directly, e.g. by copying @state directly from a user input
field
or web form.
Regards,
Brian.