go_games_collection/poker_hand_test.go
2026-07-10 09:12:06 +03:00

150 lines
8 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package main
import "testing"
func TestEvaluate5Categories(t *testing.T) {
tests := []struct {
name string
cards []Card
want PokerHandCategory
}{
{"роял-флеш", []Card{c(Ten, Spades), c(Jack, Spades), c(Queen, Spades), c(King, Spades), c(Ace, Spades)}, PokerStraightFlush},
{"стрит-флеш", []Card{c(Five, Hearts), c(Six, Hearts), c(Seven, Hearts), c(Eight, Hearts), c(Nine, Hearts)}, PokerStraightFlush},
{"каре", []Card{c(Nine, Clubs), c(Nine, Diamonds), c(Nine, Hearts), c(Nine, Spades), c(Two, Clubs)}, PokerFourOfAKind},
{"фулл-хаус", []Card{c(King, Clubs), c(King, Diamonds), c(King, Hearts), c(Two, Spades), c(Two, Clubs)}, PokerFullHouse},
{"флеш", []Card{c(Two, Hearts), c(Five, Hearts), c(Seven, Hearts), c(Nine, Hearts), c(King, Hearts)}, PokerFlush},
{"стрит", []Card{c(Four, Clubs), c(Five, Diamonds), c(Six, Hearts), c(Seven, Spades), c(Eight, Clubs)}, PokerStraight},
{"колесо (A-5 стрит)", []Card{c(Ace, Clubs), c(Two, Diamonds), c(Three, Hearts), c(Four, Spades), c(Five, Clubs)}, PokerStraight},
{"тройка", []Card{c(Jack, Clubs), c(Jack, Diamonds), c(Jack, Hearts), c(Two, Spades), c(Nine, Clubs)}, PokerThreeOfAKind},
{"две пары", []Card{c(Ten, Clubs), c(Ten, Diamonds), c(Four, Hearts), c(Four, Spades), c(Nine, Clubs)}, PokerTwoPair},
{"пара", []Card{c(Eight, Clubs), c(Eight, Diamonds), c(Two, Hearts), c(Five, Spades), c(Nine, Clubs)}, PokerPair},
{"старшая карта", []Card{c(Two, Clubs), c(Five, Diamonds), c(Seven, Hearts), c(Nine, Spades), c(King, Clubs)}, PokerHighCard},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := evaluate5(tt.cards)
if got.Category != tt.want {
t.Errorf("ожидалась категория %v, получено %v (карты: %v)", tt.want, got.Category, tt.cards)
}
})
}
}
func TestWheelStraightRanksAsFive(t *testing.T) {
wheel := evaluate5([]Card{c(Ace, Clubs), c(Two, Diamonds), c(Three, Hearts), c(Four, Spades), c(Five, Clubs)})
if wheel.Category != PokerStraight || wheel.Tiebreak[0] != 5 {
t.Fatalf("колесо A-2-3-4-5 должно оцениваться как стрит со старшей картой 5, получено %+v", wheel)
}
sixHighStraight := evaluate5([]Card{c(Two, Clubs), c(Three, Diamonds), c(Four, Hearts), c(Five, Spades), c(Six, Clubs)})
if ComparePokerHands(sixHighStraight, wheel) <= 0 {
t.Errorf("стрит 2-6 должен быть старше колеса A-5")
}
}
func TestNotAStraightWhenWheelBrokenByAceHigh(t *testing.T) {
notStraight := evaluate5([]Card{c(Ace, Clubs), c(Two, Diamonds), c(Three, Hearts), c(Four, Spades), c(King, Clubs)})
if notStraight.Category == PokerStraight || notStraight.Category == PokerStraightFlush {
t.Errorf("A,2,3,4,K не должно засчитываться как стрит, получено %v", notStraight.Category)
}
}
func TestRoyalFlushBeatsStraightFlush(t *testing.T) {
royal := evaluate5([]Card{c(Ten, Spades), c(Jack, Spades), c(Queen, Spades), c(King, Spades), c(Ace, Spades)})
lower := evaluate5([]Card{c(Five, Hearts), c(Six, Hearts), c(Seven, Hearts), c(Eight, Hearts), c(Nine, Hearts)})
if ComparePokerHands(royal, lower) <= 0 {
t.Errorf("роял-флеш должен быть строго сильнее стрит-флеша 5-9")
}
}
func TestFourOfAKindKickerBreaksTie(t *testing.T) {
a := evaluate5([]Card{c(Nine, Clubs), c(Nine, Diamonds), c(Nine, Hearts), c(Nine, Spades), c(King, Clubs)})
b := evaluate5([]Card{c(Nine, Clubs), c(Nine, Diamonds), c(Nine, Hearts), c(Nine, Spades), c(Two, Clubs)})
if ComparePokerHands(a, b) <= 0 {
t.Errorf("одинаковое каре девяток с кикером королём должно побеждать кикер двойку")
}
}
func TestFullHouseTripsMatterMoreThanPair(t *testing.T) {
a := evaluate5([]Card{c(Two, Clubs), c(Two, Diamonds), c(Two, Hearts), c(King, Spades), c(King, Clubs)})
b := evaluate5([]Card{c(Queen, Clubs), c(Queen, Diamonds), c(Queen, Hearts), c(Ace, Spades), c(Ace, Clubs)})
if ComparePokerHands(b, a) <= 0 {
t.Errorf("фулл-хаус на тройке дам должен побеждать фулл-хаус на тройке двоек, несмотря на более слабую пару")
}
}
func TestTwoPairComparesHigherPairFirst(t *testing.T) {
a := evaluate5([]Card{c(King, Clubs), c(King, Diamonds), c(Two, Hearts), c(Two, Spades), c(Nine, Clubs)})
b := evaluate5([]Card{c(Queen, Clubs), c(Queen, Diamonds), c(Jack, Hearts), c(Jack, Spades), c(Ace, Clubs)})
if ComparePokerHands(a, b) <= 0 {
t.Errorf("две пары королей и двоек должны побеждать пары дам и валетов, несмотря на более слабый кикер")
}
}
func TestTwoPairKickerBreaksExactTie(t *testing.T) {
a := evaluate5([]Card{c(King, Clubs), c(King, Diamonds), c(Two, Hearts), c(Two, Spades), c(Ace, Clubs)})
b := evaluate5([]Card{c(King, Hearts), c(King, Spades), c(Two, Clubs), c(Two, Diamonds), c(Nine, Hearts)})
if ComparePokerHands(a, b) <= 0 {
t.Errorf("при равных парах решает кикер — туз должен побеждать девятку")
}
}
func TestPairComparesKickersInOrder(t *testing.T) {
a := evaluate5([]Card{c(Eight, Clubs), c(Eight, Diamonds), c(Ace, Hearts), c(Two, Spades), c(Three, Clubs)})
b := evaluate5([]Card{c(Eight, Hearts), c(Eight, Spades), c(King, Clubs), c(Queen, Diamonds), c(Jack, Hearts)})
if ComparePokerHands(a, b) <= 0 {
t.Errorf("при равных парах восьмёрок кикер-туз должен побеждать набор король-дама-валет")
}
}
func TestFlushComparesAllFiveCardsInOrder(t *testing.T) {
a := evaluate5([]Card{c(Two, Hearts), c(Five, Hearts), c(Seven, Hearts), c(Nine, Hearts), c(Ace, Hearts)})
b := evaluate5([]Card{c(Two, Spades), c(Five, Spades), c(Seven, Spades), c(Nine, Spades), c(King, Spades)})
if ComparePokerHands(a, b) <= 0 {
t.Errorf("флеш с тузом должен побеждать флеш с королём при прочих равных")
}
}
func TestIdenticalHandsSplitPot(t *testing.T) {
a := evaluate5([]Card{c(Two, Hearts), c(Five, Hearts), c(Seven, Hearts), c(Nine, Hearts), c(King, Hearts)})
b := evaluate5([]Card{c(Two, Spades), c(Five, Spades), c(Seven, Spades), c(Nine, Spades), c(King, Spades)})
if ComparePokerHands(a, b) != 0 {
t.Errorf("одинаковые по значению флеши разных мастей должны оцениваться как полностью равные (сплит банка), получено a=%+v b=%+v", a, b)
}
}
func TestEvaluateBest5ChoosesBestOfSeven(t *testing.T) {
hole := []Card{c(Ace, Spades), c(Ace, Hearts)}
board := []Card{c(Ace, Clubs), c(Ace, Diamonds), c(King, Spades), c(Two, Hearts), c(Three, Clubs)}
all := append(append([]Card{}, hole...), board...)
best := EvaluateBest5(all)
if best.Category != PokerFourOfAKind {
t.Fatalf("ожидалось каре тузов из семи карт, получено %v", best.Category)
}
if best.Tiebreak[0] != 14 || best.Tiebreak[1] != 13 {
t.Errorf("кикером каре тузов должен был стать король (13), получено %+v", best.Tiebreak)
}
}
func TestEvaluateBest5IgnoresWorseFiveCardSubset(t *testing.T) {
hole := []Card{c(Two, Hearts), c(Nine, Hearts)}
board := []Card{c(Five, Hearts), c(Six, Hearts), c(Seven, Clubs), c(Eight, Diamonds), c(King, Hearts)}
all := append(append([]Card{}, hole...), board...)
best := EvaluateBest5(all)
if best.Category != PokerFlush {
t.Fatalf("ожидался флеш как лучшая комбинация из семи карт, получено %v", best.Category)
}
}
func TestCombinations5Count(t *testing.T) {
cards := make([]Card, 7)
for i := range cards {
cards[i] = c(Rank(2+i), Clubs)
}
count := 0
combinations5(cards, func(combo []Card) { count++ })
if count != 21 {
t.Errorf("ожидалось ровно 21 сочетание из 7 по 5, получено %d", count)
}
}