日本だんでぃ協会
Japan Dandy Association

中の人プロフィール
だんでぃ
web拍手作った人
プログラマーでミュージシャンだと言い張って聞かない37才

おこんてんつ
  トップ
プログラミング (12)
デカ文字ジェネレータ
  音楽 (7)
  ポーカー (1)
  雑記 (1)

リンク
ろじっくぱらだいす
老舗のプログラム系テキストサイト。web拍手を思い付くきっかけをいただいたサイトです。ワタナベさんラヴ!

■ポーカーの役判定 ツーペア、フルハウス編

2017/04/23 00:33 作成
前回、フォーカード、スリーカード、ワンペアの解説をしましたので、
同様の「同じ数字が複数枚あることで成立する役」の残りのツーペアとフルハウスを解説します。

んでは、何となく簡単そうなツーペアからいってみましょう。

判定の考え方としては、
「数字の組み合わせを数えていって、『同じ数字が2枚』が2つあったらツーペア」
になるわけですが、なんかこの文章だと分かりづらいですね。

実際にトランプで見てみると、

とか

みたいなのがツーペアになるわけですね。

では、実際のコードはこんな感じになります。
function IsTwoPairs( targetCards ){

	//数字を数える入れ物を用意
	var numbers = { 1:0, 2:0, 3:0, 4:0, 5:0, 6:0, 7:0, 8:0, 9:0, 10:0, 11:0, 12:0, 13:0 };

	//引数として渡されたカードの数字をカウントしていく
	for( var i=0; i<targetCards.length; i++ ){
		numbers[targetCards[i]["Number"]]++;
	}

	//「同じ数字が○枚」がいくつあったのかを数える入れ物を用意
	var sameCount = { 0:0, 1:0, 2:0, 3:0, 4:0 };

	//カウントした数字を集計
	for( var i=1; i<=13; i++ ){
		sameCount[numbers[i]]++;
	}

	//「同じ数字が2枚」が2つあったらツーペア判定
	if( sameCount[2]==2 ){
		return true;
	}

	//ここまで到達でツーペアは成立していない
	return false;
}
早めに言っておきますと、このプログラムはバグっています。

この関数は「同じ数字が2枚あるのが2組あったらツーペア判定」としているため、
上で実際にトランプの画像でお見せしたカードのデータをこの関数に渡してもちゃんとツーペア判定をしてくれますが、
テキサスホールデムでは7枚のカードから最も強い役ができる5枚を使うというルールなため、

こんなカードのデータが渡される可能性があるわけです。

ちなみに、この7枚のカードから最も強い役ができる5枚を抜き出すと、

こうなるため、この7枚のカードは同じ数字が2枚あるのが3組存在していますが、
成立している役としてはツーペアになるわけです。

なので、判定としては
「同じ数字が2枚あるのが2組あったらツーペア判定」
ではなく、
「同じ数字が2枚あるのが2組以上あったらツーペア判定」
にしなくてはいけないわけですね。

これを見落としてしまうと、上記の7枚のカードが渡されたときにツーペア判定できず、
本来はツーペアのハンドをワンペアと誤って判定してしまうという
恐ろしいバグを含んでいるプログラムを納品してしまいかねません。

こういう見落としに如何に気付けるかもプログラマの重要なスキルですね。

んでは、正しいツーペア判定のプログラムはこうです
function IsTwoPairs( targetCards ){

	//数字を数える入れ物を用意
	var numbers = { 1:0, 2:0, 3:0, 4:0, 5:0, 6:0, 7:0, 8:0, 9:0, 10:0, 11:0, 12:0, 13:0 };

	//引数として渡されたカードの数字をカウントしていく
	for( var i=0; i<targetCards.length; i++ ){
		numbers[targetCards[i]["Number"]]++;
	}

	//「同じ数字が○枚」がいくつあったのかを数える入れ物を用意
	var sameCount = { 0:0, 1:0, 2:0, 3:0, 4:0 };

	//カウントした数字を集計
	for( var i=1; i<=13; i++ ){
		sameCount[numbers[i]]++;
	}

	//「同じ数字が2枚」が2つ以上あったらツーペア判定
	if( sameCount[2]>=2 ){
		return true;
	}

	//ここまで到達でツーペアは成立していない
	return false;
}

	if( sameCount[2]==2 ){
		return true;
	}
こうだった箇所が

	if( sameCount[2]>=2 ){
		return true;
	}
こう修正されていますね。

たった一文字「=」を「>」に書き換えただけですが、
これでバグ無く理想的にツーペア判定ができるようになりました。


それでは、フルハウスの判定プログラムを書いてみましょう。

フルハウスという役は

こんな感じで、
「同じ数字が3枚が1組と、同じ数字が2枚が1組」の状態で成立します。

コード的にはこんな感じです。
function IsFullHouse( targetCards ){

	//数字を数える入れ物を用意
	var numbers = { 1:0, 2:0, 3:0, 4:0, 5:0, 6:0, 7:0, 8:0, 9:0, 10:0, 11:0, 12:0, 13:0 };

	//引数として渡されたカードの数字をカウントしていく
	for( var i=0; i<targetCards.length; i++ ){
		numbers[targetCards[i]["Number"]]++;
	}

	//「同じ数字が○枚」がいくつあったのかを数える入れ物を用意
	var sameCount = { 0:0, 1:0, 2:0, 3:0, 4:0 };

	//カウントした数字を集計
	for( var i=1; i<=13; i++ ){
		sameCount[numbers[i]]++;
	}

	//同じ数字が3枚が1組と、同じ数字が2枚が1組あったらフルハウス成立
	if( sameCount[3]==1 && sameCount[2]==1 ){
		return true;
	}

	//ここまで到達でフルハウスは成立していない
	return false;
}
なんとなくツーペアの判定と似たコードになりましたね。
そして、お察しの通りこのコードはバグってます。

ツーペアの時と同様に、以下のような7枚のカードの時がフォローされていません。


同じ数字が3枚が1組と、同じ数字が2枚が2組


同じ数字が3枚が2組

このようなカードの組み合わせが渡された時にも正しく判定できるようにしなければいけません。

ということで、コードを直すとこんな感じになります。
function IsFullHouse( targetCards ){

	//数字を数える入れ物を用意
	var numbers = { 1:0, 2:0, 3:0, 4:0, 5:0, 6:0, 7:0, 8:0, 9:0, 10:0, 11:0, 12:0, 13:0 };

	//引数として渡されたカードの数字をカウントしていく
	for( var i=0; i<targetCards.length; i++ ){
		numbers[targetCards[i]["Number"]]++;
	}

	//「同じ数字が○枚」がいくつあったのかを数える入れ物を用意
	var sameCount = { 0:0, 1:0, 2:0, 3:0, 4:0 };

	//カウントした数字を集計
	for( var i=1; i<=13; i++ ){
		sameCount[numbers[i]]++;
	}

	//同じ数字が3枚が1組以上と、同じ数字が2枚が1組以上あったらフルハウス成立
	if( sameCount[3]>=1 && sameCount[2]>=1 ){
		return true;
	}

	//同じ数字が3枚が2組以上あったらフルハウス成立
	if( sameCount[3]>=2 ){
		return true;
	}

	//ここまで到達でフルハウスは成立していない
	return false;
}
これで正しくフルハウスの判定ができるようになりました。

一見すると、
	if( sameCount[3]>=1 && sameCount[2]>=1 ){
		return true;
	}
この判定だけで全てのパターンをカバーできそうに見えますが、
上記の例で言うと

この時に「同じ数字が2枚」は存在しないのでチェック漏れが起きてしまいます。
なので、
	if( sameCount[3]>=2 ){
		return true;
	}
これも必要ということになります。

それと、
	//同じ数字が3枚が1組と、同じ数字が2枚が1組以上あったらフルハウス成立
	if( sameCount[3]==1 && sameCount[2]>=1 ){
		return true;
	}
こうじゃなくて
	//同じ数字が3枚が1組以上と、同じ数字が2枚が1組以上あったらフルハウス成立
	if( sameCount[3]>=1 && sameCount[2]>=1 ){
		return true;
	}
こうなっている理由ですが、
テキサスホールデムの場合最大で7枚のカードなので「同じ数字が3枚が1組」でかまわないのですが、
今後何かしらの理由で8枚以上のカードを判定しなければいけない場面があった時でも
コードの改造を全くしなくても大丈夫なようにしておくためです。

こうしておくと、「カードが何枚渡されても正しく役判定ができる」という状態にできるため、
今回の「テキサスホールデムの役判定ができる」という要件を満たしつつ、
さらに汎用性の高いプログラムになるわけです。

こういう、一見すると蛇足とも言える汎用性を持たせておくというのは
プログラマによって好みが分かれるところだと思うのですが、
たった1文字や2文字変えるだけで汎用性を上げられて、
かつバグの心配もなさそうなら、僕はやっておく派です。


はい、ということで、今回はツーペアとフルハウスの解説をしました。
今までに解説した役と違い、バグを見落としてしまいがちな危険を孕んでいる役でした。

あとは
・ストレート
・ストレートフラッシュ
・ロイヤルフラッシュ
の判定が残っていますね。

ではまた次回~♪


トランプの画像はこちらからお借りしました。
ありがとうございます♪
http://sozai.7gates.net/docs/trump/



前の記事 ポーカーの役判定 数字の重なり編
次の記事 ポーカーの役判定 ストレート編
関連記事
ポーカーの役判定 最終回
ポーカーの役判定 ストレート編
ポーカーの役判定 ツーペア、フルハウス編
ポーカーの役判定 数字の重なり編
ポーカーの役判定プログラムを作ってみよう!

2017 日本だんでぃ協会 All Rights Reserved.