2020.08.27

Javaプログラミング

ポーカーの役判定

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

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

判定する役は、以下のとおりです。

ロイヤルフラッシュ(ロイヤルストレートフラッシュ)…同じマークのA・K・Q・J・10
ストレートフラッシュ…同じマークで連番
フォーカード…同じ数字が4枚
フルハウス…同じ数字が3枚と同じ数字が2枚の組み合わせ
フラッシュ…同じマークが5枚
スリーカード…同じ数字が3枚
ストレート…連番
ツーペア…同じ数字が2枚と、他の同じ数字が2枚の組み合わせ
ワンペア…同じ数字が2枚
ノーペア(ハイカード)…役なし

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

Javaソースコード

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

PokerHands.java

001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028
029
030
031
032
033
034
035
036
037
038
039
040
041
042
043
044
045
046
047
048
049
050
051
052
053
054
055
056
057
058
059
060
061
062
063
064
065
066
067
068
069
070
071
072
073
074
075
076
077
078
079
080
081
082
083
084
085
086
087
088
089
090
091
092
093
094
095
096
097
098
099
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
// トランプを操作するクラス
class CardsManager {
	// トランプ配列
	private int[] cards;

	//  配列の値
	//  000 : ジョーカー
	//  101~113 : スペードの1~13
	//  201~213 : ハートの1~13
	//  301~313 : ダイヤの1~13
	//  401~413 : クラブの1~13

	// コンストラクタ
	public CardsManager()
	{
		// 配列を作成
		cards = new int[ 13 * 4 + 1 ];

		// 初期化
		organize();
	}


	// トランプの整列
	public void organize()
	{
		// ジョーカーを格納
		cards[ 0 ] = 0;

		for ( int i = 1; i <= 13; ++ i ) {
			// スペードを格納(添え字:1~13)
			cards[ i ] = 100 + i;

			// ダイヤを格納(添え字:14~26)
			cards[ i + 13 ] = 300 + i;

			// クラブを格納(添え字:27~39)
			cards[ i + 26 ] = 400 + i;

			// ハートを格納(添え字:40~52)
			cards[ i + 39 ] = 200 + i;
		}
	}


	// トランプのシャッフル
	public void shuffle()
	{
		for ( int i = 0; i < cards.length; ++ i ) {
			// 0~(配列aryの個数-1)の乱数を発生
			int rnd =  (int)( Math.random() *  (double)cards.length );

			// cards[ i ]とcards[ rnd ]を入れ替える
			int w = cards[ i ];
			cards[ i ] = cards[ rnd ];
			cards[ rnd ] = w;
		}
	}


	// トランプの取得
	public int getCard( int num )
	{
		// numが、1~53番目以外の場合、-1を戻す
		if ( ( 1 > num ) || ( 53 < num ) ) return -1;

		// カードを戻す
		return cards[ num - 1 ];
	}
}


// メイン
public class PokerHands {
	// エラー
	static final int ERROR           = 0;

	// ポーカーの役の定数を定義しています。
	// ロイヤルフラッシュ(ロイヤルストレートフラッシュ)
	static final int ROYAL_FLUSH     = 1;
	// ストレートフラッシュ
	static final int STRAIGHT_FLUSH  = 2;
	// フォーカード
	static final int FOUR_OF_A_KIND  = 3;
	// フルハウス
	static final int FULL_HOUSE      = 4;
	// フラッシュ
	static final int FLUSH           = 5;
	// ストレート
	static final int STRAIGHT        = 6;
	// スリーカード
	static final int THREE_OF_A_KIND = 7;
	// ツーペア
	static final int TWO_PAIR        = 8;
	// ワンペア
	static final int ONE_PAIR        = 9;
	// ノーペア
	static final int NO_PAIR         = 10;


	// カード5枚を配列で渡して役を判定するメソッド
	static int getPockerHand( int[] cards )
	{
		// 配列がnullだったらエラー
		if ( null == cards ) return ERROR;

		// 配列の個数が5でなければエラー
		if ( 5 != cards.length ) return ERROR;


		// トランプのマークの個数を格納する配列
		int[] suit = new int[ 4 ];

		// トランプのマークの個数に0を代入(初期化)
		for ( int i = 0; i < suit.length; i++ )
			suit[ i ] = 0;


		// トランプの番号(1-13)の個数を格納する配列
		// number[ 0 ]とnumber[13]の両方にAの個数を格納
		int[] number = new int[ 14 ];

		// トランプのマークの個数に0を代入(初期化)
		for ( int i = 0; i < number.length; i++ )
			number[ i ] = 0;

		// 5枚のカードのマークと番号の個数を格納
		for ( int i = 0; i < cards.length; i++ ) {
			// マーク
			int mark = cards[ i ] / 100;
			// 番号
			int num = cards[ i ] % 100;

			// markが1から4の範囲外であればエラー
			if ( ( 1 > mark ) || ( 4 < mark ) ) {
				return ERROR;
			}

			// numが1から13の範囲外であればエラー
			if ( ( 1 > num ) || ( 13 < num ) ) {
				return ERROR;
			}

			// マークの個数に1を足す
			++ suit[ mark - 1 ];

			// 番号の個数に1を足す
			++ number[ num - 1 ];
		}
		// number[ 13 ]にAの個数を代入
		number[ 13 ] = number[ 0 ];

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

		// ここから判定処理

		// 個数の最大が4の場合、フォーカード確定
		if ( 4 == number_max )
			return FOUR_OF_A_KIND;

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

		// ストレートの判定
		boolean isStraight = false;
		int continuous1 = 0;
		int firstnum = 0;
		for ( int i = 0; i < number.length; ++ i ) {
			if ( 1 != number[ i ] ) {
				continuous1 = 0;
				firstnum = 0;
			}
			else {
				++ continuous1;
				// ストレートの最初の番号を格納
				if ( 1 == continuous1 )
					firstnum = i + 1;

				// 5回連続だったら
				if ( 5 == continuous1 ) {
					// ストレートは確定
					isStraight = true;
					break;
				}
			}
		}

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

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


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

		// ストレートだったら
		if ( isStraight ) {
			// ストレート確定
			return STRAIGHT;
		}

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

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

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

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

		// ノーペア
		return NO_PAIR;
	}


	// 番号を文字に変換
	static String getStringNumber( int num ) {
		switch ( num ) {
			case 1:
				return "A";
			case 2:
				return "2";
			case 3:
				return "3";
			case 4:
				return "4";
			case 5:
				return "5";
			case 6:
				return "6";
			case 7:
				return "7";
			case 8:
				return "8";
			case 9:
				return "9";
			case 10:
				return "10";
			case 11:
				return "J";
			case 12:
				return "Q";
			case 13:
				return "K";
		}
		return ";"
	}


	// メイン
	public static void main( String[] args ) {
		// トランプクラスを作成
		CardsManager cards = new CardsManager();

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

		// 200回処理
		int loopcount = 200;
		for ( int j = 0; j < loopcount; ++ j ) {
			// トランプをシャッフル
			cards.shuffle();

			// トランプを上から順番に引いていく
			int card_num = 0;
			for ( int i = 1; i <= 53; ++ i ) {
				// i番目のカードを取得
				int card = cards.getCard( i );

				// ジョーカーだったら配列に入れない
				if ( 0 == card ) continue;

				// カードが5枚になったらループを抜ける
				cards5[ card_num] = card;
				++ card_num;
				if ( 5 == card_num ) break;
			}


			// カードを表示
			for ( int i = 0; i < 5; ++ i ) {
				// マーク
				int mark = cards5[ i ] / 100;
				// 番号
				int num = cards5[ i ] % 100;

				// 番号を文字列に変更
				String strnum = getStringNumber( num );

				// 表示
				switch ( mark ) {
					case 1:
						// スペード
						System.out.print( "S" + strnum );
						break;
					case 2:
						// ハート
						System.out.print( "H" + strnum );
						break;
					case 3:
						// ダイヤ
						System.out.print( "D" + strnum );
						break;
					case 4:
						// クラブ
						System.out.print( "C" + strnum );
						break;
				}
				System.out.print( " " );
			}

			// 役を判定
			int hand = getPockerHand( cards5 );
			switch ( hand ) {
				case ROYAL_FLUSH:
					System.out.println( "ロイヤルフラッシュ" );	
					break;

				case STRAIGHT_FLUSH:
					System.out.println( "ストレートフラッシュ" );	
					break;

				case FOUR_OF_A_KIND:
					System.out.println( "フォーカード" );	
					break;

				case FULL_HOUSE:
					System.out.println( "フルハウス" );	
					break;

				case FLUSH:
					System.out.println( "フラッシュ" );	
					break;

				case STRAIGHT:
					System.out.println( "ストレート" );	
					break;

				case THREE_OF_A_KIND:
					System.out.println( "スリーカード" );	
					break;

				case TWO_PAIR:
					System.out.println( "ツーペア" );	
					break;

				case ONE_PAIR:
					System.out.println( "ワンペア" );
					break;

				default:
					System.out.println( "ノーペア" );
					break;
			}
		}
	}
}

実行結果

コンパイル ソースコードが「ANSI」の場合

C:\talavax\javasample>javac -encoding sjis PokerHands.java

コンパイル ソースコードが「UTF-8」の場合

C:\talavax\javasample>javac PokerHands.java

PokerHandsを実行

C:\talavax\javasample>java PokerHands
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ソースコートの解説

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

001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028
029
030
031
032
033
034
035
036
037
038
039
040
041
042
043
044
045
046
047
048
049
050
051
052
053
054
055
056
057
058
059
060
061
062
063
064
065
066
067
068
069
070
// トランプを操作するクラス
class CardsManager {
	// トランプ配列
	private int[] cards;

	//  配列の値
	//  000 : ジョーカー
	//  101~113 : スペードの1~13
	//  201~213 : ハートの1~13
	//  301~313 : ダイヤの1~13
	//  401~413 : クラブの1~13

	// コンストラクタ
	public CardsManager()
	{
		// 配列を作成
		cards = new int[ 13 * 4 + 1 ];

		// 初期化
		organize();
	}


	// トランプの整列
	public void organize()
	{
		// ジョーカーを格納
		cards[ 0 ] = 0;

		for ( int i = 1; i <= 13; ++ i ) {
			// スペードを格納(添え字:1~13)
			cards[ i ] = 100 + i;

			// ダイヤを格納(添え字:14~26)
			cards[ i + 13 ] = 300 + i;

			// クラブを格納(添え字:27~39)
			cards[ i + 26 ] = 400 + i;

			// ハートを格納(添え字:40~52)
			cards[ i + 39 ] = 200 + i;
		}
	}


	// トランプのシャッフル
	public void shuffle()
	{
		for ( int i = 0; i < cards.length; ++ i ) {
			// 0~(配列aryの個数-1)の乱数を発生
			int rnd =  (int)( Math.random() *  (double)cards.length );

			// cards[ i ]とcards[ rnd ]を入れ替える
			int w = cards[ i ];
			cards[ i ] = cards[ rnd ];
			cards[ rnd ] = w;
		}
	}


	// トランプの取得
	public int getCard( int num )
	{
		// numが、1~53番目以外の場合、-1を戻す
		if ( ( 1 > num ) || ( 53 < num ) ) return -1;

		// カードを戻す
		return cards[ num - 1 ];
	}
}

ここまでのソースコードの詳細は以下の記事を参考にしてください。

トランプ(カード)を扱うクラスを紹介しています。

2019.08.05

ここから、ポーカーの役を判定する処理です。

073
074
// メイン
public class PokerHands {

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

075
076
077
078
079
080
081
082
083
084
085
086
087
088
089
090
091
092
093
094
095
096
097
098
	// エラー
	static final int ERROR           = 0;

	// ポーカーの役の定数を定義しています。
	// ロイヤルフラッシュ(ロイヤルストレートフラッシュ)
	static final int ROYAL_FLUSH     = 1;
	// ストレートフラッシュ
	static final int STRAIGHT_FLUSH  = 2;
	// フォーカード
	static final int FOUR_OF_A_KIND  = 3;
	// フルハウス
	static final int FULL_HOUSE      = 4;
	// フラッシュ
	static final int FLUSH           = 5;
	// ストレート
	static final int STRAIGHT        = 6;
	// スリーカード
	static final int THREE_OF_A_KIND = 7;
	// ツーペア
	static final int TWO_PAIR        = 8;
	// ワンペア
	static final int ONE_PAIR        = 9;
	// ノーペア
	static final int NO_PAIR         = 10;

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

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

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

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

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

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

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

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

104
105
106
107
108
		// 配列がnullだったらエラー
		if ( null == cards ) return ERROR;

		// 配列の個数が5でなければエラー
		if ( 5 != cards.length ) return ERROR;

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

111
112
113
114
115
116
		// トランプのマークの個数を格納する配列
		int[] suit = new int[ 4 ];

		// トランプのマークの個数に0を代入(初期化)
		for ( int i = 0; i < suit.length; i++ )
			suit[ i ] = 0;

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

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

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

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

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

119
120
121
122
123
124
125
		// トランプの番号(1-13)の個数を格納する配列
		// number[ 0 ]とnumber[13]の両方にAの個数を格納
		int[] number = new int[ 14 ];

		// トランプのマークの個数に0を代入(初期化)
		for ( int i = 0; i < number.length; i++ )
			number[ i ] = 0;

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

127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
		// 5枚のカードのマークと番号の個数を格納
		for ( int i = 0; i < cards.length; i++ ) {
			// マーク
			int mark = cards[ i ] / 100;
			// 番号
			int num = cards[ i ] % 100;

			// markが1から4の範囲外であればエラー
			if ( ( 1 > mark ) || ( 4 < mark ) ) {
				return ERROR;
			}

			// numが1から13の範囲外であればエラー
			if ( ( 1 > num ) || ( 13 < num ) ) {
				return ERROR;
			}

			// マークの個数に1を足す
			++ suit[ mark - 1 ];

			// 番号の個数に1を足す
			++ number[ num - 1 ];
		}
		// number[ 13 ]にAの個数を代入
		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
155
156
157
158
		// 番号の個数の最大値を取得
		int number_max = 0;
		for ( int i = 0; i < number.length - 1; i++ ) {
			if ( number_max < number[ i ] )
				number_max = number[ i ];
		}

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

160
161
162
163
164
		// ここから判定処理

		// 個数の最大が4の場合、フォーカード確定
		if ( 4 == number_max )
			return FOUR_OF_A_KIND;

ここから判定処理です。

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

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

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

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

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

				// 5回連続だったら
				if ( 5 == continuous1 ) {
					// ストレートは確定
					isStraight = true;
					break;
				}
			}
		}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

252
253
		// ノーペア
		return NO_PAIR;

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

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

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

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

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
300
301
		// 200回処理
		int loopcount = 200;
		for ( int j = 0; j < loopcount; ++ j ) {

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

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

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

305
306
307
308
309
310
311
312
313
314
315
316
317
318
			// トランプを上から順番に引いていく
			int card_num = 0;
			for ( int i = 1; i <= 53; ++ i ) {
				// i番目のカードを取得
				int card = cards.getCard( i );

				// ジョーカーだったら配列に入れない
				if ( 0 == card ) continue;

				// カードが5枚になったらループを抜ける
				cards5[ card_num] = card;
				++ card_num;
				if ( 5 == card_num ) break;
			}

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

321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
			// カードを表示
			for ( int i = 0; i < 5; ++ i ) {
				// マーク
				int mark = cards5[ i ] / 100;
				// 番号
				int num = cards5[ i ] % 100;

				// 番号を文字列に変更
				String strnum = getStringNumber( num );

				// 表示
				switch ( mark ) {
					case 1:
						// スペード
						System.out.print( "S" + strnum );
						break;
					case 2:
						// ハート
						System.out.print( "H" + strnum );
						break;
					case 3:
						// ダイヤ
						System.out.print( "D" + strnum );
						break;
					case 4:
						// クラブ
						System.out.print( "C" + strnum );
						break;
				}
				System.out.print( " " );
			}

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

353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
			// 役を判定
			int hand = getPockerHand( cards5 );
			switch ( hand ) {
				case ROYAL_FLUSH:
					System.out.println( "ロイヤルフラッシュ" );	
					break;

				case STRAIGHT_FLUSH:
					System.out.println( "ストレートフラッシュ" );	
					break;

				case FOUR_OF_A_KIND:
					System.out.println( "フォーカード" );	
					break;

				case FULL_HOUSE:
					System.out.println( "フルハウス" );	
					break;

				case FLUSH:
					System.out.println( "フラッシュ" );	
					break;

				case STRAIGHT:
					System.out.println( "ストレート" );	
					break;

				case THREE_OF_A_KIND:
					System.out.println( "スリーカード" );	
					break;

				case TWO_PAIR:
					System.out.println( "ツーペア" );	
					break;

				case ONE_PAIR:
					System.out.println( "ワンペア" );
					break;

				default:
					System.out.println( "ノーペア" );
					break;
			}

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

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

関連コンテンツ

Javaの学習に役立つソースコードを多数紹介しています。是非、ご覧ください。

2022.09.10

簡単な「じゃんけん」ゲームの作り方をソースコードを使って詳しく説明しています。

2023.05.22

連続で「じゃんけん」ができるプログラムの作り方をソースコードを使って詳しく説明しています。

2023.05.23

同じ型の変数(データ)を複数個まとめて管理するデータの持ちかたがあります。これが配列です。くわしくは、記事をご覧ください。

2016.01.14

乱数の意味と、Math.randomメソッドの使い方をソースコードを使って詳しく解説しています。

2015.12.27

プログラミング、ITに関する用語をまとめています。

2022.10.17

条件式を判断して処理を分岐する方法を詳しく説明しています。

2023.03.20

メソッドを抜けるときに使用するreturn文について説明しています。

2020.03.20

式の値によって処理を分岐する方法を詳しく解説しています。

2016.08.04

繰り返し処理を制御するための機能の1つである「continue」について詳しく解説しています。

2019.10.16

繰り返し処理(ループ)から強制的に抜けかたについて解説しています。

2017.07.14

変数やクラスに格納されている値をコンソール出力する方法は?

2020.03.23

プログラムの最初に実行されるメソッドは?

2022.12.13

プログラミングで使う変数って何?

2020.03.23

Javaのプログラムを書いてみませんか?プログラムの書き方をくわしく説明しています。

2020.03.23

「Javaソースコード」から実行可能な「オブジェクトコード」に変換する方法をくわしく説明しています。

2020.03.23

プログラミング言語とは?種類や特徴について説明しています。

2022.08.03

Javaプログラムの構成について解説しています。詳しくは、こちらをご覧ください。

2020.03.23

メソッドの定義方法を詳しく解説しています。Javaのサンプルソースコードを使った説明もあります。

2020.03.23

自然数と整数って何が違う?

2020.03.23

数値を2進数で表したときの各桁の「0」と「1」に対して演算を行えます。4種類の演算、AND(論理積)、OR(論理和)、XOR(排他的論理和)、NOT(否定)を詳しく説明しています。

2016.03.26

for文で変数名iがよく使われる理由について説明しています。興味のある方は是非。

2022.08.29

2つの値のうち、小さい方の値と、大きい方の値を取得する方法。

2020.03.23

処理を繰り返すために使用するfor文について解説しています。

2020.03.23

繰り返し処理の作り方を解説しています。

2016.03.02

広告