joncodo / Crib

A crib engine to play the card game crib with AI and a card counter
3 stars 2 forks source link

counter.rb: Code Review #3

Closed scott-steadman closed 10 years ago

scott-steadman commented 10 years ago

I'm experimenting with making each review point a separate comment...

scott-steadman commented 10 years ago

Rename the class/file from Counter to Hand. Reason: Use terms from the problem domain. This class looks like it does what a card hand does.

scott-steadman commented 10 years ago

Rename the hand attribute to cards Reason: A hand contains cards.

scott-steadman commented 10 years ago

Rename calculate_score to score and memoize result. Reason: You only need to calculate the score once. Example:

def score
  @score ||= pairs_score + flush_score + fifteen_score + right_jack_score + runs_score
end
scott-steadman commented 10 years ago

Privatize other *_score methods. Reason: Keep your cards interface simple by not exposing more than you have to.

scott-steadman commented 10 years ago

I think Spaid should be spelled Spade

scott-steadman commented 10 years ago

Create a private all_cards method. Reason: DRY.

Example:

def all_cards
  @all_cards ||= cards + top_card
end

Then you can get rid of all your all_cards = cards << top_card calls, and just use all_cards wherever you need them.

joncodo commented 10 years ago

Wow. Thanks so much for doing this.

scott-steadman commented 10 years ago

My pleasure. I'm a big fan of code reviews. :)

scott-steadman commented 10 years ago

Use a has to accumulate suit counts in flush_score. Reason: You can do the same thing in less code.

Cons: This may be less readable to you.

def flush_score
  counts_by_suit = Hash.new(0)

  all_cards.each do |card|
    counts_by_suit[card.suit] += 1
  end

  score = counts_by_suit.values.max
  ...
end
scott-steadman commented 10 years ago

Clean up fifteen_score method Reason: improve readability.

Example code:

def fifteen_score
  two_card_combo_score + three_card_combo_score + four_card_combo_score + five_card_combo_score
end

def two_card_combo_core
...
end
...

If calculating the combo scores can be parameterized, then you can try the following:

def fifteen_score
  [2,3,4,5].inject(0) {|score, combo| score += calculate_combo_score(combo)}
end

def calculate_combo_score(combo, sum=15)
...
end
scott-steadman commented 10 years ago

Don't use hand.each use hand.any? in right_hand_jack score Reason: Needless looping through cards after match found

Example code:

def right_hand_jack_score
  return 1 if hand.any? {|card| card.jack? and card.same_suit?(top_card.suit)}
  return 0
end