HSP3 ゲームのプログラミング | |
ポーカー・ゲーム制作 |
(5) ポーカーの役
処理の順序としては親カードの交換であるが、どのカードを交換するかを判定するにも現在の役を知る必要がある。乱数などで交換してしまうとせっかくできている役を崩すことにもなるからである。
このポーカー・ゲームの役は次の通りとする。強い順に並べてある。
◆ ジョーカーはオールマイティーで、どのカードの代用にもなる。
役名 カードの組合わせ ファイブカード 同じ数のカード4枚とジョーカー ロイヤルストレートフラッシュ 5枚とも同じ種類で、10, J, Q, K, Aの連番 ストレートフラッシュ 5枚とも同じ種類で、5枚連番 フォーカード 同じ数のカードが4枚、残りの1枚は何でも良い フルハウス 同じ数のカードが3枚と別のカードで同じ数のカード2枚 フラッシュ 5枚とも同じ種類 ストレート 種類はバラバラで、5枚連番 スリーカード 同じ数のカードが3枚、ほかの2枚は何でも良い ツーペア 同じ数が2枚の組が2組、残りの1枚は何でも良い ワンペア 同じ数が2枚の組が1組、残りの3枚は何でも良い ノーペア 役なし
◆ 連番とは例えば4, 5, 6, 7, 8のように5枚がつながったもののこと。ただしAと2はつながらないが、KとAはつながる。
◆ 役が同じ場合は、その役を構成するカードの数字が大きい方、数字も同じ場合は種類が強い方とする。種類の強さはスペード、ハート、ダイヤ、クローバーの順である。
フォーカードでは4枚のカード、フルハウスでは3枚のカードを比較の対象とする。
◆ 役なし同士の場合は、スペードのA, K, Q, J, 10, 9, 8, …, 3, 2, ハートのA, K, Q, J, 10, 9, 8, …, 3, 2, ダイヤのA, K, Q, J, 10, 9, 8, …, 3, 2, クローバーのA, K, Q, J, 10, 9, 8, …, 3, 2の順でもっとも強いカード同士を比較する。(実際には、スペードのカードの数が多い方、同じ数ならより大きいスペードを持っている方、どちらも持っていなければハートで比べ、ハートもなければダイヤで比べる。)
(6) カード(手札)の解析
役は、同じ数字のカードの枚数で構成される役、同じ種類のカードで構成される役、連番で構成される役、同じ種類で連番で構成される役がある。
○ カードの種類と数字
カードはスペード、ハート、ダイヤ、クローバーの順で、さらに数字順の通し番号で表し、配列crdに格納されている。まず、この通し番号をかーどの種類syuと数字suuに変換する。配列の添字cntはループのカウンタ(システム変数)である。
syu = crd(cnt) / 13 … 0=スペード、1=ハート、2=ダイヤ、3=クローバー、4=ジョーカー
suu = crd(cnt) \ 13 + 1 … 数字。ただし、1(A)は14に変換する。
○ 数字のカウント(配列hcnt)
数字suuは2〜14(14はAのこと)の範囲にある。配列hcntを用意して数字の個数をカウントする。カウントの方法は、数字suuを配列hcntの添字にして、1ずつ加算するだけである。
hcnt(suu)++
ジョーカーはsyu = 4、 suu = 1となる。Aは14に変換するので数字が競合することはない。
配列hcnt (0) (1) (2) (3) (4) (5) (6) (7) (8) (9) (10) (11) (12) (13) (14) カードの数字 2 3 4 5 6 7 8 9 10 J Q K A
例えば、hcnt(8)の値が3ならば、8のスリーカードと判定できる。
○ 数字の並び(配列hnum, hsn)
数字の並びを判定するために、2進数でそれぞれの数字を表すことにする。例えば数字が2, 3, 4, 5, 6であったとする。それぞれの数字を2の指数とすると2進数の各けたが数字と対応することになる。配列hnumをカードの種類分(4+1=5)用意して種類ごとに計算する。
26 + 25 + 24 + 23 + 22 = 1111100(2)
カードの
数字suu 2suu 2進数 S=スペード、H=ハート
D=ダイヤ、C=クローバー2 2 22 0000 0000 0000 0100 S2, S3, S4, S5, S6のとき
hnum(0) = 111 1100(2) = 124
hnum(1) = hnum(2) = hnum(3) =03 3 23 0000 0000 0000 1000 4 4 24 0000 0000 0001 0000 5 5 25 0000 0000 0010 0000 6 6 26 0000 0000 0100 0000 S2, H3, S4, H5, S6のとき
hnum(0) = 101 0100(2) = 84
hnum(1) = 010 1000(2) = 40
hnum(2) = hnum(3) =07 7 27 0000 0000 1000 0000 8 8 28 0000 0001 0000 0000 9 9 29 0000 0010 0000 0000 10 10 210 0000 0100 0000 0000 S2, H3, D4, C5, S6のとき
hnum(0) = 100 0100(2) = 68
hnum(1) = 000 1000(2) = 8
hnum(2) = 001 0000(2) = 16
hnum(3) = 010 0000(2) = 32J 11 211 0000 1000 0000 0000 Q 12 212 0001 0000 0000 0000 K 13 213 0010 0000 0000 0000 A 14 214 0100 0000 0000 0000
数字suuは2〜14の13種類であるから13けたの2進数ですべてを表すことができるが、計算しやすいように数字0と1の分も用意しておく。また、コンピュータは8の倍数が区切りがよいので、16けたの2進数として表すことにする。
配列hnumには111 1100のように2進数が格納されるのではなく、10進数で124と格納される。
次に、この10進数を2進数の文字列に変換するサブルーチンbin2strを作成して、配列hsnに格納する。
;10進数データを16桁の2進数文字列に変換及び1のビット数カウント -----
; bindata : 元データ(10進数)
; binstr : 変換データ(2進数)
; binnum : 1のビット数
*bin2str
binstr = ""
;2進数文字列に変換
repeat
br = bindata \ 2
bindata = bindata / 2
if br = 1 : binstr = "1" + binstr : else : binstr = "0" + binstr
if bindata = 0 : break
loop
;16けたの2進数に変換
binstr = "0000000000000000" + binstr
binstr = strmid(binstr, -1, 16)
;文字1の個数カウント
binnum = 0
repeat 16
if strmid(binstr, cnt, 1) = "1" : binnum++
loop
return
2進数の文字列に変換するとともに1の個数もカウントしている。カウントした数は配列hnnに格納することにする。hnn(0)=5ならばスペードが5枚あると判定できる。
配列hsn(0)〜(3)を一つにまとめ、種類に関係なく数字の並びを判定するためのデータを配列hsn(4)に格納する。
ここまでのカード解析は、役判定をする前の処理である。役判定はサブルーチンpoker_hanteiとして作成する予定であるので、カード解析の処理も役判定のサブルーチンの中に入れる。
次に、カード解析の処理をサンプルとして示す。サブルーチンpoker_hanteiとしては未完成であるので注意すること。
(poker12.hsp)
役判定のサブルーチンpoker_hanteiの前段階であるカードの解析処理を作成する。
サブルーチン以外に配列の宣言が必要である(灰色部分以外)。さらに、指数の計算が必要なので関数も追加しておく。
#module
#defcfunc pow int dd, int kk
;
;pow(整数値, 乗数)
; 返却値=int べき乗の値
;
ans = 1
repeat kk
ans = ans * dd
loop
return ans
#global
;初期設定 -----
;配列宣言
dim card, 53 ;カードの山用
dim ptx, 11 : dim pty, 11 ;カード置き場所座標
dim crd, 10 ;配布カードの通番格納用
dim chg, 10 ;交換用フラグ
dim hnum, 5 : dim hcnt, 15 ;役判定用(数字と種類)
sdim hsn, 5 : dim hnn, 5 ;役判定用(数字(2進数)と種類別枚数)
;役判定処理 -----
*poker_hantei
;役判定用配列初期化
repeat 5
hnum(cnt) = 0
hsn(cnt) = ""
hnn(cnt) = 0
loop
repeat 15
hcnt(cnt) = 0
loop
;カード解析、プレイヤーcrd(0)-(4)/親crd(5)-(9)
repeat 5, oya * 5 ;←←←←←※
syu = crd(cnt) / 13
suu = crd(cnt) \ 13 + 1
if syu = 4 { ;joker
hnum(4) = 1
} else {
if suu = 1 : suu = 14 ;10,J,Q,K,Aの並びのため
hcnt(suu)++ ;数字別カウント
hnum(syu) += pow(2, suu) ;種類別数字
}
loop
;カード解析2、数字2進数文字列変換、種類別枚数等
hnumw = 0
repeat 4
hnumw |= hnum(cnt) ;種類別数字のまとめ
bindata = hnum(cnt)
gosub *bin2str ;2進数文字列変換
hsn(cnt) = binstr ;種類別数字→"0101010101010" 2進数文字列
hnn(cnt) = binnum ;種類別枚数
loop
bindata = hnumw
gosub *bin2str ;2進数文字列変換
hsn(4) = binstr ;種類別数字まとめ→"0101010101010" 2進数文字列
※ プレイヤーの役を判定するときは変数oya=0とし、親の役を判定するときは変数oya=1としてサブルーチンを呼び出す。
ここまでのカード解析処理で、解析結果が次の通り配列に格納される。この後続く役判定の処理ではこれらの配列を調べることになる。
配 列 内 容 hcnt(0)〜(14) 数字ごとの枚数 hnum(0)〜(4) 種類ごとの数字の並び(10進数) hsn(0)〜(3) 種類ごとの数字の並び(2進数) hnn(0)〜(3) 種類ごとの枚数 hsn(4) 数字の並び(2進数)
ポーカー・ゲーム制作 | |
2007 © Hiroshi Masuda |