Skip to content
This repository has been archived by the owner on Oct 18, 2022. It is now read-only.

Allie's poker implementation #1

Open
wants to merge 49 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
525fe65
Change namespace from to-poker to poker
acreilly Dec 8, 2016
2c9535f
Set up base Poker::Card model with specs
acreilly Dec 8, 2016
a99294e
Added constants SUITS and RANKS with specs
acreilly Dec 8, 2016
0cc265f
Add deck file and require it
acreilly Dec 8, 2016
d873367
Make create! happen immediately on initialize. Added specs
acreilly Dec 8, 2016
10ff6cb
Add shuffle method with specs
acreilly Dec 8, 2016
a8ece76
Create number_value method
acreilly Dec 8, 2016
d0299d7
Set up hand model and #sets method to organize hand cards
acreilly Dec 8, 2016
5d437c0
Set up four_of_a_kind, three_of_a_kind and one pair with specs
acreilly Dec 8, 2016
391b4d1
Add two_pair? method with specs
acreilly Dec 8, 2016
f292d20
Add #straight? method with specs
acreilly Dec 8, 2016
9746382
Refactor one pair spec
Dec 8, 2016
e9641fd
Merge pull request #1 from gmacdougall/refactored-one-pair-spec
acreilly Dec 8, 2016
616dfbb
Move sets to private and remove its specs
acreilly Dec 8, 2016
d761a5e
Refactor four_of_a_kind? specs
acreilly Dec 8, 2016
f805452
Refactor straight? specs
acreilly Dec 8, 2016
6f028bb
Refactored three_of_a_kind? spec
acreilly Dec 8, 2016
537ce51
Refactored two_pair? spec
acreilly Dec 8, 2016
7632db0
Remove unused cyo_card method from specs
acreilly Dec 8, 2016
d720b2d
Add #flush? with specs
acreilly Dec 8, 2016
273f059
Set up specs for full_house?
acreilly Dec 8, 2016
2ac80f3
Full house implementation with testing
Dec 8, 2016
e142fbd
Merge pull request #2 from gmacdougall/full-house-implementation
acreilly Dec 8, 2016
e464e38
Implemented #straight_flush? with specs
acreilly Dec 8, 2016
989ca15
Fix #straight? method by checking for set key length to eq 5
acreilly Dec 8, 2016
cea868f
Refactor straight? to consider low ace options
acreilly Dec 8, 2016
9c847dd
Add #level to determine hand type
acreilly Dec 8, 2016
d455e03
Change contents to cards to make more sense and remove shuffle method…
acreilly Dec 8, 2016
504ca8e
Raise error if not enough cards are delt
acreilly Dec 8, 2016
f1c002c
Set up dealer, selects an array of winners in the case that there is …
acreilly Dec 8, 2016
a01fb9b
Cleaning up unused code/comments
acreilly Dec 8, 2016
2410bc1
Move frozen_string_literal to top line
acreilly Dec 9, 2016
525de7b
Refactor deal_round
acreilly Dec 9, 2016
4924ea5
Move creation of cards to initialize and remove create spec
acreilly Dec 9, 2016
9aa83c2
Include enumerable to add more methods to deck
acreilly Dec 9, 2016
75f6974
Remove error from poker hand and add custom error to poker dealer
acreilly Dec 9, 2016
944131c
Refactored sets and fixed all methods affected by refactor
acreilly Dec 9, 2016
e45d987
Change spec to match_array instead of include with wild card so it is…
acreilly Dec 9, 2016
fdb106b
Refactor #winner method significantly
acreilly Dec 9, 2016
1775059
Add comparable method to compare a hands rank to another, also added …
acreilly Dec 9, 2016
b963ee5
Install factory_girl
acreilly Dec 9, 2016
2e189e5
Set up hand factory
acreilly Dec 9, 2016
2c8ad02
Add specs to level
acreilly Dec 9, 2016
a841989
Refactor <=> method and add sorted_sets method, add passing specs
acreilly Dec 9, 2016
06c3a8f
Fix sorted_sets since it was not always sorting correctly
acreilly Dec 9, 2016
db1504a
Fix #winner method to utilize .max enumerable to select the winner
acreilly Dec 9, 2016
e06d697
Fix errors in factories
acreilly Dec 9, 2016
394fd9d
Refactor specs to be cleaner
acreilly Dec 9, 2016
182bd83
Add adjust_ace to sorted sets in case of low ace straight
acreilly Dec 9, 2016
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,23 @@ PATH
GEM
remote: https://rubygems.org/
specs:
activesupport (5.0.0.1)
concurrent-ruby (~> 1.0, >= 1.0.2)
i18n (~> 0.7)
minitest (~> 5.1)
tzinfo (~> 1.1)
binding_of_caller (0.7.2)
debug_inspector (>= 0.0.1)
coderay (1.1.1)
concurrent-ruby (1.0.2)
debug_inspector (0.0.2)
diff-lcs (1.2.5)
factory_girl (4.7.0)
activesupport (>= 3.0.0)
i18n (0.7.0)
interception (0.5)
method_source (0.8.2)
minitest (5.10.1)
pry (0.10.4)
coderay (~> 1.1.0)
method_source (~> 0.8.1)
Expand All @@ -39,16 +49,23 @@ GEM
rspec-support (~> 3.5.0)
rspec-support (3.5.0)
slop (3.6.0)
thread_safe (0.3.5)
tzinfo (1.2.2)
thread_safe (~> 0.1)
yard (0.9.5)

PLATFORMS
ruby

DEPENDENCIES
binding_of_caller
factory_girl
pry
pry-rescue
pry-stack_explorer
rspec (>= 3.5.0)
to-poker!
yard

BUNDLED WITH
1.13.6
9 changes: 9 additions & 0 deletions lib/poker.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# frozen_string_literal: true
require 'pry'
require 'poker/card'
require 'poker/deck'
require 'poker/hand'
require 'poker/dealer'
# Poker Top Level Library
module Poker
end
17 changes: 17 additions & 0 deletions lib/poker/card.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
module Poker
class Card
attr_reader :rank, :suit

RANKS = ['2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K', 'A']
SUITS = ['Hearts', 'Spades', 'Diamonds', 'Clubs']

def initialize(rank, suit)
@rank = rank
@suit = suit
end

def number_value
RANKS.index(rank) + 1
end
end
end
30 changes: 30 additions & 0 deletions lib/poker/dealer.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
module Poker
class Dealer
class EmptyDeckError < StandardError; end

attr_reader :deck, :hands

def initialize(num_players)
@num_players = num_players
@deck = Poker::Deck.new
@hands = []
end

def deal_round
@hands = Array.new(@num_players) { deal }
end

def winner
@hands.select { |hand| hand == @hands.max }
end


private

def deal
Poker::Hand.new(@deck.cards.pop(5))

raise EmptyDeckError if @deck.cards.empty?
end
end
end
20 changes: 20 additions & 0 deletions lib/poker/deck.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
module Poker
class Deck
include Enumerable

attr_reader :cards

def initialize
@cards = Poker::Card::RANKS.flat_map do |rank|
Poker::Card::SUITS.flat_map do |suit|
Poker::Card.new(rank, suit)
end
end.shuffle!
end

def each(&block)
@cards.each(&block)
end

end
end
109 changes: 109 additions & 0 deletions lib/poker/hand.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
module Poker
class Hand
include Comparable

def initialize(cards)
@cards = cards
@sets = sets
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The method in which this is memoized is a bit weird. We should contain this logic in the method below.

end

def straight_flush?
straight? && flush?
end

def four_of_a_kind?
of_a_kind?(4)
end

def full_house?
three_of_a_kind? && one_pair?
end

def flush?
@cards.map { |c| c.suit }.uniq.length == 1
end

def straight?
standard_straight? || ace_low_straight?
end

def three_of_a_kind?
of_a_kind?(3)
end

def two_pair?
one_pair? && @sets.select { |k,v| v == 2 }.length == 2
end

def one_pair?
of_a_kind?(2)
end

def of_a_kind?(number)
@sets.values.any? {|s| s == number }
end

def level
if straight_flush?
8
elsif four_of_a_kind?
7
elsif full_house?
6
elsif flush?
5
elsif straight?
4
elsif three_of_a_kind?
3
elsif two_pair?
2
elsif one_pair?
1
else
0
end
end

def <=>(other_hand)
lvl_compare = level <=> other_hand.level

return lvl_compare unless lvl_compare == 0

sorted_sets <=> other_hand.sorted_sets
end

def sorted_sets
# &:reverse makes sure that the hash sorts by value first then key
@sorted_sets = @sets.sort_by(&:reverse).reverse.to_h.keys

adjust_ace if ace_low_straight?

@sorted_sets
end

private

def standard_straight?
@sets.keys.length == 5 && @sets.keys == (@sets.keys.first..@sets.keys.last).to_a
end

def ace_low_straight?
sets.keys == [1, 2, 3, 4, 13]
end

def adjust_ace
@sorted_sets.shift
@sorted_sets.push(0)
end

def sets
sets = @cards.inject(Hash.new(0)) do |hash, card|
hash[card.number_value] += 1
hash
end

Hash[sets.sort]
end
end
end
5 changes: 0 additions & 5 deletions lib/to-poker.rb

This file was deleted.

145 changes: 145 additions & 0 deletions spec/factories/hand_factory.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
FactoryGirl.define do
factory :hand, class: Poker::Hand do
initialize_with do
ranks = Poker::Card::RANKS.shuffle
suits = Poker::Card::SUITS
new((0..4).map {|c| Poker::Card.new(ranks.pop, suits.sample) })
end
end

factory :straight_flush, class: Poker::Hand do
initialize_with do
new(
[
Poker::Card.new('2', 'Diamonds'),
Poker::Card.new('3', 'Diamonds'),
Poker::Card.new('4', 'Diamonds'),
Poker::Card.new('5', 'Diamonds'),
Poker::Card.new('6', 'Diamonds'),
]
)
end
end

factory :four_of_a_kind, class: Poker::Hand do
initialize_with do
new(
[
Poker::Card.new('2', 'Diamonds'),
Poker::Card.new('2', 'Spades'),
Poker::Card.new('2', 'Hearts'),
Poker::Card.new('5', 'Clubs'),
Poker::Card.new('2', 'Clubs'),
]
)
end
end

factory :full_house, class: Poker::Hand do
initialize_with do
new(
[
Poker::Card.new('7', 'Diamonds'),
Poker::Card.new('7', 'Hearts'),
Poker::Card.new('7', 'Spades'),
Poker::Card.new('8', 'Diamonds'),
Poker::Card.new('8', 'Spades'),
]
)
end
end

factory :flush, class: Poker::Hand do
initialize_with do
new(
[
Poker::Card.new('2', 'Hearts'),
Poker::Card.new('3', 'Hearts'),
Poker::Card.new('8', 'Hearts'),
Poker::Card.new('5', 'Hearts'),
Poker::Card.new('6', 'Hearts'),
]
)
end
end

factory :straight, class: Poker::Hand do
initialize_with do
new(
[
Poker::Card.new('2', 'Spades'),
Poker::Card.new('3', 'Spades'),
Poker::Card.new('4', 'Spades'),
Poker::Card.new('5', 'Spades'),
Poker::Card.new('6', 'Clubs'),
]
)
end
end

factory :straight_with_ace, class: Poker::Hand do
initialize_with do
new(
[
Poker::Card.new('A', 'Clubs'),
Poker::Card.new('2', 'Diamonds'),
Poker::Card.new('3', 'Diamonds'),
Poker::Card.new('4', 'Diamonds'),
Poker::Card.new('5', 'Diamonds'),
]
)
end
end

factory :three_of_a_kind, class: Poker::Hand do
transient do
match_rank nil
high_card nil
end

initialize_with do
new(
[
Poker::Card.new(match_rank || '4', 'Diamonds'),
Poker::Card.new(match_rank || '4', 'Spades'),
Poker::Card.new(match_rank || '4', 'Hearts'),
Poker::Card.new(high_card || '5', 'Clubs'),
Poker::Card.new('2', 'Clubs'),
]
)
end
end

factory :two_pair, class: Poker::Hand do
transient do
one_pair_rank nil
high_card nil
end

initialize_with do
new(
[
Poker::Card.new(one_pair_rank || '7', 'Diamonds'),
Poker::Card.new('J', 'Spades'),
Poker::Card.new('J', 'Hearts'),
Poker::Card.new(high_card || '5', 'Clubs'),
Poker::Card.new(one_pair_rank || '7', 'Clubs'),
]
)
end
end

factory :one_pair, class: Poker::Hand do
initialize_with do
new(
[
Poker::Card.new('K', 'Diamonds'),
Poker::Card.new('Q', 'Spades'),
Poker::Card.new('J', 'Hearts'),
Poker::Card.new('4', 'Clubs'),
Poker::Card.new('Q', 'Clubs'),
]
)
end
end
end
Loading