-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathPokerHand.java
executable file
·411 lines (334 loc) · 12.2 KB
/
PokerHand.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
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
399
400
401
402
403
404
405
406
407
408
409
410
411
/**
* PokerHand.java
* Name: Quang Nguyen Dang
* Login ID: dangn1
* This class is responsible to provide classifications and convenient methods to
* classify a poker hand and compare between two hands.
*/
import java.util.ArrayList;
import java.util.Collections;
public enum PokerHand {
/**
* The purpose of this class is to hold information about 9 classifications
* of poker hand, their orders (based on classification order, the higher the
* value is, the higher the classification is) and support main program.
*
* This class provide two main methods to support main program:
*
* 1. checkHandClassification to return the actual classification of a
* player's hand.
*
* 2. compareTwoHands to determine the result of win or draw among two
* poker hands.
*
* The class assumes that the player's raw hand (array of cards generated
* from command line input) that it takes to process is sorted in descending
* order. Therefore, to make sure that all static methods in this class work
* properly, the given player's raw hand has to be sorted in descending
* order.
*
* Additionally, there are two static variables that this class holds to
* support its methods:
*
* 1. Extra information: to support classification checking and comparing
* by holding a number of ranks of a player's poker hand depending on
* actual hand classification of that player. The logic of extra information
* implemented in this class is to put the more decisive values (higher
* cards, rank of set, higher rank of pairs etc) first and they are sorted
* based on their importance (for example: rank of set is put before rank of
* pairs).
*
* 2. Player description: also support classification checking by
* determining player's hand description depending on actual hand
* classification of that player.
*/
HIGH_CARD(1), ONE_PAIR(2), TWO_PAIR(3), THREE_OF_A_KIND(4), STRAIGHT(5), FLUSH(
6), FULL_HOUSE(7), FOUR_OF_A_KIND(8), STRAIGHT_FLUSH(9);
// Instance variable
private int classificationOrder; // Classification order
// Static variables
private static Rank[] extraInfo; // Extra information
private static String playerDescription; // Description
// Constructor
/**
* @param classificationOrder Order of a hand classification
*/
private PokerHand(int classificationOrder) {
this.classificationOrder = classificationOrder;
}
// Getter
/**
* @return Order of a hand classification
*/
public int getClassificationOrder() {
return this.classificationOrder;
}
// Static methods
/**
* This method checks the classification of a player's raw hand, determines
* the appropriate extra information needed to compare between two player's
* poker hand and the description of a player's poker hand.
* @param p Player object
*/
public static void checkHandClassification(Player p) {
// Store player's raw hand
Card[] playerRawHand = p.getPlayerRawHand();
// Store n-of-a-kind cards (if available)
ArrayList<NOfAKind> checkNOfAKind = PokerHand
.checkNOfAKind(playerRawHand);
// Check straight flush
if (PokerHand.checkStraightHand(playerRawHand)
&& PokerHand.checkFlushHand(playerRawHand)) {
// Set player hand
p.setPlayerHand(PokerHand.STRAIGHT_FLUSH);
// Extra information
extraInfo = PokerHand.getRankArray(playerRawHand);
p.setExtraInfo(extraInfo);
// Set player's hand description
playerDescription = "Player " + Integer.toString(p.getPlayerNo())
+ ": " + extraInfo[0] + "-high straight flush";
p.setDescription(playerDescription);
}
// Check four of a kind
else if (checkNOfAKind.size() == 1
&& checkNOfAKind.get(0).getDuplicateTimes() == 4) {
p.setPlayerHand(PokerHand.FOUR_OF_A_KIND);
p.setExtraInfo(extraInfo);
playerDescription = "Player " + Integer.toString(p.getPlayerNo())
+ ": " + "Four " + extraInfo[0] + "s";
p.setDescription(playerDescription);
}
// Check full house
else if (checkNOfAKind.size() == 2
&& (checkNOfAKind.get(0).getDuplicateTimes() + checkNOfAKind
.get(1).getDuplicateTimes()) == 5) {
p.setPlayerHand(PokerHand.FULL_HOUSE);
p.setExtraInfo(extraInfo);
playerDescription = "Player " + Integer.toString(p.getPlayerNo())
+ ": " + extraInfo[0] + "s full of " + extraInfo[1] + "s";
p.setDescription(playerDescription);
}
// Check flush
else if (PokerHand.checkFlushHand(playerRawHand)) {
p.setPlayerHand(PokerHand.FLUSH);
extraInfo = PokerHand.getRankArray(playerRawHand);
p.setExtraInfo(extraInfo);
playerDescription = "Player " + Integer.toString(p.getPlayerNo())
+ ": " + extraInfo[0] + "-high flush";
p.setDescription(playerDescription);
}
// Check straight
else if (PokerHand.checkStraightHand(playerRawHand)) {
p.setPlayerHand(PokerHand.STRAIGHT);
extraInfo = PokerHand.getRankArray(playerRawHand);
p.setExtraInfo(extraInfo);
playerDescription = "Player " + Integer.toString(p.getPlayerNo())
+ ": " + extraInfo[0] + "-high straight";
p.setDescription(playerDescription);
}
// Check three of a kind
else if (checkNOfAKind.size() == 1
&& (checkNOfAKind.get(0).getDuplicateTimes() == 3)) {
p.setPlayerHand(PokerHand.THREE_OF_A_KIND);
p.setExtraInfo(extraInfo);
playerDescription = "Player " + Integer.toString(p.getPlayerNo())
+ ": Three " + extraInfo[0] + "s";
p.setDescription(playerDescription);
}
// Check two pair
else if (checkNOfAKind.size() == 2
&& (checkNOfAKind.get(0).getDuplicateTimes() + checkNOfAKind
.get(1).getDuplicateTimes()) == 4) {
p.setPlayerHand(PokerHand.TWO_PAIR);
p.setExtraInfo(extraInfo);
playerDescription = "Player " + Integer.toString(p.getPlayerNo())
+ ": " + extraInfo[0] + "s over " + extraInfo[1] + "s";
p.setDescription(playerDescription);
}
// Check one pair
else if (checkNOfAKind.size() == 1
&& checkNOfAKind.get(0).getDuplicateTimes() == 2) {
p.setPlayerHand(PokerHand.ONE_PAIR);
p.setExtraInfo(extraInfo);
playerDescription = "Player " + Integer.toString(p.getPlayerNo())
+ ": Pair of " + extraInfo[0] + "s";
p.setDescription(playerDescription);
}
// High card
else {
p.setPlayerHand(PokerHand.HIGH_CARD);
extraInfo = PokerHand.getRankArray(playerRawHand);
p.setExtraInfo(extraInfo);
playerDescription = "Player " + Integer.toString(p.getPlayerNo())
+ ": " + extraInfo[0] + "-high";
p.setDescription(playerDescription);
}
}
/**
* This method compares two poker hand to determine the winner among the
* two by first comparing their classification order and then the extra
* information if necessary.
* @param p1 First player object
* @param p2 Second player object
* @return Null if two players draw or the winner player's object
*/
public static Player compareTwoHands(Player p1, Player p2) {
// First compare the classification order of two player's poker hand
if (p1.getPlayerHand().getClassificationOrder() >
p2.getPlayerHand().getClassificationOrder()) {
return p1;
} else if (p1.getPlayerHand().getClassificationOrder() <
p2.getPlayerHand().getClassificationOrder()) {
return p2;
} else {
// If two classification orders are same, compare the value
// inside extra information array
Player winner = null;
for (int i = 0; i < p1.getExtraInfo().length; i++) {
if (p1.getExtraInfo()[i] != p2.getExtraInfo()[i]) {
int rankOrderOfP1 = p1.getExtraInfo()[i].getRankOrder();
int rankOrderOfP2 = p2.getExtraInfo()[i].getRankOrder();
if (Math.max(rankOrderOfP1, rankOrderOfP2) == rankOrderOfP1) {
winner = p1;
break;
} else {
winner = p2;
break;
}
}
}
// Return null if two players draw or the winner
if (winner != null) {
return winner;
} else {
return null;
}
}
}
/**
* This method checks whether a player's raw hand is straight or not.
* @param hand Array of cards in a hand
* @return true if a player's raw hand is straight and false if not
*/
public static boolean checkStraightHand(Card[] hand) {
// Check whether the rank of cards in the hand are in consecutive order
// or not
for (int i = 0; i < hand.length - 1; i++) {
if (Math.abs(hand[i + 1].getRank().getRankOrder()
- hand[i].getRank().getRankOrder()) != 1) {
return false;
}
}
return true;
}
/**
* This method checks whether a player's raw hand is flush or not.
* @param hand Array of cards in a hand
* @return true if a player's raw hand is flush and false if not
*/
public static boolean checkFlushHand(Card[] hand) {
// Check whether the suit of cards in the hand are the same or not
for (int i = 1; i < hand.length; i++) {
if (hand[0].getSuit() != hand[i].getSuit()) {
return false;
}
}
return true;
}
/**
* This method checks a player's raw hand to find out any duplication
* of card(s) (based on card rank only) in this hand. From that, we can
* determine whether that/those duplication(s) mean(s) pair(s)/three of
* a kind/four of a kind. Also, this method sets static extra information
* required for classification checking and comparing.
* @param hand A player's raw hand
* @return An ArrayList (of NOfAKind type) contains duplicated card(s)
* and how many times it/they is/are duplicated.
*/
public static ArrayList<NOfAKind> checkNOfAKind(Card[] hand) {
// To store found duplicated cards in the given hand to avoid
// determining those cards again
ArrayList<Rank> duplicateList = new ArrayList<Rank>();
// To store found non-duplicated cards in the given hand to separate
// duplicated and non-duplicated cards to determine extra information
// for classification checking and comparing.
ArrayList<Rank> nonDuplicateList = new ArrayList<Rank>();
// To store duplicated card(s) and how many times it/they is/are
// duplicated
ArrayList<NOfAKind> finalList = new ArrayList<NOfAKind>();
// Check the duplication of card(s) in given player's raw hand and
// assign to final list
for (int i = 0; i < hand.length; i++) {
int duplicateTimes = PokerHand.getDuplicateTimes(hand, hand[i]);
// Check if cards appear more than one and not in duplicate list yet
if ( duplicateTimes > 1
&& !duplicateList.contains(hand[i].getRank())) {
duplicateList.add(hand[i].getRank());
finalList.add(new NOfAKind(hand[i].getRank(), duplicateTimes));
}
// Fulfil non duplicate list with cards appear only once
else {
nonDuplicateList.add(hand[i].getRank());
}
}
// Sort the final list based on duplicate times of card
Collections.sort(finalList);
// Get duplicate list from sorted final list
duplicateList.clear();
for (NOfAKind nOfAKind : finalList) {
duplicateList.add(nOfAKind.getCardRank());
}
// Combine the duplicated list with non-duplicated list
// to provide the extra information needed to n-of-a-kind
// classification. The whole idea of this operation is to put
// the duplicated card first (means rank of n-of-a-kind first)
// to compare and then non-duplicated will be compared later
// if necessary
duplicateList.addAll(nonDuplicateList);
extraInfo = PokerHand.convert(duplicateList);
return finalList;
}
/**
* This method gets all card ranks from a given cards array and put them
* into another Rank array.
* @param hand Array of cards in a hand
* @return An array of ranks from given cards array
*/
public static Rank[] getRankArray(Card[] hand) {
int s = hand.length;
Rank[] rankArray = new Rank[s];
for (int i = 0; i < s; i++) {
rankArray[i] = hand[i].getRank();
}
return rankArray;
}
/**
* This method is used to convert a Rank ArrayList to a Rank array
* @param rankList A Rank ArrayList
* @return a Rank array
*/
public static Rank[] convert(ArrayList<Rank> rankList) {
int s = rankList.size();
Rank[] rankArray = new Rank[s];
for (int i = 0; i < s; i++) {
rankArray[i] = rankList.get(i);
}
return rankArray;
}
/**
* This method returns how many times an card appear in an array of
* cards.
* @param hand Array of cards in a hand
* @param card A card object
* @return
*/
private static int getDuplicateTimes(Card[] hand, Card card) {
int duplicateTimes = 0;
for (int i = 0; i < hand.length; i++) {
if (hand[i].getRank() == card.getRank()) {
duplicateTimes ++;
}
}
return duplicateTimes;
}
}