mirror of
https://github.com/Stone-Red-Code/se-poker.git
synced 2026-09-09 07:56:11 +02:00
Refactor into classes
This commit is contained in:
@@ -0,0 +1,185 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sort"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type Hand struct {
|
||||
Cards []Card
|
||||
}
|
||||
|
||||
// NewHand parses an input string and returns a new Hand.
|
||||
func NewHand(input string) (*Hand, error) {
|
||||
parts := strings.Fields(input)
|
||||
if len(parts) != 5 {
|
||||
return nil, fmt.Errorf("invalid number of cards: %d", len(parts))
|
||||
}
|
||||
|
||||
var cards []Card
|
||||
valueMap := map[byte]int{
|
||||
'2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9,
|
||||
'T': 10, 'J': 11, 'Q': 12, 'K': 13, 'A': 14,
|
||||
}
|
||||
|
||||
for _, p := range parts {
|
||||
if len(p) != 2 {
|
||||
return nil, fmt.Errorf("invalid card format: %s", p)
|
||||
}
|
||||
suitChar := string(p[0])
|
||||
valChar := p[1]
|
||||
|
||||
val, ok := valueMap[valChar]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("invalid value: %c", valChar)
|
||||
}
|
||||
cards = append(cards, Card{Suit: suitChar, Value: val})
|
||||
}
|
||||
return &Hand{Cards: cards}, nil
|
||||
}
|
||||
|
||||
type HandCategory int
|
||||
|
||||
const (
|
||||
HighCard HandCategory = iota
|
||||
Pair
|
||||
TwoPair
|
||||
ThreeOfAKind
|
||||
Straight
|
||||
Flush
|
||||
FullHouse
|
||||
FourOfAKind
|
||||
StraightFlush
|
||||
RoyalFlush
|
||||
)
|
||||
|
||||
var handNames = []string{
|
||||
"High Card", "Pair", "Two Pair", "Three of a Kind", "Straight",
|
||||
"Flush", "Full House", "Four of a Kind", "Straight Flush", "Royal Flush",
|
||||
}
|
||||
|
||||
type HandResult struct {
|
||||
Category HandCategory
|
||||
TieBreakers []int
|
||||
}
|
||||
|
||||
// Evaluate evaluates the hand and returns its category and tiebreakers.
|
||||
func (h *Hand) Evaluate() HandResult {
|
||||
sort.Slice(h.Cards, func(i, j int) bool {
|
||||
return h.Cards[i].Value > h.Cards[j].Value
|
||||
})
|
||||
|
||||
counts := make(map[int]int)
|
||||
suits := make(map[string]int)
|
||||
for _, c := range h.Cards {
|
||||
counts[c.Value]++
|
||||
suits[c.Suit]++
|
||||
}
|
||||
|
||||
isFlush := len(suits) == 1
|
||||
isStraight, straightHigh := h.checkStraight()
|
||||
|
||||
if isFlush && isStraight {
|
||||
if straightHigh == 14 {
|
||||
return HandResult{Category: RoyalFlush, TieBreakers: []int{}}
|
||||
}
|
||||
return HandResult{Category: StraightFlush, TieBreakers: []int{straightHigh}}
|
||||
}
|
||||
|
||||
type group struct {
|
||||
val int
|
||||
count int
|
||||
}
|
||||
var groups []group
|
||||
for v, c := range counts {
|
||||
groups = append(groups, group{v, c})
|
||||
}
|
||||
sort.Slice(groups, func(i, j int) bool {
|
||||
if groups[i].count != groups[j].count {
|
||||
return groups[i].count > groups[j].count
|
||||
}
|
||||
return groups[i].val > groups[j].val
|
||||
})
|
||||
|
||||
var tieBreakers []int
|
||||
for _, g := range groups {
|
||||
tieBreakers = append(tieBreakers, g.val)
|
||||
}
|
||||
if len(groups) > 1 && groups[0].count == 1 {
|
||||
// Fallback for Straight/Flush Sortierung: sicherstellen, dass es rein nach Wert geht
|
||||
tieBreakers = nil
|
||||
for _, c := range h.Cards {
|
||||
tieBreakers = append(tieBreakers, c.Value)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if groups[0].count == 4 {
|
||||
return HandResult{Category: FourOfAKind, TieBreakers: []int{groups[0].val, groups[1].val}}
|
||||
}
|
||||
if groups[0].count == 3 && groups[1].count == 2 {
|
||||
return HandResult{Category: FullHouse, TieBreakers: []int{groups[0].val, groups[1].val}}
|
||||
}
|
||||
if isFlush {
|
||||
return HandResult{Category: Flush, TieBreakers: tieBreakers}
|
||||
}
|
||||
if isStraight {
|
||||
return HandResult{Category: Straight, TieBreakers: []int{straightHigh}}
|
||||
}
|
||||
if groups[0].count == 3 {
|
||||
return HandResult{Category: ThreeOfAKind, TieBreakers: []int{groups[0].val, groups[1].val, groups[2].val}}
|
||||
}
|
||||
if groups[0].count == 2 && groups[1].count == 2 {
|
||||
return HandResult{Category: TwoPair, TieBreakers: []int{groups[0].val, groups[1].val, groups[2].val}}
|
||||
}
|
||||
if groups[0].count == 2 {
|
||||
return HandResult{Category: Pair, TieBreakers: []int{groups[0].val, groups[1].val, groups[2].val, groups[3].val}}
|
||||
}
|
||||
|
||||
return HandResult{Category: HighCard, TieBreakers: tieBreakers}
|
||||
}
|
||||
|
||||
func (h *Hand) checkStraight() (bool, int) {
|
||||
isStd := true
|
||||
for i := 0; i < 4; i++ {
|
||||
if h.Cards[i].Value != h.Cards[i+1].Value+1 {
|
||||
isStd = false
|
||||
break
|
||||
}
|
||||
}
|
||||
if isStd {
|
||||
return true, h.Cards[0].Value
|
||||
}
|
||||
|
||||
if h.Cards[0].Value == 14 && h.Cards[1].Value == 5 && h.Cards[2].Value == 4 && h.Cards[3].Value == 3 && h.Cards[4].Value == 2 {
|
||||
return true, 5
|
||||
}
|
||||
|
||||
return false, 0
|
||||
}
|
||||
|
||||
// Compare compares the current hand with another hand.
|
||||
// Returns 1 if the current hand wins, 2 if the other hand wins, and 0 for a tie.
|
||||
func (h *Hand) Compare(other *Hand) int {
|
||||
h1Result := h.Evaluate()
|
||||
h2Result := other.Evaluate()
|
||||
|
||||
if h1Result.Category > h2Result.Category {
|
||||
return 1
|
||||
}
|
||||
if h2Result.Category > h1Result.Category {
|
||||
return 2
|
||||
}
|
||||
|
||||
for i := 0; i < len(h1Result.TieBreakers); i++ {
|
||||
if h1Result.TieBreakers[i] > h2Result.TieBreakers[i] {
|
||||
return 1
|
||||
}
|
||||
if h2Result.TieBreakers[i] > h1Result.TieBreakers[i] {
|
||||
return 2
|
||||
}
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
||||
Reference in New Issue
Block a user