package main import ( "math/rand" "testing" ) // TestMinesweeperRandomGamesNoCorruption прогоняет много случайных // партий на каждом классическом пресете размера, проверяя // отсутствие паник и что каждая партия корректно завершается // (победой или поражением) за разумное число ходов. func TestMinesweeperRandomGamesNoCorruption(t *testing.T) { rnd := rand.New(rand.NewSource(1)) presets := []struct{ w, h, mines int }{ {9, 9, 10}, {16, 16, 40}, {30, 16, 99}, } for _, p := range presets { for game := 0; game < 20; game++ { g := NewMinesweeperGame(p.w, p.h, p.mines) const maxMoves = 2000 moves := 0 for ; moves < maxMoves && g.Result == nil; moves++ { var candidates []MinesweeperPos for r := 0; r < g.Height; r++ { for c := 0; c < g.Width; c++ { cell := g.Board[r][c] if !cell.Revealed && !cell.Flagged { candidates = append(candidates, msp(r, c)) } } } if len(candidates) == 0 { break } pos := candidates[rnd.Intn(len(candidates))] if err := g.Reveal(pos); err != nil { t.Fatalf("пресет %dx%d/%d, игра %d, ход %d: неожиданная ошибка: %v", p.w, p.h, p.mines, game, moves, err) } } if g.Result == nil { t.Fatalf("пресет %dx%d/%d, игра %d: партия не завершилась за %d ходов", p.w, p.h, p.mines, game, maxMoves) } } } }