Let's make draw poker with ruby-Preparation- ↓ Let's make draw poker with ruby-test-unit preparation- ↓ Let's make draw poker with ruby-Implementation 1 (card)-
Followed by.
Source: https://github.com/rytkmt/ruby_poker
This time we will implement the role.
Let's reorganize the requirements.
--The role is judged based on 5 cards
--Players compare wins and losses based on their roles
--If you create a "role" class to compare roles and use Comparable
, you can compare them.
――Among the roles, hold the cards to be compared for the same role (1 card)
――The role is "** hand **" in English. This is important.
So it's time to implement.
First of all, create a file normally
ruby_poker/hand.rb
module RubyPoker
class Hand
def intialize(cards:)
end
end
end
ruby_poker.rb
require "ruby_poker/hand"
If you are generating a "role" class, you should make a judgment at that timing. ..
Therefore, use the judgment method at the time of generation and set the comparison card for the type and the same role.
ruby_poker/hand.rb
attr_reader :hand_type, :comparison_card
def intialize(cards:)
raise(ArgumentError) if cards.size != 5
@hand_type, @comparison_card = judge(cards: cards)
end
private
def judge(cards:)
end
Don't make it an instance variable because you don't need to keep it just by using cards to judge the role.
How to implement role judgment ...
Since there are many roles, I feel that I haven't been able to separate them by preparing methods one by one. .. So, let's cut it out as a judgment module.
Then, the judgment should be made in order of strength, and the one that matches at the beginning should be set. First, define it as you did for the card.
Refer to here for the English name ... lol https://en.wikipedia.org/wiki/List_of_poker_hands
ruby_poker.rb
HAND_TYPES = %i[
royal_straight_flush
straight_flush
four_of_a_kind
full_house
flush
straight
three_of_a_kind
two_pair
one_pair
high_card
].reverse.freeze
Since I want to get the module class dynamically, I want to convert from snake case to camel case and get it with const_get
. ..
So let's use the ʻactive_support` gem for word conversion there
(When I usually touch rails, it's convenient to reach the itchy area around here and I want to use it.)
Gemfile
gem "activesupport"
$ bundle install
This completes the installation
ruby_poker.rb
require "active_support/all"
Don't forget to read
ruby_poker/hand.rb
Dir[__dir__ + "/hand/hand_type_judgers/*.rb"].each { |p| require p }
module RubyPoker
class Hand
ruby_poker/hand.rb
private
def judge(cards:)
matched_cards = nil
matched_type = RubyPoker::HAND_TYPES.find do |type|
judger = RubyPoker::Hand::HandTypeJudgers.const_get(type.to_s.classify) # <=Active for here_support
matched_cards = judger.judge(cards: cards)
end
[matched_type, matched_cards.max]
end
I thought that it was within the responsibility of hand in the form of separating the internal processing of hand, so I will implement it as an inner module of hand.
Judger's .judge
always returns the card that is the target of the same role judgment if it matches, and returns nil if it does not match
ruby_poker/lib/ruby_poker/hand/hand_type_judgers/royal_straight_flush.rb
module RubyPoker
class Hand
module HandTypeJudgers
module RoyalStraightFlush
def self.judge(cards:)
return nil unless cards.map(&:suit).uniq.size == 1
return nil unless cards.sort.map(&:number) == [10, 11, 12, 13, 1]
cards
end
end
end
end
end
ruby_poker/lib/ruby_poker/hand/hand_type_judgers/straight_flush.rb
module RubyPoker
class Hand
module HandTypeJudgers
module StraightFlush
def self.judge(cards:)
return nil unless cards.map(&:suit).uniq.size == 1
min_number_level = cards.min.number_level
expected = [*min_number_level..min_number_level + 4]
return nil unless cards.sort.map(&:number_level) == expected
cards
end
end
end
end
end
ruby_poker/lib/ruby_poker/hand/hand_type_judgers/four_of_a_kind.rb
module RubyPoker
class Hand
module HandTypeJudgers
module FourOfAKind
def self.judge(cards:)
cards.group_by(&:number).detect { |k, v| v.size == 4 }&.second
end
end
end
end
end
ruby_poker/lib/ruby_poker/hand/hand_type_judgers/full_house.rb
module RubyPoker
class Hand
module HandTypeJudgers
module FullHouse
def self.judge(cards:)
grouped_number_cards = cards.group_by(&:number)
three_card_number, three_cards = grouped_number_cards.detect { |k, v| v.size == 3 }
return nil unless three_card_number
grouped_number_cards.delete(three_card_number)
return nil unless grouped_number_cards.detect { |k, v| v.size == 2 }
three_cards
end
end
end
end
end
ruby_poker/lib/ruby_poker/hand/hand_type_judgers/flush.rb
module RubyPoker
class Hand
module HandTypeJudgers
module Flush
def self.judge(cards:)
return nil unless cards.map(&:suit).uniq.size == 1
cards
end
end
end
end
end
ruby_poker/lib/ruby_poker/hand/hand_type_judgers/straight.rb
module RubyPoker
class Hand
module HandTypeJudgers
module Straight
def self.judge(cards:)
min_number_level = cards.min.number_level
expected = [*min_number_level..min_number_level + 4]
return nil unless cards.sort.map(&:number_level) == expected
cards
end
end
end
end
end
ruby_poker/lib/ruby_poker/hand/hand_type_judgers/three_of_a_kind.rb
module RubyPoker
class Hand
module HandTypeJudgers
module ThreeOfAKind
def self.judge(cards:)
cards.group_by(&:number).detect { |k, v| v.size == 3 }&.second
end
end
end
end
end
ruby_poker/lib/ruby_poker/hand/hand_type_judgers/two_pair.rb
module RubyPoker
class Hand
module HandTypeJudgers
module TwoPair
def self.judge(cards:)
pairs = cards.group_by(&:number_level).select { |k, v| v.size == 2 }
return nil unless pairs.size == 2
pairs.max.second
end
end
end
end
end
ruby_poker/lib/ruby_poker/hand/hand_type_judgers/one_pair.rb
module RubyPoker
class Hand
module HandTypeJudgers
module OnePair
def self.judge(cards:)
cards.group_by(&:number_level).detect { |k, v| v.size == 2 }&.second
end
end
end
end
end
ruby_poker/lib/ruby_poker/hand/hand_type_judgers/high_card.rb
module RubyPoker
class Hand
module HandTypeJudgers
module HighCard
def self.judge(cards:)
[cards.max]
end
end
end
end
end
It was a little difficult including the implementation of the test, but the implementation was completed. Now you can perform the role judgment and return the judgment card at the same time.
ruby_poker/hand.rb
+ include Comparable
ruby_poker/hand.rb
def hand_level
RubyPoker::HAND_TYPES.reverse.index(@hand_type)
end
def <=>(other)
hand_comparison = hand_level <=> other.hand_level
hand_comparison.zero? ? @comparison_card <=> other.comparison_card : hand_comparison
end
Now you can compare the wins and losses of roles by >
etc.
With this content, I think that all the important processing for the game, such as cards and roles, has been completed. Next time, I would like to create players who use these and the game progress.
↓ Try to make draw poker with ruby-Implementation 3 (player)-
Recommended Posts