repl.it
@ActionJack/

Poker Hand Generator/Evaluator

JavaScript

Randomly generates a hand of cards and determines their best poker hand.

fork
loading
main.js
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
//First we establish a list of card values and rank them from lowest to highest so the program can know what a high card is.

var cardTypes= ["2 of ","3 of ","4 of ","5 of ", "6 of ","7 of ","8 of ","9 of ","10 of ","Jack of ","Queen of ","King of ","Ace of "];

//Then we rank the possible hands from lowest to highest. We don't currently use this, but it'll be handy if we ever need to compare two different hands to pick a winner.

var handRanks= 
[ '2 high',
  '3 high',
  '4 high',
  '5 high',
  '6 high',
  '7 high',
  '8 high',
  '9 high',
  '10 high',
  'Jack high',
  'Queen high',
  'King high',
  'Ace high',
  'Pair of 2',
  'Pair of 3',
  'Pair of 4',
  'Pair of 5',
  'Pair of 6',
  'Pair of 7',
  'Pair of 8',
  'Pair of 9',
  'Pair of 10',
  'Pair of Jack',
  'Pair of Queen',
  'Pair of King',
  'Pair of Ace',
  'Two pair',
  'Three of a kind',
  'Straight',
  'Full house',
  'Four of a kind',
  'Straight flush',
  'Royal flush!' 
];

//We establish an array of zeroes, one for each card value, to help the program keep track of whether pairs have been found.

var typeCount= [0,0,0,0,0,0,0,0,0,0,0,0,0]

//We establish the names of the different suits.

var suitNames=["Spades","Hearts","Clubs","Diamonds"];

//Now we can generate individual cards by picking two random numbers, one for the suit and the other for the value.

function getCard(){
  var suit = suitNames[(Math.floor(Math.random()*4))];
  var valueLocation= (Math.floor(Math.random()*13));
  var value = cardTypes[valueLocation];
  return(value+suit)
}

//We can then generate a hand by generating five cards and grouping them in an array...

function getHand(){
  var hand=[];
  for(var card=1;card<=5;card++){
    var nextCard=getCard();
    //...but since a hand should never have two of the exact same card, if we generate something that's already in our hand we backpedal and generate a new card.
    if(hand.indexOf(nextCard)>0){
      card--;
      let decrementValue= cardTypes.indexOf(nextCard.slice(0,nextCard.lastIndexOf(" ")+1));
      continue;
    }
    hand.push(nextCard)
  }
  return(hand)
}

//Since cards are just a descriptive string and don't actually know what suit and value they are, this function will let us scan the string and return what suit the card is.

function findSuit(card){
  var suitLocation=card.lastIndexOf(" ")+1;
  return card.slice(suitLocation,card.length)
}

//Now we can start evaluating for patterns in the hand to figure out what our result is.  First we check for a straight.

function straightCheck(){
  //We start by finding the lowest value that appears once in the hand.
  let start = typeCount.indexOf(1);
  //If there are no values that appear exactly once, we don't have a straight.
  if(start===-1){
    return false;
  }
  //If the lowest represented value is better than a 10, we don't have a straight. 
  if(typeCount.length-5<start){
    return false;
  }
  //And if the next four higher values aren't represented exactly once, we don't have a straight.
  for(let i=start+1;i<start+5;i++){
    if(typeCount[i]!==1){
      return false;
    }
  }
  //If we haven't hit a false result, then we have a straight.
  return true;
}

//Then we check for a flush.

function flushCheck(hand){
  //We do this by looking at each card in the hand except the first.  If its suit is different from the card before it, we don't have a flush.
  for(var card=1;card<hand.length;card++){
    if(findSuit(hand[card])!==findSuit(hand[card-1])){
      return false;
    }
  }
  //But if each card passes the test, we have a flush.
  return true;
}

//Now that we can check for both a straight and a flush, it's pretty simple to check for a straight flush.

function straightFlushCheck(hand){
  //console.log(straightCheck()); 
  //console.log(flushCheck(hand));
  return (straightCheck()===true && flushCheck(hand)===true);
}

//We can also check for a royal flush by running our flush check alongside a custom straight check that only evaluates number of occurences of the five highest values.

function royalFlushCheck(hand){
  for(let i=8; i<typeCount.length;i++){
    if(typeCount[i]!==1){
      return false;
    }
  }
  return flushCheck(hand);
}

//We can check for a full house by seeing if a value is represented twice and another is represented three times.

function fullHouseCheck(){
  if(typeCount.indexOf(2)>-1 && typeCount.indexOf(3)>-1){
    return true;
  }
  return false;
}

//We can also find a two-pair by seeing whether two different values are represented twice.

function twoPairCheck(){
  if(typeCount.indexOf(2)>-1 && typeCount.indexOf(2)!==typeCount.lastIndexOf(2)){
    return true;
  }
  return false;
}

//Four of a kind and three of a kind are even easier to check...

function fourOfAKindCheck(){
  return(typeCount.indexOf(4)!==-1);
}

function threeOfAKindCheck(){
  return(typeCount.indexOf(3)!==-1);
}

//...but for a single pair, we need to evaluate the value of the duplicate by finding its index in the typeCount and pulling its name as a string from the names in cardTypes.

function pairCheck(){
  if(typeCount.indexOf(2)===-1){
    return false;
  }
  let pairValue= cardTypes[typeCount.indexOf(2)].slice(0, cardTypes[typeCount.indexOf(2)].indexOf(" "));
  //if(pairValue.length>2){
    pairValue+="s";
  //}
  return ("Pair of " + pairValue)
}

//We also get the name if our hand is a measly high card.

function highCard(){
  for(let i=typeCount.length;i>0;i--){
    if(typeCount[i]===1){
      return(cardTypes[i].slice(0, cardTypes[i].indexOf(" ")) + " high")
    }
  }
}

//Now that we can check for all of the hands, we put them all together in a function that accepts a five-card hand, then runs each check in descending order from best hand to worst hand.  Once a hand is found, the function breaks and does not check for the lesser hands.

function handCheck(hand){
  console.log(hand);
  var cardValue="";
  for(let card=0; card<hand.length; card++){
    cardValue= hand[card].slice(0,hand[card].lastIndexOf(" ")+1);
    typeCount[cardTypes.indexOf(cardValue)]++;
  }
  //console.log(typeCount);
  if(royalFlushCheck(hand)===true){
    return "Royal flush!";
  }
  if(straightFlushCheck(hand)===true){
    return "Straight flush";
  }
  if(fourOfAKindCheck()===true){
    return "Four of a kind";
  }
  if(fullHouseCheck()===true){
    return "Full house";
  }
  if(flushCheck(hand)===true){
    return "Flush";
  }
  if(straightCheck()===true){
    return "Straight";
  }
  if(threeOfAKindCheck()===true){
    return "Three of a kind";
  }
  if(twoPairCheck()===true){
    return "Two pair";
  }
  if(pairCheck()!==false){
    return pairCheck();
  }
  return highCard();
}

//Our final function just generates a random hand and runs it through the checker.

function pokerHand(){
  return handCheck(getHand());
}

pokerHand()
Native Browser JavaScript
?