文字列内の文字や単語の数をカウントする処理を使ってポーカーの役判定ができるかも?と思ったことから、Rubyでポーカーの役判定プログラムを書いてみました。
#ポーカーの役判定
#カードをスートと数字に分けて配列に入れる
str = "S1 H8 D7 S11 C8" #5枚のカードの内容を、スートと数字をつけて文字列として入力。
suit = str.delete("^A-Z| ").split(' ')
snum = str.delete("^0-9| ").split(' ')
num = []
flush = 0
straight = 0
for i in 0..4
num[i] = snum[i].to_i
end
#手札のスートが全て一致しているか判定
if suit.count(suit[0]) == suit.length
flush = 1
end
#手札が全て続き番号(もしくは、[1,10,11,12,13])になっているか判定
if num.sort[1] == num.sort[0] +1 && num.sort[2] == num.sort[0] + 2 && num.sort[3] == num.sort[0] +3 && num.sort[4] == num.sort[0] + 4 || num.sort == [1,10,11,12,13]
straight = 1
end
#カードの数を数えてから役を判定
count_box = []
for i in 0..num.uniq.length-1
count_box[i] = num.count(num.uniq[i])
end
if count_box.sort.reverse == [4,1]
puts "4カード"
elsif count_box.sort.reverse == [3,2]
puts "フルハウス"
elsif count_box.sort.reverse == [3,1,1]
puts "3カード"
elsif count_box.sort.reverse == [2,2,1]
puts "2ペア"
elsif count_box.sort.reverse == [2,1,1,1]
puts "1ペア"
elsif count_box.sort.reverse == [1,1,1,1,1]
if num.sort == [1,10,11,12,13] && flush == 1
puts "ロイヤルストレートフラッシュ"
elsif straight == 1 && flush == 1 && num.sort != [1,10,11,12,13]
puts "ストレートフラッシュ"
elsif flush == 1
puts "フラッシュ"
elsif straight == 1
puts "ストレート"
else
puts "ノーペア"
end
end
今回のRubyで書いたプログラムは、与えられた手札5枚についての文字列からポーカーの役を判定するものになってます。さすがに今の段階(PaizaランクDが終わった)では、ポーカーゲームができるようなプログラムは手に負えないです。
手札の情報をそれぞれの配列に格納する
5枚の手札は、「S1 H8 D7 S11 C8」の形の文字列で表記されます。数字の前の半角アルファベットはスートを表しており、Sがスペード、Hがハート、Dがダイヤ、Cがクラブになってます。なお、ジョーカーは使用しません。
まずは、手札の文字列について、スートと数字に分けて、それぞれの配列(suit[]、snum[])に入れます。
スートについては、.delete(“^A-Z| “)メソッドで文字列から数字を消してから、.split(‘ ‘)メソッドによって空白で区切ったものをスート用配列(suit[])に入れます。一方の数字については、.delete(“^0-9| “)メソッドで文字列からアルファベットを消してから、 .split(‘ ‘)メソッドによって空白で区切ったものを数字用配列(snum[])に入れ、さらにデータ型を整数型に変換してから、新しく用意した配列(num[])に入れます。
手札5枚のスートが全て同じかどうかどうかの判定。
スートが入った配列の最初の要素(suit[0])について配列内の個数をカウントし、配列の要素数(suit.length)と一致していれば、手札のスートが全て一致していることになります。スートが一致した場合は、Flush変数を1にします。
手札5枚が続き番号もしくは、[1,10,11,12,13]になっているかどうかの判定。
手札5枚の数字が入っている配列num[]の要素が、続き番号もしくは、[1,10,11,12,13]になっているかどうかを判定します。
num[]の要素は、.sortメソッドで昇順に並べ替えてから、num[1]、num[2]、num[3]、num[4]の要素について、それぞれnum[0]+1、num[0]+2、num[0]+3、num[0]+4と等しいか判定。全て満たしていれば、手札5枚が続き番号になってます。
ここで手札5枚が続き番号もしくは、[1,10,11,12,13]になっていた場合は、straight変数を1にします。
数字用配列内の要素の個数から役を判定
手札の数字が入っている配列num[]の中に、同じ数字がいくつあるかカウントします。
重複を除いた配列(num[].uniq)の各要素について、元の配列num[]に含まれる個数をカウントし、カウント結果格納用の配列(count_box[])に格納します。
配列count_box[]に同じ数字の個数を格納したら、.sort.reverseメソッドを使用して要素を降順に並べ替てから、その内容によって役を判定していきます。
[4,1]の場合、「4カード」を表示。
[3,2]の場合、「フルハウス」を表示。
[3,1,1]の場合、「3カード」を表示。
[2,2,1]の場合、「2ペア」を表示。
[2,1,1,1]の場合、「1ペア」を表示。
ここで5枚の手札内に同じ数字がなかった(num[]の内容が[1,1,1,1,1])場合は、次の処理に進みます。
同じ数字のカードがなかった場合の役判定
Flush変数が1で、num[]の内容が[1,10,11,12,13]であれば、「ロイヤルストレートフラッシュ」を表示。
Flush 変数、straight 変数がともに1になっていて、かつ、num[]の内容が[1,10,11,12,13]でない場合は、「ストレートフラッシュ」を表示。
Flush 変数が1で、straight 変数が0の場合は、「フラッシュ」を表示。
Flush 変数が0で、straight 変数が1の場合は、「ストレート」を表示。
Flush 変数、straight 変数が両者とも0の場合は、「ノーペア」(いわゆる役無し)を表示。
以上がRubyで書いたポーカーの役判定プログラムになります。何しろプログラミング初心者なので、気の利いた書き方になっていない。
プログラムが書き終わったので、オンラインの開発環境サイトpaiza.ioを使って、実際にプログラムを動かしてみます。いくつかのテストデータを入れて試したところ、何とか上手く動いてくれました。
いずれはポーカーゲームができるプログラムも書けるようになりたいですが、かなり先になりそうです。