前回記事は、こちらです。↓
和了判定プログラムを完成させる。
こちらが、完成したプログラムになります。
def agari_check(t)
tehai=t
tehai_check = Array.new(46,0)
tehai.map {|v|tehai_check[v]+=1}
#雀頭候補抜き取り
jt=[] #雀頭候補格納配列
tehai_check.each_with_index do |v,i|
if v>=2 then
jt << i
end
end
agari_mentsu=[]
#七対子Check
if jt.size==7 then
c=[]
jt.each do |v|
c << [v,v]
end
agari_mentsu << c
end
#国士無双Check
if jt.size==1 then
kokushi_check_bit = [
0,1,0,0,0,0,0,0,0,1,
0,1,0,0,0,0,0,0,0,1,
0,1,0,0,0,0,0,0,0,1,
0,1,0,1,0,1,0,1,0,0,
0,1,0,1,0,1
]
tmp_kokushi=tehai_check.dup
amtmp_kokushi=[]
#雀頭を抜く
amtmp_kokushi << [jt[0],jt[0]]
tmp_kokushi[jt[0]]-=2
kokushi_check_bit[jt[0]]-=1
kokushi_check=true
kokushi_check_bit.each_with_index do |kv,ki|
kokushi_check = false if kv!=tmp_kokushi[ki]
end
if kokushi_check == true then
k_tmp=[]
tmp_kokushi.each_with_index{|kv,ki| k_tmp << ki if kv==1}
amtmp_kokushi << k_tmp
agari_mentsu << amtmp_kokushi
end
end
#面子手Check
#雀頭候補毎にcheck
jt.each_with_index do |v,i|
tmp=tehai_check.dup
amtmp=[]
#雀頭を抜く
amtmp << [v,v]
tmp[v]-=2
kohtsu_list = []
#刻子をチェック
tmp.each_with_index do |vv,ii|
kohtsu_list << ii if vv>=3
end
kohtsu_ptn = []
num = 2**kohtsu_list.size
bit = kohtsu_list.size
if kohtsu_list.size != 0 then
kohtsu_ptn_bit=Array.new(num)
(num-1).downto(0) do |i|
kpb_tmp=Array.new(bit - 1)
(bit-1).downto(0) do |ii|
kpb_tmp[ii]= i[ii]!=0 ? kohtsu_list[ii] : 0
end
kpb_tmp.delete(0)
kohtsu_ptn << kpb_tmp
end
end
#刻子パターンごとに刻子を抜く
kohtsu_ptn.each_with_index do |vv,ii|
tmp2=tmp.dup
amtmp2=amtmp.dup
vv.each do |vvv|
amtmp2 << [vvv,vvv,vvv]
tmp2[vvv]-=3
end
agari_mentsu << amtmp2 if tmp2.count{|x|x>0}==0
#順子を抜く
(1..27).each do |iii|
tmp2[iii].times do
if tmp2[iii]>0&&tmp2[iii+1]>0&&tmp2[iii+2]>0 then
amtmp2 << [iii,iii+1,iii+2]
tmp2[iii ]-=1
tmp2[iii+1]-=1
tmp2[iii+2]-=1
end
end
end
agari_mentsu << amtmp2 if tmp2.count{|x|x>0}==0
end
#順子を抜く(刻子なし)
(1..27).each do |iii|
tmp[iii].times do
if tmp[iii]>0&&tmp[iii+1]>0&&tmp[iii+2]>0 then
amtmp << [iii,iii+1,iii+2]
tmp[iii ]-=1
tmp[iii+1]-=1
tmp[iii+2]-=1
end
end
end
agari_mentsu << amtmp if tmp.count{|x|x>0}==0
end
if agari_mentsu.count==0 then
return false
else
result=agari_mentsu.uniq
return result
end
end
それでは、要点を解説します。
和了り形を格納する。
和了りが確定する可能性がある以下の個所で、和了り形を格納する変数配列”agari_mentsu”に和了り形を格納します。
- 七対子判定(22行目)
- 国士無双判定(49行目)
- 刻子判定(93行目)
- 順子判定(106行目、119行目)
メソッド化させる。
以上のプログラムを、agari_checkと言う名前のメソッドにしました。
メソッドの引数は手牌を表す配列で、返り値が和了り形です(125行目)。
和了り形ができていなかったら”false”を返すようにしました。
124行目に使用しているメソッド”uniq”は、重複している値(和了り形)を削除するメソッドです。
このプログラムを”agari_check.rb”と言うファイル名で保存したら、完成です。
使用例
それでは、使用例を紹介します。
require_relative './agari_check.rb'
tehai=[1,1,2,2,3,3,3,4,5,11,12,13,19,19]
t = agari_check(tehai)
p t
# => [[[19, 19], [1, 2, 3], [1, 2, 3], [3, 4, 5], [11, 12, 13]]]
3枚ある(3)を、刻子と判定せずに、和了りであることを判定してくれています。
次に、二盃口形を見てみます。
require_relative './agari_check.rb'
tehai=[1,1,2,2,3,3,11,11,12,12,13,13,19,19]
t = agari_check(tehai)
p t
# => [[[1, 1], [2, 2], [3, 3], [11, 11], [12, 12], [13, 13], [19, 19]],
# [[19, 19], [1, 2, 3], [1, 2, 3], [11, 12, 13], [11, 12, 13]]]
二盃口だけでなく、七対子形も判定しています。点数計算する際はすべての和了り形を考慮して、一番高い点数を申告するため、このような戻り値になる必要があります。
完成!!
これで、完成しました。
麻雀ゲームを作成している方の参考になれば幸いです。
私は、作成している入れ替えパズルに組み込みたいと思います。
コメント