Created
July 2, 2018 03:18
-
-
Save CodePint/238bbc4603b15f45e78517936e44d538 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
## 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