-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathhand.go
253 lines (229 loc) · 4.78 KB
/
hand.go
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
package poker
/*
In the card game poker, a hand consists of five cards and are ranked, from
lowest to highest, in the following way:
High Card: Highest value card.
One Pair: Two cards of the same value.
Two Pairs: Two different pairs.
Three of a Kind: Three cards of the same value.
Straight: All cards are consecutive values.
Flush: All cards of the same suit.
Full House: Three of a kind and a pair.
Four of a Kind: Four cards of the same value.
Straight Flush: All cards are consecutive values of same suit.
Royal Flush: Ten, Jack, Queen, King, Ace, in same suit.
The cards are valued in the order:
2, 3, 4, 5, 6, 7, 8, 9, 10, Jack, Queen, King, Ace.
*/
import (
"sort"
"strings"
)
type Hand struct {
cards []Card
}
// implement sort interface
func (h Hand) Len() int {
return len(h.cards)
}
// sort cards by significance for the hand type
func (h Hand) Less(i, j int) bool {
a, b := h.cards[i], h.cards[j]
arank, brank := a.RankIndex(), b.RankIndex()
retval := true
if arank == brank {
retval = a.SuitIndex() < b.SuitIndex()
} else {
// count number of a, b ranks in this hand
acount, bcount := 0, 0
for _, c := range h.cards {
if a.Rank() == c.Rank() {
acount++
}
if b.Rank() == c.Rank() {
bcount++
}
}
if acount == bcount {
// same -- compare rank
retval = arank < brank
} else {
// pick higher count
retval = acount > bcount
}
}
return retval
}
func (h Hand) Swap(i, j int) {
h.cards[i], h.cards[j] = h.cards[j], h.cards[i]
}
func (h Hand) String() string {
s := make([]string, len(h.cards))
for _, c := range h.cards {
cs := c.String()
// TODO: why doesn't this work?
// cs := string(c)
s = append(s, cs)
}
return strings.Join(s, " ")
}
// Hand ranks
const (
HighCard = iota
Pair
TwoPair
ThreeOfAKind
Straight
Flush
FullHouse
FourOfAKind
StraightFlush
RoyalFlush
)
////////////////////////////////////////////////////////////////
// Helper methods
// helper method -- return map of ranks to counts
func (h Hand) countRanks() map[string][]Card {
ranks := make(map[string][]Card)
for _, c := range h.cards {
rank := c.Rank()
ranks[rank] = append(ranks[rank], c)
}
return ranks
}
// helper method -- check if n of same rank
func (h Hand) isNOfAKind(n int) bool {
isNOfAKind := false
for _, ary := range h.countRanks() {
if len(ary) == n {
isNOfAKind = true
break
}
}
return isNOfAKind
}
////////////////////////////////////////////////////////////////
// Exported methods
// IsStraight returns bool and high card
func (h Hand) IsStraight() bool {
var ranks []int
for _, c := range h.cards {
ranks = append(ranks, c.RankIndex())
}
sort.Ints(ranks)
isStraight := true
prev, ranks := ranks[0], ranks[1:]
for _, r := range ranks {
if prev+1 != r {
isStraight = false
break
}
prev = r
}
return isStraight
}
func (h Hand) IsFlush() bool {
suit := h.cards[0].Suit()
isFlush := true
for _, c := range h.cards {
val := c.Suit()
if val != suit {
isFlush = false
break
}
}
return isFlush
}
func (h Hand) IsRoyalFlush() bool {
return h.HighCard().Rank() == "A" && h.IsStraightFlush()
}
func (h Hand) IsStraightFlush() bool {
return h.IsStraight() && h.IsFlush()
}
func (h Hand) IsFourOfAKind() bool {
return h.isNOfAKind(4)
}
func (h Hand) IsFullHouse() bool {
foundTwo, foundThree := false, false
for _, ary := range h.countRanks() {
switch len(ary) {
case 3:
foundThree = true
case 2:
foundTwo = true
}
}
return foundThree && foundTwo
}
func (h Hand) IsTwoPair() bool {
numPairs := 0
for _, ary := range h.countRanks() {
if len(ary) == 2 {
numPairs++
}
}
return numPairs == 2
}
func (h Hand) IsThreeOfAKind() bool {
return h.isNOfAKind(3)
}
func (h Hand) IsPair() bool {
return h.isNOfAKind(2)
}
func (h Hand) HighCard() Card {
return h.cards[0]
}
func (h Hand) Rank() int {
rank := HighCard
switch {
case h.IsRoyalFlush():
rank = RoyalFlush
case h.IsStraightFlush():
rank = StraightFlush
case h.IsFourOfAKind():
rank = FourOfAKind
case h.IsFullHouse():
rank = FullHouse
case h.IsFlush():
rank = Flush
case h.IsStraight():
rank = Straight
case h.IsThreeOfAKind():
rank = ThreeOfAKind
case h.IsTwoPair():
rank = TwoPair
case h.IsPair():
rank = Pair
default:
rank = HighCard
}
return rank
}
func (h Hand) Beats(other Hand) bool {
rank := h.Rank()
otherRank := other.Rank()
wins := false
switch {
case rank > otherRank:
wins = true
case otherRank > rank:
wins = false
default:
{
// else pick highest ranking card
for ii := 0; ii < len(h.cards); ii++ {
switch {
case h.cards[ii].Rank() > other.cards[ii].Rank():
wins = true
case h.cards[ii].Rank() < other.cards[ii].Rank():
wins = false
default:
continue
}
// determined..
break
}
}
}
return wins
}