110 lines
4 KiB
Go
110 lines
4 KiB
Go
package main
|
|
|
|
import "testing"
|
|
|
|
func TestNewTicTacToeGameXAlwaysStartsFirst(t *testing.T) {
|
|
g := NewTicTacToeGame(TicTacToeO)
|
|
if g.CurrentTurn != TicTacToeX {
|
|
t.Errorf("крестики должны ходить первыми независимо от того, за кого играет человек")
|
|
}
|
|
}
|
|
|
|
func TestNewTicTacToeGameDefaultsToXOnInvalidMark(t *testing.T) {
|
|
g := NewTicTacToeGame(TicTacToeEmpty)
|
|
if g.HumanMark != TicTacToeX {
|
|
t.Errorf("недопустимый знак человека должен откатываться на крестики по умолчанию")
|
|
}
|
|
}
|
|
|
|
func TestPlaceMarkRejectsOccupiedCell(t *testing.T) {
|
|
g := NewTicTacToeGame(TicTacToeX)
|
|
if err := g.PlaceMark(0); err != nil {
|
|
t.Fatalf("неожиданная ошибка: %v", err)
|
|
}
|
|
if err := g.PlaceMark(0); err != ErrTicTacToeCellOccupied {
|
|
t.Errorf("ожидалась ошибка занятой клетки, получено: %v", err)
|
|
}
|
|
}
|
|
|
|
func TestPlaceMarkRejectsOutOfRange(t *testing.T) {
|
|
g := NewTicTacToeGame(TicTacToeX)
|
|
if err := g.PlaceMark(-1); err != ErrTicTacToeInvalidPosition {
|
|
t.Errorf("ожидалась ошибка недопустимой позиции для -1, получено: %v", err)
|
|
}
|
|
if err := g.PlaceMark(9); err != ErrTicTacToeInvalidPosition {
|
|
t.Errorf("ожидалась ошибка недопустимой позиции для 9, получено: %v", err)
|
|
}
|
|
}
|
|
|
|
func TestPlaceMarkRejectsAfterGameOver(t *testing.T) {
|
|
g := NewTicTacToeGame(TicTacToeX)
|
|
// X быстро выигрывает верхнюю строку: 0,1,2
|
|
moves := []int{0, 3, 1, 4, 2} // X: 0,1,2 O: 3,4
|
|
for _, pos := range moves {
|
|
if err := g.PlaceMark(pos); err != nil {
|
|
t.Fatalf("неожиданная ошибка на ходу %d: %v", pos, err)
|
|
}
|
|
}
|
|
if g.Phase != TicTacToePhaseOver || g.Result.Winner != TicTacToeX {
|
|
t.Fatalf("ожидалась победа крестиков, получено Phase=%v Result=%+v", g.Phase, g.Result)
|
|
}
|
|
if err := g.PlaceMark(5); err != ErrTicTacToeGameOver {
|
|
t.Errorf("ожидалась ошибка завершённой игры, получено: %v", err)
|
|
}
|
|
}
|
|
|
|
func TestAllEightWinLinesDetected(t *testing.T) {
|
|
lines := [8][3]int{
|
|
{0, 1, 2}, {3, 4, 5}, {6, 7, 8},
|
|
{0, 3, 6}, {1, 4, 7}, {2, 5, 8},
|
|
{0, 4, 8}, {2, 4, 6},
|
|
}
|
|
for _, line := range lines {
|
|
var board [9]TicTacToeMark
|
|
board[line[0]] = TicTacToeX
|
|
board[line[1]] = TicTacToeX
|
|
board[line[2]] = TicTacToeX
|
|
winner, gotLine, ok := ticTacToeCheckWin(board)
|
|
if !ok || winner != TicTacToeX {
|
|
t.Errorf("линия %v должна была засчитаться как победная", line)
|
|
}
|
|
if gotLine != line {
|
|
t.Errorf("ожидалась выигрышная линия %v, получено %v", line, gotLine)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestDrawWhenBoardFullWithoutWinner(t *testing.T) {
|
|
g := NewTicTacToeGame(TicTacToeX)
|
|
// классическая ничейная раскладка:
|
|
// X O X
|
|
// X O O
|
|
// O X X
|
|
moves := []int{0, 1, 2, 4, 3, 5, 7, 6, 8}
|
|
for i, pos := range moves {
|
|
if err := g.PlaceMark(pos); err != nil {
|
|
t.Fatalf("ход %d (клетка %d): неожиданная ошибка %v", i, pos, err)
|
|
}
|
|
if g.Phase == TicTacToePhaseOver && i != len(moves)-1 {
|
|
t.Fatalf("партия завершилась преждевременно на ходу %d (клетка %d), доска: %v", i, pos, g.Board)
|
|
}
|
|
}
|
|
if g.Phase != TicTacToePhaseOver || !g.Result.Draw {
|
|
t.Fatalf("ожидалась ничья, получено Phase=%v Result=%+v", g.Phase, g.Result)
|
|
}
|
|
}
|
|
|
|
func TestTurnAlternatesBetweenMoves(t *testing.T) {
|
|
g := NewTicTacToeGame(TicTacToeX)
|
|
if g.CurrentTurn != TicTacToeX {
|
|
t.Fatalf("ожидался первый ход крестиков")
|
|
}
|
|
g.PlaceMark(0)
|
|
if g.CurrentTurn != TicTacToeO {
|
|
t.Errorf("после хода крестиков должна ходить нолики")
|
|
}
|
|
g.PlaceMark(1)
|
|
if g.CurrentTurn != TicTacToeX {
|
|
t.Errorf("после хода ноликов должны снова ходить крестики")
|
|
}
|
|
}
|