Skip to content

Instantly share code, notes, and snippets.

@CodePint
Created July 2, 2018 03:18
Show Gist options
  • Save CodePint/238bbc4603b15f45e78517936e44d538 to your computer and use it in GitHub Desktop.
Save CodePint/238bbc4603b15f45e78517936e44d538 to your computer and use it in GitHub Desktop.
## Simple poker hand comparison ##
require 'pry'
FACE = ["A", "2", "3", "4", "5", "6", "7", "8", "9", "T", "J", "Q", "K" ]
SUITS = ["S", "H", "D", "C"]
class Deck
attr_accessor :cards, :discards
def initialize
@cards = []
@discards = []
FACE.each do |face|
SUITS.each do |suit|
@cards << face+suit
end
end
self.shuffle
end
def shuffle
@cards = @cards.shuffle!
end
def count
@cards.count
end
def draw_hand
@cards.pop(5).join(" ")
end
end
class Hand
include Comparable
attr_accessor :cards, :possible_hands, :highest_hand, :check_low, :duplicates, :flushes, :straight, :highest_card, :remaining_cards
# runs the card transformation, analyses the cards, checks for possible hands
def setup
puts "setup running"
@cards = @cards.split(" ")
@check_low = self.check_low_straight
numerical_cards_map
transform_values
analyze_cards
check_possible_hands
find_highest_hand
end
def initialize(cards)
@cards = cards
@possible_hands = []
self.setup
end
@@values = {
high_card: 1,
pair: 2,
two_pair: 3,
three_of_a_kind: 4,
straight: 5,
flush: 6,
full_house: 7,
four_of_a_kind: 8,
straight_flush: 9,
royal_flush: 10,
}
def find_highest_hand
@highest_hand = possible_hands.sort_by {|hand| hand[:value]}.last
end
####################################################################################################
## Running comparisons of hands and high cards and kickers
# the result of this function is the win/lose/draw result for self
# Win should return the integer `1`
# Loss should return the integer `2`
# Tie should return the integer `3`
def compare_hands(other)
#binding.pry
if self.highest_hand[:value] > other.highest_hand[:value]
# Win
return 1
elsif self.highest_hand[:value] < other.highest_hand[:value]
# Loss
return 2
elsif self.highest_hand[:value] == other.highest_hand[:value]
binding.pry
# Draw
if self.highest_hand[:type] == ("royal_flush" || "straight_flush" || "flush" || "straight")
return check_highs_cards(other)
elsif self.highest_hand[:type] == ("high_card" || "pair" || "two_pair" || "three_of_a_kind" || "full_house" || "four_of_a_kind")
binding.pry
return check_high_cards_then_kicker(other)
end
end
end
# checking the high card if the highest_hand[:value] is a draw for specified hand types
def check_highs_cards(other)
if self.highest_hand[:high_card][:value] > other.highest_hand[:high_card][:value]
# Win
return 1
elsif self.highest_hand[:high_card][:value] < other.highest_hand[:high_card][:value]
# Loss
return 2
elsif self.highest_hand[:high_card][:value] == other.highest_hand[:high_card][:value]
# draw
return 3
end
end
# checking the high card and then the kickers if the highest_hand[:value] is a draw for specified hand types
def check_high_cards_then_kicker(other)
#binding.pry
if self.highest_hand[:type] == "full_house"
return compare_full_house(other)
elsif self.highest_hand[:type] == "two_pair"
return compare_two_pair(other)
else
return compare_duplicates(other)
end
end
# comparing high card and of a kinds
def compare_duplicates(other)
binding.pry
self_hand = self.highest_hand[:contents].first.first
other_hand = other.highest_hand[:contents].first.first
if self_hand > other_hand
return 1
elsif self_hand < other_hand
return 2
elsif self_hand == other_hand
return check_kickers(other)
end
end
# comparing kickers
def check_kickers(other)
self.highest_hand[:high_cards].reverse!
other.highest_hand[:high_cards].reverse!
return_value = nil
self.highest_hand[:high_cards].each do |self_card|
other.highest_hand[:high_cards].each do |other_card|
if self_card > other_card
return_value = 1
elsif self_card < other_card
return_value = 2
end
end
return_value ||= 3
return return_value
end
end
def compare_two_pair(other)
self_high_pair = self.highest_hand[:contents].max_by{|k,v| v}.first
other_high_pair = other.highest_hand[:contents].max_by{|k,v| v}.first
if self_high_pair > other_high_pair
return 1
elsif self_high_pair < other_high_pair
return 2
elsif self_high_pair == other_high_pair
self_low_pair = self.highest_hand[:contents].min_by{|k,v| v}.first
other_low_pair = other.highest_hand[:contents].min_by{|k,v| v}.first
if self_low_pair > other_low_pair
return 1
elsif self_low_pair < other_low_pair
return 2
elsif self_low_pair == other_low_pair
return check_kickers
end
end
end
def compare_full_house(other)
self_three_of_a_kind = self.possible_hands.find {|hand| hand[:type] == 'three_of_a_kind' }
other_three_of_a_kind = other.possible_hands.find {|hand| hand[:type] == 'three_of_a_kind' }
if self_three_of_a_kind > other_three_of_a_kind
return 1
elsif self_three_of_a_kind < other_three_of_a_kind
return 2
elsif self_three_of_a_kind == other_three_of_a_kind
self_pair = self.possible_hands.find {|hand| hand[:type] == 'pair' }
other_pair = other.possible_hands.find {|hand| hand[:type] == 'pair' }
if self_pair > other_pair
return 1
elsif self_pair < other_pair
return 2
elsif self_pair == other_pair
return 3
end
end
end
#################################################################################
# turning each card into a value/suit hash
def numerical_cards_map
card_map = []
@cards.map do |card|
card_map << {face: card[0], suit: card[1]}
end
@cards = card_map
end
# transforming the value into an integer
def transform_values
@cards.each do |card|
case card[:face]
when "T"
card[:value] = 10
when "J"
card[:value] = 11
when "Q"
card[:value] = 12
when "K"
card[:value] = 13
when "A"
if @check_low
card[:value] = 1
else
card[:value] = 14
end
else
card[:value] = card[:face].to_i
end
end
end
# checking if the hand contains a low straight (only instance where ace value should be low)
def check_low_straight
low_straight = ["A", "2", "3", "4", "5"]
number_only_cards = @cards.map {|c| c[0]}
if (number_only_cards & low_straight) == low_straight
return true
else
return false
end
end
# finding duplicate counts for cards in hand
def find_duplicates
@duplicates = @cards.each_with_object(Hash.new(0)) {|h1, h2| h2[h1[:value]] +=1}
end
# finding the remaining cards after duplicates/high card
def find_remaining_cards
@remaining_cards = @duplicates.select {|key, value| value == 1}.map{|k,v| k}.sort
end
# finding counts for flushes
def find_flushes
@flushes = @cards.each_with_object(Hash.new(0)) {|h1, h2| h2[h1[:suit]] +=1}
end
# finding out if the hand contains a straight and what its high is.
def find_straights
@straight = Array.new
@cards.each_with_index do |card, index|
if index == (@cards.length - 1)
@straight << card
elsif (card[:value] + 1) == (@cards[index+1][:value])
@straight << card
end
end
end
# finding the highest card for all hands not relying on duplicates
def find_highest_card
@highest_card = @cards.max_by {|card| card[:value]}
end
# check if the player has a flush
def is_flush?
if @flushes.length == 1
if !@possible_hands.any? {|hand| hand[:type] == "flush"}
@possible_hands << {type: "flush", contents: @flushes, high_card: @highest_card, value: @@values[:flush]}
end
return true
end
end
# check if the player has a straight
def is_straight?
if @straight.length == 5
if !@possible_hands.any? {|hand| hand[:type] == "straight"}
@possible_hands << {type: "straight", contents: @straight, high_card: @highest_card, value: @@values[:straight]}
end
return true
end
end
#check if the player has a full house
def is_full_house?
if is_pair? && is_three_of_a_kind?
if !@possible_hands.any? {|hand| hand[:type] == "full_house"}
@possible_hands << {type: "full_house", contents: @duplicates, high_card: @highest_card, value: @@values[:full_house]}
end
return true
end
end
# check if the player has a straight flush
def is_straight_flush?
if is_straight? && is_flush?
if !@possible_hands.any? {|hand| hand[:type] == "straight_flush"}
@possible_hands << {type: "straight_flush", contents: @straight, high_card: @highest_card, value: @@values[:straight_flush]}
end
return true
end
end
# check if the player has a royal flush
def is_royal_flush?
if is_straight? && is_flush? && (@highest_card[:value] == 14)
if !@possible_hands.any? {|hand| hand[:type] == "royal_flush"}
@possible_hands << {type: "royal_flush", contents: @straight, high_card: @highest_card, value: @@values[:royal_flush]}
end
return true
end
end
# check if the player has two of a kind
def is_pair?
twos = @duplicates.select {|key, value| value == 2}
if twos.length == 1
if !@possible_hands.any? {|hand| hand[:type] == "pair"}
@possible_hands << {type: "pair", contents: twos, high_cards: @remaining_cards, value: @@values[:pair]}
end
return true
end
end
# check if the player has two pairs
def is_two_pair?
twos = @duplicates.select {|key, value| value == 2}
if twos.length == 2
if !@possible_hands.any? {|hand| hand[:type] == "two_pair"}
@possible_hands << {type: "two_pair", contents: twos, high_cards: @remaining_cards, value: @@values[:two_pair]}
end
return true
end
end
# check if the player has three of a kind
def is_three_of_a_kind?
threes = @duplicates.select {|key, value| value == 3}
if !threes.empty?
if !@possible_hands.any? {|hand| hand[:type] == "three_of_a_kind"}
@possible_hands << {type: "three_of_a_kind", contents: threes, high_cards: @remaining_cards, value: @@values[:three_of_a_kind] }
end
return true
end
end
# check if the player has four of a kind
def is_four_of_a_kind?
fours = @duplicates.select {|key, value| value == 4}
if !fours.empty?
if !@possible_hands.any? {|hand| hand[:type] == "four_of_a_kind"}
@possible_hands << {type: "four_of_a_kind", contents: fours, high_cards: @remaining_cards}
end
return true
end
end
# setting the high card value and leaving the remaining cards as kickers
def high_card
high_card = @duplicates.max_by {|k,v| v}.first
high_card = {high_card => 1}
if !@possible_hands.any? {|hand| hand[:type] == "high_card"}
@possible_hands << {type: "high_card", contents: high_card, high_cards: @remaining_cards[0..3], value: @@values[:high_card] }
end
end
def analyze_cards
find_duplicates
find_remaining_cards
find_flushes
find_straights
find_highest_card
find_remaining_cards
end
def check_possible_hands
is_flush?
is_straight?
is_straight_flush?
is_royal_flush?
is_pair?
is_two_pair?
is_three_of_a_kind?
is_four_of_a_kind?
is_full_house?
high_card
end
end
deck = Deck.new
hand_1 = Hand.new(deck.draw_hand)
hand_2 = Hand.new(deck.draw_hand)
hand_straight = Hand.new("3C 4D 5S 6D 7H")
low_straight_hand = Hand.new("AC 2D 3S 4D 5H")
high_ace_hand = Hand.new("AS 5H KD JS 8H")
flush_hand = Hand.new("AS QS KS TS JS")
straight_flush = Hand.new("3S 4S 5S 6S 7S")
royal_flush = Hand.new("TH JH QH KH AH")
high_card_other = Hand.new("AH 3D 6C JH 9S")
high_card_self = Hand.new("AS 3D 6C TH 9S")
#puts high_card_self.compare_hands(high_card_other)
pair_self = Hand.new("5C 5H 8D 9D JH")
pair_other = Hand.new("6H 6S KD 9H 3H")
puts pair_self.compare_hands(pair_other)
print "---------------------"
binding.pry
puts "break"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment