ポーカーの役判定
お題にしようと思っていたのに間違えてしまいました。今から変更可能でしょうか?
(説明) 当初間違ってトピックに投稿していたので、このようなコメントを付けていたのですが、 このコメントに気づいた管理人さんにお題に移していただきました。 (最初の2つだけ投稿日時が早いのはそのためです)
Posted feedbacks - Ruby
rankとsuitを分離して扱いました.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 | def poker(hand)
def one_pair(rank, count = 0)
rank.values.map{|x| count += 1 if x.size == 2}
count == 1
end
def two_pair(rank, count = 0)
rank.values.each{|x| count += 1 if x.size == 2}
count == 2
end
def three_cards(rank)
rank.values.map{|x| x.size == 3 ? true : nil}.compact.shift
end
def straight(rank)
rank.size == 5 ? rank.keys.sort.first + 4 == rank.keys.sort.last : false
end
def flush(suit); suit.size == 1 ;end
def fourcards(rank)
rank.values.map{|x| x.size == 4 ? true : nil}.compact.shift
end
def convert(char)
case char
when 'T': 10
when 'J': 11
when 'Q': 12
when 'K': 13
when 'A': 14
else
char.to_i
end
end
def div_suit_and_rank(hand)
suit_hash, rank_hash = Hash.new, Hash.new
cards = hand.split('')
Array.new(hand.size.div(2)){|i| 2*i}.each{|i|
suit = cards[i]
rank = convert(cards[i+1])
eval("suit_hash[suit] #{(suit_hash[suit] ? '<< rank' : '= [rank]')}")
eval("rank_hash[rank] #{(rank_hash[rank] ? '<< suit' : '= [suit]')}")
}
[suit_hash, rank_hash]
end
suit, rank = *div_suit_and_rank(hand)
if straight(rank)
"#{rank.keys.sort.first == 10 ? 'Loyal ' : ''}Straight #{(flush(suit) ? 'Flush' : '')}"
elsif fourcards(rank)
"Four of a Kind"
elsif three_cards(rank) and one_pair(rank)
"Full House"
elsif flush(suit)
"Flush"
elsif three_cards(rank)
"Three of a Kind"
elsif two_pair(rank)
"Two Pair"
elsif one_pair(rank)
"One Pair"
else
"No Pair"
end
end
hands = ['SQSJSASKST', 'D9D7D6D5D8', 'C2D2S2H3H2', 'C2D3S2H3H2', 'S9S4S8STSJ', 'C4H7D5S6H3', 'S6H6C5DQC6', 'S6HQC5DQC6', 'S6H4C5DQC6', 'SJSQSKSAC2']
hands.each{|x| puts poker(x)}
|
確かに, Aを14としたのが敗因でした. straightメソッドに場合分けを追加する必要がありますね.
短さ優先。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | ranks = []
1.step(10, 2) do |i| ranks << ARGV[0][i, 1] end
rank_hash = Hash.new(0)
ranks.each do |rank| rank_hash[rank] += 1 end
flush = ARGV[0].count(ARGV[0][0,1].to_s) == 5
straight = ("23456789AJKQT".include? ranks.sort!.to_s or "2345A".include? ranks.to_s)
case
when (ranks.to_s == "AJKQT" and flush) then puts "Royal Flush"
when (straight and flush) then puts "Straight Flush"
when rank_hash.values.max == 4 then puts "Four of a Kind"
when (rank_hash.values.max == 3 and rank_hash.values.include? 2) then puts "Full House"
when flush then puts "Flush"
when straight then puts "Straight"
when rank_hash.values.max == 3 then puts "Three of a Kind"
when rank_hash.values.to_s.count("2") == 2 then puts "Two Pair"
when rank_hash.values.max == 2 then puts "One Pair"
else puts "No Pair"
end
|
素直に書いてみた。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 | class Poker
def initialize str
suits=[]
nums=[]
str.scan(/[SDHCTJQKA0-9]{2}/).each{|card|
tmp=card.scan(/./)
num=case tmp[1]
when "T": 10
when "J": 11
when "Q": 12
when "K": 13
when "A": 1
else tmp[1].to_i
end
suits << tmp[0]
nums << num
}
@cards = {
:suit=>suits,
:num=>nums,
:layer => nums.inject({}){|result,n| # [1,2,2,2,3,3,4] => [1,3,2,1]
result[n]=0 if !result[n]
result[n]+=1
result
}.values
}
end
def one_pair
@cards[:layer].max == 2 && @cards[:layer].length == 4
end
def two_pair
@cards[:layer].max == 2 && @cards[:layer].length == 3
end
def three_card
@cards[:layer].max == 3 && @cards[:layer].length == 3 # not full house
end
def four_card
@cards[:layer].max == 4 && @cards[:layer].length == 2
end
def full_house
@cards[:layer].max == 3 && @cards[:layer].length == 2
end
def five_card
@cards[:layer].max == 5 && @cards[:layer].length == 1
end
def straight
((1..13).to_a.join(" ")).include?(@cards[:num].sort.join(" "))
end
def flush
@cards[:suit].uniq.length == 1
end
def royal_straight_flush
flush() && @cards[:num].sort == [1,10,11,12,13]
end
def cards_rank
# p @cards
case
when (royal_straight_flush()) : "Royal Straight Flush"
when (straight() && flush()): "Straight Flush"
when (four_card()): "Four of a kind"
when (full_house()): "Full house"
when (flush()) : "Flush"
when (straight()) : "Straight"
when (three_card()): "Three of a kind"
when (two_pair()) : "Two pair"
when (one_pair()) : "One pair"
else "No pair"
end
end
end
arr="SQSJSASKST D9D7D6D5D8 C2D2S2H3H2 C2D3S2H3H2 S9S4S8STSJ C4H7D5S6H3 S6H6C5DQC6 S6HQC5DQC6 S6H4C5DQC6 SJSQSKSAC2".split(/\s/)
arr.each{|cards|
puts Poker.new(cards).cards_rank
}
# str=ARGV.shift
# puts poker(str)
|
合っているかいるかどうかわからないので全組合せを喰わせてみました。
かなり汚いできではありますが、うまくいっているようです。
皆様のコードを参考にさせていただきました。
結果は
Royal flush 4 1/649740
Straight flush 36 1/72193.33
Four of a kind 624 1/4165
Full house 3744 1/694.17
Flush 5108 1/508.8
Straight 10200 1/254.8
Three of a kind 54912 1/47.33
Two pair 123552 1/21.04
One pair 1098240 1/2.37
No pair 1302540 1/2
total 2598960
でした。
全組合せは以下で作りました。
suits = ["S","D","H","C"]
rank = (["A"] + ("2".."9").to_a + ["T","J","Q","K"])
card = []
for i in suits.product(rank)
card << i.join
end
for i in card.combination(5).to_a
puts i.shuffle.join #一応、シャッフル。
end
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 | def porker(hand)
narabi =(["0","A"] + ("2".."9").to_a + ["T","J","Q","K"])
def num(a)
(["0","A"] + ("2".."9").to_a + ["T","J","Q","K"]).index(a)
end
tmp = hand.scan(/[SDHCTJQKA2-9]{2}/).map(&:chars).map(&:to_a)
card = Hash.new{|h,k|h[k]=[]}
for i in tmp
i[0]
card[i[0]] << i[1]
end
suuji = Hash.new(0)
for i in card.values.flatten
suuji[i] += 1
end
case
when card.keys.size == 1 && card.values.flatten.sort_by{|a|num(a)}.join(" ") == "A T J Q K"
"Royal flush"
when card.keys.size == 1 && %r(#{suuji.keys.sort_by{|a|num(a)}.join(" ")}) =~ narabi.join(" ")
"Straight flush"
when suuji.select{|k,v|v == 4}.size == 1
"Four of a kind"
when suuji.keys.size == 2
"Full house"
when card.keys.size == 1
"Flush"
when suuji.keys.size == 5 && (%r(#{suuji.keys.sort_by{|a|num(a)}.join(" ")}) =~ narabi.join(" ") ||
suuji.keys.sort_by{|a|num(a)}.join(" ") == "A T J Q K")
"Straight"
when suuji.select{|k,v|v == 3}.size == 1
"Three of a kind"
when suuji.select{|k,v|v == 2}.size == 2
"Two pair"
when suuji.select{|k,v|v == 2}.size == 1
"One pair"
else
"No pair"
end
end
#ruby porker.rb file|SQSJSASKST|なしの場合は__END__以下
if ARGV.size == 1
if File.exist?(ARGV[0])
f = open(ARGV[0])
while f.gets
hand = $_.chomp
puts [hand,porker(hand)].join(" ")
end
else
puts [ARGV[0],porker(ARGV[0])].join(" ")
end
else
while DATA.gets
hand = $_.chomp
puts [hand,porker(hand)].join(" ")
end
end
__END__
SQSJSASKST
D9D7D6D5D8
C2D2S2H3H2
C2D3S2H3H2
S9S4S8STSJ
C4H7D5S6H3
S6H6C5DQC6
S6HQC5DQC6
S6H4C5DQC6
SJSQSKSAC2
|





xsd
#4978()
Rating6/10=0.60
引数に手札を与えると、ポーカーの役を表示するプログラムを作ってください。
条件:
実行例:
see: ポーカー - Wikipedia
1 reply [ reply ]