go_games_collection/klondike_bot_test.go
2026-07-04 13:51:04 +03:00

101 lines
2.5 KiB
Go

package main
import (
"math/rand"
"testing"
)
// klondikeAutoStep пытается совершить один разумный ход: сначала
// проверяет, можно ли отправить видимую карту (из отбоя или любой
// колонны) на фундамент; если нет — пробует случайный допустимый ход
// между колоннами или из отбоя в колонну; если и это невозможно —
// добирает из колоды. Возвращает false, если вообще ничего сделать
// нельзя (колода и отбой пусты, и нет легальных ходов) — сигнал
// закончить прогон.
func klondikeAutoStep(g *KlondikeGameState, rnd *rand.Rand) bool {
for col := 0; col < 7; col++ {
if g.MoveTableauToFoundation(col) == nil {
return true
}
}
if g.MoveWasteToFoundation() == nil {
return true
}
order := rnd.Perm(7)
for _, from := range order {
destOrder := rnd.Perm(7)
for _, to := range destOrder {
if from == to {
continue
}
if g.MoveTableauToTableau(from, to) == nil {
return true
}
}
}
for _, to := range rnd.Perm(7) {
if g.MoveWasteToTableau(to) == nil {
return true
}
}
if g.DrawStock() == nil {
return true
}
return false
}
func TestKlondikeAutoPlayManyGamesNoCorruption(t *testing.T) {
rnd := rand.New(rand.NewSource(1))
for game := 0; game < 200; game++ {
g := NewKlondikeGame()
const maxSteps = 3000
stalledStreak := 0
for step := 0; step < maxSteps; step++ {
progressed := klondikeAutoStep(g, rnd)
if !progressed {
stalledStreak++
if stalledStreak > 3 {
break
}
} else {
stalledStreak = 0
}
if g.Won {
break
}
seen := map[Card]bool{}
total := 0
checkAdd := func(c Card) {
if seen[c] {
t.Fatalf("игра %d, шаг %d: карта %v встретилась дважды", game, step, c)
}
seen[c] = true
total++
}
for col := 0; col < 7; col++ {
for _, kc := range g.Tableau[col] {
checkAdd(kc.Card)
}
}
for _, c := range g.Stock {
checkAdd(c)
}
for _, c := range g.Waste {
checkAdd(c)
}
for s, r := range g.Foundations {
for rank := 1; rank <= r; rank++ {
checkAdd(Card{Suit: Suit(s), Rank: Rank(rank)})
}
}
if total != 52 {
t.Fatalf("игра %d, шаг %d: ожидалось 52 карты в игре, получено %d", game, step, total)
}
}
}
}