Skip to content

Instantly share code, notes, and snippets.

@danielpclark
Last active August 29, 2015 14:10
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save danielpclark/5fe66c2685999c71e80e to your computer and use it in GitHub Desktop.
Save danielpclark/5fe66c2685999c71e80e to your computer and use it in GitHub Desktop.
What would be the best way to handle many instance variables handling state in a class?

My IDE says my game class has too many instance variables. I'm curious as to how it 'should' be? I could re-implement it into a hash or maybe a struct object. But I'm not sure that makes it any better. The variables are specific state that belong to the game. Would refactoring lead to some being memoized? Maybe some variables moved into a "rule-set" struct? What patterns apply to initializing multiple variables handling state?

class TonkGame
  def initialize
    @max_players = 5
    @min_players = 2
    @players = []
    @bet = 1
    @tonk = Game.new
    @face_up = []
    @turn = nil
    @over = false
    @round = 0
  end
# ...
end
@danielpclark
Copy link
Author

Just thinking out loud... I could have a GameTable object which contains no rules but would be a sensible object to hold players seated and cards in the center of the table.

A Player object could hold a default bet. Player already hold cards in hand.

turn, round , and over are specific game states. Possibly leave these alone?

min and max players could possibly go into a simple rule-set struct.

I seem to just be shuffling things around. Is that good? Many things to consider.

@danielpclark
Copy link
Author

player_limit = Struct.new(:min,:max,:players) {def playable?; (min..max) === players; end}.new(2,5)
player_limit.players = 1
player_limit.playable?
# => false
player_limit.players = 2
player_limit.playable?
# => true
player_limit.players = 6
player_limit.playable?
# => false

Maybe I should change this to the GameTable and actually "seat" Player instances within an Array in this struct.

@danielpclark
Copy link
Author

table = Struct.new(:min,:max,:players) {
  def playable?; (min..max) === Array(players).count; end
  def join(player); self.players = Array(self.players) << player; end
}.new(2,5)
table.join Player.new
table.join Player.new
table.playable?
# => true

@danielpclark
Copy link
Author

Table = Struct.new(:min,:max,:players,:face_up) {
  def playable?; (min..max) === Array(players).count; end
  def join(player); self.players = Array(players) << player; end
  def discard(card); self.face_up = Array(face_up) << card; end
  def discard?; Array(face_up).last; end
}
class TonkGame
  def initialize
    @table = Table.new(2,5)
    @bet = 1
    @tonk = Game.new
    @turn = nil
    @over = false
    @round = 0
  end
# ...
end

This frees up 4 to 1.

@danielpclark
Copy link
Author

I'm thinking of creating an Object that behaves similar to what Enumerable does for Ruby. I'll call it Rotation. It can handle player turn and table round. Implemented with cycling on table.players object using "Count iteration on the Enumerable cycle" for iteration counting. That will extract two instance variables out to one object which will be in charge of all game rotation features.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment