Javaプログラミング学習サイト ゆるゆるプログラミング

・ポーカーの役判定

ポーカーの役判定を行うJavaのプログラムをを作成しました。

ここでは、ジョーカーを除く5枚のカードからポーカーの役を判定する方法を詳しく解説します。

判定する役は、

 ロイヤルフラッシュ(ロイヤルストレートフラッシュ) … 同じマークのA・K・Q・J・10

 ストレートフラッシュ … 同じマークで連番

 フォーカード … 同じ数字が4枚

 フルハウス … 同じ数字が3枚と同じ数字が2枚の組み合わせ

 フラッシュ … 同じマークが5枚

 スリーカード … 同じ数字が3枚

 ストレート … 連番

 ツーペア … 同じ数字が2枚と、他の同じ数字が2枚の組み合わせ

 ワンペア … 同じ数字が2枚

 ノーペア(ハイカード) … 役なし

です。

配られたカード5枚の各数字の数と各マークの数を配列に格納し、その数字の連続性と各マ-クの個数を利用して役の判定を行います。

以下が、そのJavaのソースコードです。トランプをランダムに並び替えて、その束の上からジョーカーを除く5枚のカードを取り、その5枚でできるポーカーの役を判定してます。

PokerHands.java ← クリックしてダウンロードページに移動
001:    // トランプを操作するクラス
002:    class CardsManager {
003:    	// トランプ配列
004:    	private int[] cards;
005:    
006:    	//  配列の値
007:    	//  000 : ジョーカー
008:    	//  101~113 : スペードの1~13
009:    	//  201~213 : ハートの1~13
010:    	//  301~313 : ダイヤの1~13
011:    	//  401~413 : クラブの1~13
012:    
013:    	// コンストラクタ
014:    	public CardsManager()
015:    	{
016:    		// 配列を作成
017:    		cards = new int[ 13 * 4 + 1 ];
018:    
019:    		// 初期化
020:    		organize();
021:    	}
022:    
023:    
024:    	// トランプの整列
025:    	public void organize()
026:    	{
027:    		// ジョーカーを格納
028:    		cards[ 0 ] = 0;
029:    
030:    		for ( int i = 1; i <= 13; ++ i ) {
031:    			// スペードを格納(添え字:1~13)
032:    			cards[ i ] = 100 + i;
033:    
034:    			// ダイヤを格納(添え字:14~26)
035:    			cards[ i + 13 ] = 300 + i;
036:    
037:    			// クラブを格納(添え字:27~39)
038:    			cards[ i + 26 ] = 400 + i;
039:    
040:    			// ハートを格納(添え字:40~52)
041:    			cards[ i + 39 ] = 200 + i;
042:    		}
043:    	}
044:    
045:    
046:    	// トランプのシャッフル
047:    	public void shuffle()
048:    	{
049:    		for ( int i = 0; i < cards.length; ++ i ) {
050:    			// 0~(配列aryの個数-1)の乱数を発生
051:    			int rnd = (int)( Math.random() * (double)cards.length );
052:    
053:    			// cards[ i ]とcards[ rnd ]を入れ替える
054:    			int w = cards[ i ];
055:    			cards[ i ] = cards[ rnd ];
056:    			cards[ rnd ] = w;
057:    		}
058:    	}
059:    
060:    
061:    	// トランプの取得
062:    	public int getCard( int num )
063:    	{
064:    		// numが、1~53番目以外の場合、-1を戻す
065:    		if ( ( 1 > num ) || ( 53 < num ) ) return -1;
066:    
067:    		// カードを戻す
068:    		return cards[ num - 1 ];
069:    	}
070:    }
071:    
072:    
073:    // メイン
074:    public class PokerHands {
075:    	// エラー
076:    	static final int ERROR           = 0;
077:    
078:    	// ポーカーの役の定数を定義しています。
079:    	// ロイヤルフラッシュ(ロイヤルストレートフラッシュ)
080:    	static final int ROYAL_FLUSH     = 1;
081:    	// ストレートフラッシュ
082:    	static final int STRAIGHT_FLUSH  = 2;
083:    	// フォーカード
084:    	static final int FOUR_OF_A_KIND  = 3;
085:    	// フルハウス
086:    	static final int FULL_HOUSE      = 4;
087:    	// フラッシュ
088:    	static final int FLUSH           = 5;
089:    	// ストレート
090:    	static final int STRAIGHT        = 6;
091:    	// スリーカード
092:    	static final int THREE_OF_A_KIND = 7;
093:    	// ツーペア
094:    	static final int TWO_PAIR        = 8;
095:    	// ワンペア
096:    	static final int ONE_PAIR        = 9;
097:    	// ノーペア
098:    	static final int NO_PAIR         = 10;
099:    
100:    
101:    	// カード5枚を配列で渡して役を判定するメソッド
102:    	static int getPockerHand( int[] cards )
103:    	{
104:    		// 配列がnullだったらエラー
105:    		if ( null == cards ) return ERROR;
106:    
107:    		// 配列の個数が5でなければエラー
108:    		if ( 5 != cards.length ) return ERROR;
109:    
110:    
111:    		// トランプのマークの個数を格納する配列
112:    		int[] suit = new int[ 4 ];
113:    
114:    		// トランプのマークの個数に0を代入(初期化)
115:    		for ( int i = 0; i < suit.length; i++ )
116:    			suit[ i ] = 0;
117:    
118:    
119:    		// トランプの番号(1-13)の個数を格納する配列
120:    		// number[ 0 ]とnumber[13]の両方にAの個数を格納
121:    		int[] number = new int[ 14 ];
122:    
123:    		// トランプのマークの個数に0を代入(初期化)
124:    		for ( int i = 0; i < number.length; i++ )
125:    			number[ i ] = 0;
126:    
127:    		// 5枚のカードのマークと番号の個数を格納
128:    		for ( int i = 0; i < cards.length; i++ ) {
129:    			// マーク
130:    			int mark = cards[ i ] / 100;
131:    			// 番号
132:    			int num = cards[ i ] % 100;
133:    
134:    			// markが1から4の範囲外であればエラー
135:    			if ( ( 1 > mark ) || ( 4 < mark ) ) {
136:    				return ERROR;
137:    			}
138:    
139:    			// numが1から13の範囲外であればエラー
140:    			if ( ( 1 > num ) || ( 13 < num ) ) {
141:    				return ERROR;
142:    			}
143:    
144:    			// マークの個数に1を足す
145:    			++ suit[ mark - 1 ];
146:    
147:    			// 番号の個数に1を足す
148:    			++ number[ num - 1 ];
149:    		}
150:    		// number[ 13 ]にAの個数を代入
151:    		number[ 13 ] = number[ 0 ];
152:    
153:    		// 番号の個数の最大値を取得
154:    		int number_max = 0;
155:    		for ( int i = 0; i < number.length - 1; i++ ) {
156:    			if ( number_max < number[ i ] )
157:    				number_max = number[ i ];
158:    		}
159:    
160:    		// ここから判定処理
161:    
162:    		// 個数の最大が4の場合、フォーカード確定
163:    		if ( 4 == number_max )
164:    			return FOUR_OF_A_KIND;
165:    
166:    		
167:    		// マークの個数の最大値を取得
168:    		// 5枚のカードが同じマークの場合、suit_max=5となる
169:    		int suit_max = 0;
170:    		for ( int i = 0; i < suit.length; i++ ) {
171:    			if ( suit_max < suit[ i ] )
172:    				suit_max = suit[ i ];
173:    		}
174:    
175:    		// ストレートの判定
176:    		boolean isStraight = false;
177:    		int continuous1 = 0;
178:    		int firstnum = 0;
179:    		for ( int i = 0; i < number.length; ++ i ) {
180:    			if ( 1 != number[ i ] ) {
181:    				continuous1 = 0;
182:    				firstnum = 0;
183:    			}
184:    			else {
185:    				++ continuous1;
186:    				// ストレートの最初の番号を格納
187:    				if ( 1 == continuous1 )
188:    					firstnum = i + 1;
189:    
190:    				// 5回連続だったら
191:    				if ( 5 == continuous1 ) {
192:    					// ストレートは確定
193:    					isStraight = true;
194:    					break;
195:    				}
196:    			}
197:    		}
198:    
199:    		// マークが全て同じで、ストレートだったら
200:    		if ( ( 5 == suit_max ) && isStraight ) {
201:    			// ストレートの先頭の番号が10だったら
202:    			if ( 10 == firstnum ) {
203:    				// ロイヤルフラッシュ確定
204:    				return ROYAL_FLUSH;
205:    			}
206:    			// ストレートフラッシュ確定
207:    			return STRAIGHT_FLUSH;
208:    		}
209:    
210:    		// 個数の最大が3で、もう1つペアが存在したら
211:    		if ( 3 == number_max ) {
212:    			for ( int i = 0; i < number.length - 1; ++ i ) {
213:    				if ( 2 == number[ i ] ) {
214:    					// フルハウス確定
215:    					return FULL_HOUSE;
216:    				}
217:    			}
218:    		}
219:    
220:    
221:    		// マークが全て同じだったら
222:    		if ( 5 == suit_max ) {
223:    			// フラッシュ確定
224:    			return FLUSH;
225:    		}
226:    
227:    		// ストレートだったら
228:    		if ( isStraight ) {
229:    			// ストレート確定
230:    			return STRAIGHT;
231:    		}
232:    
233:    		// 個数の最大が3の場合、スリーカード確定
234:    		if ( 3 == number_max )
235:    			return THREE_OF_A_KIND;
236:    
237:    		// ペアの個数
238:    		int pair_num = 0;
239:    		for ( int i = 0; i < number.length - 1; ++ i ) {
240:    			if ( 2 == number[ i ] )
241:    				++ pair_num;
242:    		}
243:    
244:    		// ペアが2つであれば
245:    		if ( 2 == pair_num )
246:    			return TWO_PAIR;
247:    
248:    		// ペアが1つであれば
249:    		if ( 1 == pair_num )
250:    			return ONE_PAIR;
251:    
252:    		// ノーペア
253:    		return NO_PAIR;
254:    	}
255:    
256:    
257:    	// 番号を文字に変換
258:    	static String getStringNumber( int num ) {
259:    		switch ( num ) {
260:    			case 1:
261:    				return "A";
262:    			case 2:
263:    				return "2";
264:    			case 3:
265:    				return "3";
266:    			case 4:
267:    				return "4";
268:    			case 5:
269:    				return "5";
270:    			case 6:
271:    				return "6";
272:    			case 7:
273:    				return "7";
274:    			case 8:
275:    				return "8";
276:    			case 9:
277:    				return "9";
278:    			case 10:
279:    				return "10";
280:    			case 11:
281:    				return "J";
282:    			case 12:
283:    				return "Q";
284:    			case 13:
285:    				return "K";
286:    		}
287:    		return "";
288:    	}
289:    
290:    
291:    	// メイン
292:    	public static void main( String[] args ) {
293:    		// トランプクラスを作成
294:    		CardsManager cards = new CardsManager();
295:    
296:    		// 変数を宣言
297:    		int[] cards5 = new int[ 5 ];
298:    
299:    		// 200回処理
300:    		int loopcount = 200;
301:    		for ( int j = 0; j < loopcount; ++ j ) {
302:    			// トランプをシャッフル
303:    			cards.shuffle();
304:    
305:    			// トランプを上から順番に引いていく
306:    			int card_num = 0;
307:    			for ( int i = 1; i <= 53; ++ i ) {
308:    				// i番目のカードを取得
309:    				int card = cards.getCard( i );
310:    
311:    				// ジョーカーだったら配列に入れない
312:    				if ( 0 == card ) continue;
313:    
314:    				// カードが5枚になったらループを抜ける
315:    				cards5[ card_num] = card;
316:    				++ card_num;
317:    				if ( 5 == card_num ) break;
318:    			}
319:    
320:    
321:    			// カードを表示
322:    			for ( int i = 0; i < 5; ++ i ) {
323:    				// マーク
324:    				int mark = cards5[ i ] / 100;
325:    				// 番号
326:    				int num = cards5[ i ] % 100;
327:    
328:    				// 番号を文字列に変更
329:    				String strnum = getStringNumber( num );
330:    
331:    				// 表示
332:    				switch ( mark ) {
333:    					case 1:
334:    						// スペード
335:    						System.out.print( "S" + strnum );
336:    						break;
337:    					case 2:
338:    						// ハート
339:    						System.out.print( "H" + strnum );
340:    						break;
341:    					case 3:
342:    						// ダイヤ
343:    						System.out.print( "D" + strnum );
344:    						break;
345:    					case 4:
346:    						// クラブ
347:    						System.out.print( "C" + strnum );
348:    						break;
349:    				}
350:    				System.out.print( " " );
351:    			}
352:    
353:    			// 役を判定
354:    			int hand = getPockerHand( cards5 );
355:    			switch ( hand ) {
356:    				case ROYAL_FLUSH:
357:    					System.out.println( "ロイヤルフラッシュ" );	
358:    					break;
359:    
360:    				case STRAIGHT_FLUSH:
361:    					System.out.println( "ストレートフラッシュ" );	
362:    					break;
363:    
364:    				case FOUR_OF_A_KIND:
365:    					System.out.println( "フォーカード" );	
366:    					break;
367:    
368:    				case FULL_HOUSE:
369:    					System.out.println( "フルハウス" );	
370:    					break;
371:    
372:    				case FLUSH:
373:    					System.out.println( "フラッシュ" );	
374:    					break;
375:    
376:    				case STRAIGHT:
377:    					System.out.println( "ストレート" );	
378:    					break;
379:    
380:    				case THREE_OF_A_KIND:
381:    					System.out.println( "スリーカード" );	
382:    					break;
383:    
384:    				case TWO_PAIR:
385:    					System.out.println( "ツーペア" );	
386:    					break;
387:    
388:    				case ONE_PAIR:
389:    					System.out.println( "ワンペア" );
390:    					break;
391:    
392:    				default:
393:    					System.out.println( "ノーペア" );
394:    					break;
395:    			}
396:    		}
397:    	}
398:    }

PokerHands.javaの出力結果

C4 S7 H2 D6 C9 ノーペア
DK H5 D6 CK D8 ワンペア
HJ S9 HQ DK D10 ストレート
SQ S5 D7 C6 D10 ノーペア
H5 SJ D5 S8 HK ワンペア
C4 SQ SA S7 DA ワンペア
DJ D2 H4 C3 SK ノーペア

  :

CQ H4 D9 H8 DQ ワンペア
H5 C10 S3 H6 HJ ノーペア
SQ D9 H9 HK C2 ワンペア
C7 D8 S7 H7 H4 スリーカード
D9 CA C10 HK C7 ノーペア
D6 D9 C7 S9 C3 ワンペア

判定処理を200回を行っています。

結果の各行のスペース区切りの1~5番目が5枚のカードを表し、6番目が役を表しています。

カードの先頭のアルファベットはマークあらわすもので、'S'はスペード、'H'はハート、'D'はダイヤ、'C'はクラブです。アルファベットの右側の数字とアルファベットは番号で、'A'は1(エース)、'J'は11(ジャック)、'Q'は12(クィーン)、'K'は13(キング)です。

それでは、ポーカーの役を判定するプログラムのJavaソースコードを解説していきます。

001:    // トランプを操作するクラス
002:    class CardsManager {
003:    	// トランプ配列
004:    	private int[] cards;
005:    
006:    	//  配列の値
007:    	//  000 : ジョーカー
008:    	//  101~113 : スペードの1~13
009:    	//  201~213 : ハートの1~13
010:    	//  301~313 : ダイヤの1~13
011:    	//  401~413 : クラブの1~13
012:    
013:    	// コンストラクタ
014:    	public CardsManager()
015:    	{
016:    		// 配列を作成
017:    		cards = new int[ 13 * 4 + 1 ];
018:    
019:    		// 初期化
020:    		organize();
021:    	}
022:    
023:    
024:    	// トランプの整列
025:    	public void organize()
026:    	{
027:    		// ジョーカーを格納
028:    		cards[ 0 ] = 0;
029:    
030:    		for ( int i = 1; i <= 13; ++ i ) {
031:    			// スペードを格納(添え字:1~13)
032:    			cards[ i ] = 100 + i;
033:    
034:    			// ダイヤを格納(添え字:14~26)
035:    			cards[ i + 13 ] = 300 + i;
036:    
037:    			// クラブを格納(添え字:27~39)
038:    			cards[ i + 26 ] = 400 + i;
039:    
040:    			// ハートを格納(添え字:40~52)
041:    			cards[ i + 39 ] = 200 + i;
042:    		}
043:    	}
044:    
045:    
046:    	// トランプのシャッフル
047:    	public void shuffle()
048:    	{
049:    		for ( int i = 0; i < cards.length; ++ i ) {
050:    			// 0~(配列aryの個数-1)の乱数を発生
051:    			int rnd = (int)( Math.random() * (double)cards.length );
052:    
053:    			// cards[ i ]とcards[ rnd ]を入れ替える
054:    			int w = cards[ i ];
055:    			cards[ i ] = cards[ rnd ];
056:    			cards[ rnd ] = w;
057:    		}
058:    	}
059:    
060:    
061:    	// トランプの取得
062:    	public int getCard( int num )
063:    	{
064:    		// numが、1~53番目以外の場合、-1を戻す
065:    		if ( ( 1 > num ) || ( 53 < num ) ) return -1;
066:    
067:    		// カードを戻す
068:    		return cards[ num - 1 ];
069:    	}
070:    }

ここまでのソースコードの詳細はこちらを参考にしてください。「トランプの操作」

073:    // メイン
074:    public class PokerHands {

トランプを操作するクラス名を、PokerHandsとしています。

075:    	// エラー
076:    	static final int ERROR           = 0;
077:    
078:    	// ポーカーの役の定数を定義しています。
079:    	// ロイヤルフラッシュ(ロイヤルストレートフラッシュ)
080:    	static final int ROYAL_FLUSH     = 1;
081:    	// ストレートフラッシュ
082:    	static final int STRAIGHT_FLUSH  = 2;
083:    	// フォーカード
084:    	static final int FOUR_OF_A_KIND  = 3;
085:    	// フルハウス
086:    	static final int FULL_HOUSE      = 4;
087:    	// フラッシュ
088:    	static final int FLUSH           = 5;
089:    	// ストレート
090:    	static final int STRAIGHT        = 6;
091:    	// スリーカード
092:    	static final int THREE_OF_A_KIND = 7;
093:    	// ツーペア
094:    	static final int TWO_PAIR        = 8;
095:    	// ワンペア
096:    	static final int ONE_PAIR        = 9;
097:    	// ノーペア
098:    	static final int NO_PAIR         = 10;

ポーカーの役を定数として定義しています。

101:    	// カード5枚を配列で渡して役を判定するメソッド
102:    	static int getPockerHand( int[] cards )
103:    	{

ポーカーの役を判定するメソッドです。int型配列に5枚のカードを格納すると結果がint型で返ってきます。前述の定数のいずれかの値が結果として得られます。

引数として渡すカードの情報は整数で、以下のルールに従います。

  101~113は、スペードの1~13

  201~213は、ハートの1~13

  301~313は、ダイヤの1~13

  401~413は、クラブの1~13

104:    		// 配列がnullだったらエラー
105:    		if ( null == cards ) return ERROR;
106:    
107:    		// 配列の個数が5でなければエラー
108:    		if ( 5 != cards.length ) return ERROR;

引数の配列cardsがnullであったり、要素数が5でない場合は、定数のERRORを戻します。

111:    		// トランプのマークの個数を格納する配列
112:    		int[] suit = new int[ 4 ];
113:    
114:    		// トランプのマークの個数に0を代入(初期化)
115:    		for ( int i = 0; i < suit.length; i++ )
116:    			suit[ i ] = 0;

カード5枚のマークの個数を格納する配列suitを作成しています。マークは4種類なので配列要素数を4にしています。

  配列添え字0は、スペードです。

  配列添え字1は、ハートです。

  配列添え字2は、ダイヤです。

  配列添え字3は、クラブです。

119:    		// トランプの番号(1-13)の個数を格納する配列
120:    		// number[ 0 ]とnumber[13]の両方にAの個数を格納
121:    		int[] number = new int[ 14 ];
122:    
123:    		// トランプのマークの個数に0を代入(初期化)
124:    		for ( int i = 0; i < number.length; i++ )
125:    			number[ i ] = 0;

カード5枚の番号の個数を格納する配列を作成しています。番号の種類は1~13の13種類ですが、処理の都合上、配列要素数を14にしています。後ほど説明します。

127:    		// 5枚のカードのマークと番号の個数を格納
128:    		for ( int i = 0; i < cards.length; i++ ) {
129:    			// マーク
130:    			int mark = cards[ i ] / 100;
131:    			// 番号
132:    			int num = cards[ i ] % 100;
133:    
134:    			// markが1から4の範囲外であればエラー
135:    			if ( ( 1 > mark ) || ( 4 < mark ) ) {
136:    				return ERROR;
137:    			}
138:    
139:    			// numが1から13の範囲外であればエラー
140:    			if ( ( 1 > num ) || ( 13 < num ) ) {
141:    				return ERROR;
142:    			}
143:    
144:    			// マークの個数に1を足す
145:    			++ suit[ mark - 1 ];
146:    
147:    			// 番号の個数に1を足す
148:    			++ number[ num - 1 ];
149:    		}
150:    		// number[ 13 ]にAの個数を代入
151:    		number[ 13 ] = number[ 0 ];

5枚のカード情報を格納した配列cardsから、マークmarkと番号numを取得し、markに対応した配列suit[ mark - 1 ]に1を足しています。同様にnumに対応したnumber[ num - 1 ]も1を足しています。この処理で種類と番号の個数が配列に格納されます。

マークの種類と番号が範囲外の場合、ERRORを戻してメソッドを終了しています。

最後にnumber[13]にnumber[0]を代入しています。number[0]はA(エース)の個数なので、number[13]もA(エース)の個数になります。これは、役のストレートを判定する処理で、個数が1個の番号が連続で5回続くかを判定し易くするためのものです。例えば、A-K-Q-J-10をストレートと判定する場合、添え字が離れているAの個数number[0]とKの個数number[12]の連続性を判定するより、隣り合った配列で連続性を判定するほうが簡単です。

153:    		// 番号の個数の最大値を取得
154:    		int number_max = 0;
155:    		for ( int i = 0; i < number.length - 1; i++ ) {
156:    			if ( number_max < number[ i ] )
157:    				number_max = number[ i ];
158:    		}

5枚のカード番号の個数の最大値変数number_maxに格納しています。、

160:    		// ここから判定処理
161:    
162:    		// 個数の最大が4の場合、フォーカード確定
163:    		if ( 4 == number_max )
164:    			return FOUR_OF_A_KIND;

ここから判定処理です。

番号の個数の最大値number_maxが4のときフォーカードに決まります。このプログラムではジョーカーは使用しないためです。

ここからの判定は、強い役から順番に判定していきます。

167:    		// マークの個数の最大値を取得
168:    		// 5枚のカードが同じマークの場合、suit_max=5となる
169:    		int suit_max = 0;
170:    		for ( int i = 0; i < suit.length; i++ ) {
171:    			if ( suit_max < suit[ i ] )
172:    				suit_max = suit[ i ];
173:    		}

5枚のカードの種類の個数を最大値suit_maxに格納しています。

175:    		// ストレートの判定
176:    		boolean isStraight = false;
177:    		int continuous1 = 0;
178:    		int firstnum = 0;
179:    		for ( int i = 0; i < number.length; ++ i ) {
180:    			if ( 1 != number[ i ] ) {
181:    				continuous1 = 0;
182:    				firstnum = 0;
183:    			}
184:    			else {
185:    				++ continuous1;
186:    				// ストレートの最初の番号を格納
187:    				if ( 1 == continuous1 )
188:    					firstnum = i + 1;
189:    
190:    				// 5回連続だったら
191:    				if ( 5 == continuous1 ) {
192:    					// ストレートは確定
193:    					isStraight = true;
194:    					break;
195:    				}
196:    			}
197:    		}

番号の個数1が5連続しているかを判定してboolean型変数isStraightに結果を格納しています。連続していたらtrue、連続していなければfalseを格納しています。

また、5回連続している場合、その先頭の番号をint型変数firstnumに格納しています。これはロイヤルフラッシュ(ロイヤルストレートフラッシュ)の判定に使用します。

199:    		// マークが全て同じで、ストレートだったら
200:    		if ( ( 5 == suit_max ) && isStraight ) {
201:    			// ストレートの先頭の番号が10だったら
202:    			if ( 10 == firstnum ) {
203:    				// ロイヤルフラッシュ確定
204:    				return ROYAL_FLUSH;
205:    			}
206:    			// ストレートフラッシュ確定
207:    			return STRAIGHT_FLUSH;
208:    		}

5枚のカードの種類が全て同じで、番号が連続している場合の処理です。

この条件を満たすのは、ロイヤルフラッシュストレートフラッシュの2つです。

ここで役に立つのが変数firstnumです。これは連続している最初の数字を格納しているものなので、forstnumが10のとき、カードは10-J-Q-K-Aとなっており、ロイヤルフラッシュに決定します。10以外のときストレートフラッシュとなります。

210:    		// 個数の最大が3で、もう1つペアが存在したら
211:    		if ( 3 == number_max ) {
212:    			for ( int i = 0; i < number.length - 1; ++ i ) {
213:    				if ( 2 == number[ i ] ) {
214:    					// フルハウス確定
215:    					return FULL_HOUSE;
216:    				}
217:    			}
218:    		}

次は、フルハウスかどうかを判定します。

条件は番号の個数の最大値number_maxが3で、且つ、他のペアがあることです。他のペアがあるというのは、番号の個数を格納している配列numberの中に2が存在しているということです。

ここでは、for文でnumberの値が2のものを探して、見つかればフルハウスとしています。

ちなみに、ここでフルハウスでなかった場合、スリーカードとしては確定しません。強い役の順番で確定していくので、ここではスリーカードで確定させません。

221:    		// マークが全て同じだったら
222:    		if ( 5 == suit_max ) {
223:    			// フラッシュ確定
224:    			return FLUSH;
225:    		}

5枚のカードの種類が全て同じであれば、フラッシュ決定です。

227:    		// ストレートだったら
228:    		if ( isStraight ) {
229:    			// ストレート確定
230:    			return STRAIGHT;
231:    		}

5枚のカードの番号が連続していれば、ストレート決定です。

233:    		// 個数の最大が3の場合、スリーカード確定
234:    		if ( 3 == number_max )
235:    			return THREE_OF_A_KIND;

番号の個数の最大値number_maxが3であれば、スリーカード決定です。

237:    		// ペアの個数
238:    		int pair_num = 0;
239:    		for ( int i = 0; i < number.length - 1; ++ i ) {
240:    			if ( 2 == number[ i ] )
241:    				++ pair_num;
242:    		}

ペア(番号の個数が2のもの)を探し、その個数を変数pair_numに格納します。for文条件式を"i < number.length - 1"としているのはAのペアが2重にカウントされるのを避けるためです。number[ 13 ]にはnumber[ 0 ]と同じ値が入っているためです。

244:    		// ペアが2つであれば
245:    		if ( 2 == pair_num )
246:    			return TWO_PAIR;

ペアの個数pair_numが2であれば、、ツーペア決定です。

248:    		// ペアが1つであれば
249:    		if ( 1 == pair_num )
250:    			return ONE_PAIR;

ペアの個数pair_numが1であれば、、ワンペア決定です。

252:    		// ノーペア
253:    		return NO_PAIR;

どの役でもないので、ノーペア決定です。

ここまでが、ポーカーの役を判定方法の説明です。

次に、実際に判定するプログラムについて説明していきます。

257:    	// 番号を文字に変換
258:    	static String getStringNumber( int num ) {
259:    		switch ( num ) {
260:    			case 1:
261:    				return "A";
262:    			case 2:
263:    				return "2";
264:    			case 3:
265:    				return "3";
266:    			case 4:
267:    				return "4";
268:    			case 5:
269:    				return "5";
270:    			case 6:
271:    				return "6";
272:    			case 7:
273:    				return "7";
274:    			case 8:
275:    				return "8";
276:    			case 9:
277:    				return "9";
278:    			case 10:
279:    				return "10";
280:    			case 11:
281:    				return "J";
282:    			case 12:
283:    				return "Q";
284:    			case 13:
285:    				return "K";
286:    		}
287:    		return "";
288:    	}

int型変数numをトランプで使用している数字とアルファベットに変換しています。

291:    	// メイン
292:    	public static void main( String[] args ) {

このmainメソッドからプログラムを実行します。

293:    		// トランプクラスを作成
294:    		CardsManager cards = new CardsManager();

トランプを操作するクラスCardsManagerを作成します。ここでは、トランプは整列しています。

296:    		// 変数を宣言
297:    		int[] cards5 = new int[ 5 ];

カード5枚の情報を格納するint型配列を初期化しています。

299:    		// 200回処理
300:    		int loopcount = 200;
301:    		for ( int j = 0; j < loopcount; ++ j ) {

for文で200回のループを作成しています。

302:    			// トランプをシャッフル
303:    			cards.shuffle();

トランプをランダムで並び変えています。

305:    			// トランプを上から順番に引いていく
306:    			int card_num = 0;
307:    			for ( int i = 1; i <= 53; ++ i ) {
308:    				// i番目のカードを取得
309:    				int card = cards.getCard( i );
310:    
311:    				// ジョーカーだったら配列に入れない
312:    				if ( 0 == card ) continue;
313:    
314:    				// カードが5枚になったらループを抜ける
315:    				cards5[ card_num] = card;
316:    				++ card_num;
317:    				if ( 5 == card_num ) break;
318:    			}

並び変えたトランプの束から1枚づつ取っていき、5枚になったらbreak文for文を抜けます。ジョーカーは除外しています。

321:    			// カードを表示
322:    			for ( int i = 0; i < 5; ++ i ) {
323:    				// マーク
324:    				int mark = cards5[ i ] / 100;
325:    				// 番号
326:    				int num = cards5[ i ] % 100;
327:    
328:    				// 番号を文字列に変更
329:    				String strnum = getStringNumber( num );
330:    
331:    				// 表示
332:    				switch ( mark ) {
333:    					case 1:
334:    						// スペード
335:    						System.out.print( "S" + strnum );
336:    						break;
337:    					case 2:
338:    						// ハート
339:    						System.out.print( "H" + strnum );
340:    						break;
341:    					case 3:
342:    						// ダイヤ
343:    						System.out.print( "D" + strnum );
344:    						break;
345:    					case 4:
346:    						// クラブ
347:    						System.out.print( "C" + strnum );
348:    						break;
349:    				}
350:    				System.out.print( " " );
351:    			}

5枚のトランプをコンソール出力しています。printメソッドで出力しているので5枚のカード情報が1行に並びます。

353:    			// 役を判定
354:    			int hand = getPockerHand( cards5 );
355:    			switch ( hand ) {
356:    				case ROYAL_FLUSH:
357:    					System.out.println( "ロイヤルフラッシュ" );	
358:    					break;
359:    
360:    				case STRAIGHT_FLUSH:
361:    					System.out.println( "ストレートフラッシュ" );	
362:    					break;
363:    
364:    				case FOUR_OF_A_KIND:
365:    					System.out.println( "フォーカード" );	
366:    					break;
367:    
368:    				case FULL_HOUSE:
369:    					System.out.println( "フルハウス" );	
370:    					break;
371:    
372:    				case FLUSH:
373:    					System.out.println( "フラッシュ" );	
374:    					break;
375:    
376:    				case STRAIGHT:
377:    					System.out.println( "ストレート" );	
378:    					break;
379:    
380:    				case THREE_OF_A_KIND:
381:    					System.out.println( "スリーカード" );	
382:    					break;
383:    
384:    				case TWO_PAIR:
385:    					System.out.println( "ツーペア" );	
386:    					break;
387:    
388:    				case ONE_PAIR:
389:    					System.out.println( "ワンペア" );
390:    					break;
391:    
392:    				default:
393:    					System.out.println( "ノーペア" );
394:    					break;
395:    			}

5枚のトランプの情報をgetPockerHandメソッドに渡して役を判定しています。結果を格納した変数handの情報を元に、役をコンソール出力しています。

以上で説明を終わります。

■関連コンテンツ

トランプの操作 トランプを操作するクラス
配列の並び替え 配列をランダムに並び替える方法を解説
switch文 式による処理の分岐に使用するswitch文について解説
Math.randomの使い方について解説-画像

乱数 random

Math.randomメソッドを使って乱数を発生する方法を解説します。指定範囲の乱数の発生方法も解説しています。

サイコロの目のでる確率は?-画像

サイコロの出目確率

乱数で1から6の数を発生し、それぞれの数値が出現する回数を調べます。

サイコロの目のでる確率は?-画像

ゾロ目の出る確率

2つのサイコロの出目を乱数で1から6の数を発生し、出目が同じときの回数と出現率を調べます。

繰り返し処理に使用するfor文について解説-画像

for文

繰り返し処理に使用するfor文をJavaのソースコードを使って説明しています。

条件による処理の分岐に使用するif文について解説-画像

if文

条件による処理の分岐に使用するif文について解説

■新着情報

2020.10.28 1からNの和 1+2+3+ … +N=?
2020.10.21 画像の上下反転 画像を上下反転する方法
2020.10.19 指定色の画素数取得 指定RGBの画素数は何個?
2020.10.13 2値化 その2 2値のBMP画像を作成
2020.10.07 3辺の長さで三角形かを判定 3辺abcで三角形が作れるか?
2020.10.06 画像のミラー反転 画像をミラー(鏡)反転する方法
2020.09.03 お札とコインの数 必要なお札と硬貨の枚数?

■広告

フィギュア予約最大25%OFF+ポイント5%還元!ホビーサーチ

~約8,000名の受講生と80社以上の導入実績~ 企業向けプログラミング研修ならCodeCamp

日本最大級ショッピングサイト!お買い物なら楽天市場

 

 

 

 

 

 

 

 

 

Topへ