package j2.lesson04;
import j2.lesson04.card.Card;
/**
* 課題1704 - 解答例 (2/2).
* ポーカーの手札を表す.
* @author arakawa
* @version $Id: PokerHand_java.rps,v 1.1 2006/03/06 12:56:14 java2005 Exp $
*/
public class PokerHand {
/** 役なし. */
private static final int NONE = 0;
/** ロイヤルストレートフラッシュ. */
private static final int ROYAL_FLUSH = 1;
/** ストレートフラッシュ. */
private static final int STRAIGHT_FLUSH = 2;
/** フォーカード. */
private static final int FOUR_OF_KIND = 3;
/** フルハウス. */
private static final int FULL_HOUSE = 4;
/** フラッシュ. */
private static final int FLUSH = 5;
/** ストレート. */
private static final int STRAIGHT = 6;
/** スリーカード. */
private static final int THREE_OF_KIND = 7;
/** ツーペア. */
private static final int TWO_PAIR = 8;
/** ワンペア. */
private static final int ONE_PAIR = 9;
/** 役の名前. */
private static final String[] RANK_NAME = {
"なし", "ロイヤルストレートフラッシュ", "ストレートフラッシュ", "フォーカード", "フルハウス",
"フラッシュ", "ストレート", "スリーカード", "ツーペア", "ワンペア", };
/**
* 実際の手札。
*/
private final Card[] cards;
/**
* 役を表す整数。
* @see #ROYAL_FLUSH
* @see #STRAIGHT_FLUSH
* @see #FOUR_OF_KIND
* @see #FULL_HOUSE
* @see #FLUSH
* @see #STRAIGHT
* @see #THREE_OF_KIND
* @see #TWO_PAIR
* @see #ONE_PAIR
* @see #NONE
*/
private final int rankOfHand;
/**
* 手札を生成する.
* @param c1 1番目のカード
* @param c2 2番目のカード
* @param c3 3番目のカード
* @param c4 4番目のカード
* @param c5 5番目のカード
*/
public PokerHand(Card c1, Card c2, Card c3, Card c4, Card c5) {
super();
this.cards = new Card[] { c1, c2, c3, c4, c5 };
this.rankOfHand = checkRank();
}
/**
* 指定した位置のカードを指定したカードと交換する。
* 位置は <code>0..4</code> の範囲内で指定する必要がある。
* @param at 交換する位置
* @param card 交換するカード
* @return 指定した位置にあった古いカード
*/
public Card change(int at, Card card) {
Card old = this.cards[at];
this.cards[at] = card;
return old;
}
/**
* 指定した位置にあるカードを取得する。
* 位置は <code>0..4</code> の範囲内で指定する必要がある。
* @param at 取得するカードの位置
* @return カード
*/
public Card get(int at) {
return this.cards[at];
}
/**
* 現在の手札の役を文字列として取得する。
* @return 手札の役を表す文字列
*/
public String getRank() {
return RANK_NAME[this.rankOfHand];
}
/**
* 手札の役を調べる。
* @return 手札の役を表す数値
* @see #ROYAL_FLUSH
* @see #STRAIGHT_FLUSH
* @see #FOUR_OF_KIND
* @see #FULL_HOUSE
* @see #FLUSH
* @see #STRAIGHT
* @see #THREE_OF_KIND
* @see #TWO_PAIR
* @see #ONE_PAIR
* @see #NONE
*/
private int checkRank() {
int[] ranks = new int[13];
// ランクごとの出現枚数を数える
for (int i = 0; i < this.cards.length; i++) {
ranks[this.cards[i].getRankAsInt() - 1]++;
}
boolean flush = hasFlush();
boolean straight = hasStraight(ranks);
boolean four = countSameRank(4, ranks) > 0;
boolean three = countSameRank(3, ranks) > 0;
int pairs = countSameRank(2, ranks);
// 強い順に調べる
if (hasRoyalRanks(ranks) && flush) {
return ROYAL_FLUSH;
}
else if (straight && flush) {
return STRAIGHT_FLUSH;
}
else if (four) {
return FOUR_OF_KIND;
}
else if (three && pairs == 1) {
return FULL_HOUSE;
}
else if (flush) {
return FLUSH;
}
else if (straight) {
return STRAIGHT;
}
else if (three) {
return THREE_OF_KIND;
}
else if (pairs == 2) {
return TWO_PAIR;
}
else if (pairs == 1) {
return ONE_PAIR;
}
else {
return NONE;
}
}
/**
* 現在の手札が A, 10, J, Q, K のランクからなるか調べる。
* @param ranks ランクごとの出現枚数
* @return 現在の手札が A, 10, J, Q, K のランクからなるならば <code>true</code>
*/
private boolean hasRoyalRanks(int[] ranks) {
return ranks[0] == 1 && ranks[9] == 1 && ranks[10] == 1 && ranks[11] == 1 && ranks[12] == 1;
}
/**
* 指定した枚数の同じランクを持つカードが何セットあるか調べる。
* @param n 数える枚数
* @param ranks ランクごとの出現枚数
* @return 上記のようなセットの個数
*/
private int countSameRank(int n, int[] ranks) {
int count = 0;
for (int i = 0; i < ranks.length; i++) {
if (ranks[i] == n) {
count++;
}
}
return count;
}
/**
* カードのランクが5枚連続しているかどうか調べる。
* @param ranks ランクごとの出現枚数
* @return ランクが5枚連続していれば <code>true</code>
*/
private boolean hasStraight(int[] ranks) {
// カードが連続した数
int count = 0;
for (int i = 0; i < ranks.length; i++) {
if (ranks[i] == 0) {
// 一度でも 1 を見ていたら、ランクの連続はここで終わり
if (count >= 1) {
break;
}
}
else if (ranks[i] == 1) {
// 1 を連続して見た回数を増やす
count++;
}
else {
// ペアがあればストレートにはならない
return false;
}
}
// 5枚連続していればストレート
if (count == 5) {
return true;
}
else {
return false;
}
}
/**
* カードのマークが全て同じかどうか調べる。
* @return 全て同じならば <code>true</code>
*/
private boolean hasFlush() {
// 最初のカードと一枚でもマークが違えば何もしない
int firstSuite = this.cards[0].getSuiteAsInt();
for (int i = 1; i < this.cards.length; i++) {
if (firstSuite != this.cards[i].getSuiteAsInt()) {
return false;
}
}
// 全て同じならフラッシュ
return true;
}
}
|