# Texas Hold'Em

This post is my solution to Texas Hold’Em. The problem involved taking 7 cards and determining the single best 5 card hand. Like the previous problem, I decided to implement this in Ruby. I probably went too far because what I ended up with was a command line program that when you hit the enter key you see a print out of the 7 cards dealt and the best hand from those cards, not to mention a lot more code than I originally thought I was going to write. To me this seems like a classic Dynamic Programming problem, so that was the direction I went.
The first thing I did after dealing a hand was to sort the cards numerically. By virtue of the fact that the cards will only go up in value, it is much easier to rule out what kind of hand is possible just by the position of the cards. We simply take two cards away at time figure out the hand of the five remaining cards and store the results. After that we loop over the results and only keep the highest scoring hand. What follows is the main class that can be run from the command line.

texasholdem.rb:

``````require 'deck'
require 'card'
require 'player'

card_deck = Deck.new
keep_running = true

while keep_running
results = {}
card_deck.shuffle
seven_cards = card_deck.deal
seven_cards.sort!
copy = Array.new(seven_cards)

puts "Press enter to deal cards.."
line = gets

if line.chop == "quit"
keep_running = false
else
for i in 0..5
for j in i..5
copy.delete_at(i)
copy.delete_at(j)
hand = Player.check_hand(copy,0,0,nil)
if results[hand]
copy = Player.compare_hands(copy, results[hand], 4)
end
results[hand] = copy
copy = Array.new(seven_cards)
end
copy = Array.new(seven_cards)
end

max_score = -1
winning_hand = nil
best_cards = nil
results.each do |hand, cards|
score = Player.ranks[hand]
score = score.nil? ? cards.value : score
if score > max_score
max_score = score
score = Player.ranks[hand]
best_cards = cards
winning_hand = hand
end
end
puts "Best hand from #{seven_cards.join(", ")} "
puts "\n\t #{winning_hand} : #{best_cards.join(", ")}"
end

end
``````

The Player class recursively goes through the five cards in question to determine the hand, returning the last card in the array if no other hand is determined. The Player class also contains a method for breaking ties of the same hand by comparing the values of the cards.

player.rb:

``````require 'card'

class Player

STRAIGHT="straight"
STRAIGHT_FLUSH="straight flush"
PAIR = "pair"
TWO_PAIR ="two pair"
FLUSH = "flush"
FULL_HOUSE = "full house"
THREE_KIND = "3 of a kind"
FOUR_KIND = "4 of a kind"
@@ranks =  {STRAIGHT_FLUSH=>22,FOUR_KIND=>22,FULL_HOUSE=>21,FLUSH=>20,STRAIGHT=>19,THREE_KIND=>18,TWO_PAIR=>17,PAIR=>16}

def initialize

end

def self.ranks
@@ranks
end
def self.compare_hands(hand,other_hand, index)
if index < 0
return hand
elsif hand[index].value > other_hand[index].value
return hand
elsif hand[index].value < other_hand[index].value
return other_hand
else
compare_hands(hand,other_hand,index-1)
end
end

def self.check_hand(cards,index,match_index,current_hand)
if(index+1 < cards.length)
if cards[index].eq?(cards[index+1])
current_hand = hand_eq(current_hand,(index-match_index)<=1)
match_index = index
elsif cards[index].sequential?(cards[index+1])
current_hand = hand_seq(current_hand,index)
elsif current_hand == STRAIGHT
current_hand = nil
end
current_hand = check_hand(cards,index+1,match_index,current_hand)
end
current_hand = check_flush(cards,current_hand)

if current_hand.nil?
current_hand = cards
end
current_hand
end

private

def self.check_flush(cards,current_hand)
if current_hand != FULL_HOUSE && current_hand != FOUR_KIND && current_hand != STRAIGHT_FLUSH && current_hand != FLUSH
suits_match = true
for i in 0..3
if cards[i].suit != cards[i+1].suit
suits_match = false
end
end
if suits_match
current_hand = (current_hand == STRAIGHT) ? STRAIGHT_FLUSH : FLUSH
end
end
current_hand
end

def self.hand_eq(current_hand, sequential)
case current_hand
when nil
hand = PAIR
when PAIR
if sequential
hand = THREE_KIND
else
hand = TWO_PAIR
end
when TWO_PAIR
hand = FULL_HOUSE
when STRAIGHT
hand = PAIR
when THREE_KIND
if sequential
hand = FOUR_KIND
else
hand = FULL_HOUSE
end

else
hand = current_hand
end
hand
end

def self.hand_seq(current_hand,current_index)
case current_hand
when nil
if current_index == 0
hand = STRAIGHT
end
when STRAIGHT
hand = STRAIGHT
else
hand = current_hand
end
hand
end
end
``````

Finally there is a Card class and a Deck class. I’m not sure a separate classes are necessary as they definitely add to the total line count, but I think it makes the code cleaner and easier to read by abstracting away behavior into separate classes. For example the Deck class has deal and shuffle methods that to me make reading the code easier, so that is a trade off I am willing to take most of the time. card.rb:

``````class Card

def initialize (suit, face_value)
@suit = suit;
@face_value = face_value;
case @face_value
when "Jack"
@value = 11
when "Queen"
@value = 12
when "King"
@value = 13
when "Ace"
@value = 15
else
@value = @face_value.to_i
end
end

def eq? (other)
@value == other.value
end

def sequential? (other)
(@value + 1) == other.value
end

def <=> (other)
@value <=> other.value
end

def to_s
"#{@face_value} of #{@suit}s"
end
end
``````

deck.rb

``````require 'card'

class Deck
def initialize
@deck = []
values = ["2","3","4","5","6","7","8","9","10","Jack","Queen","King","Ace"]
suits.each do |suit|
values.each do |value|
@deck.push(Card.new(suit,value))
end
end
end

def to_s
@deck.join(',')
end

def deal
hand = []
start = rand(46)
index = -1
start.upto((start+6)) { |i| hand[index+=1] = @deck[i]; }
hand
end

def shuffle
@deck.shuffle!
end
end
``````