package main import ( "strconv" ) const ( GameStateInProgress int = 0 GameStateWaitingUser = 1 GameStateEnded = 2 GameStateDraw = 3 GameStateAIWon = 4 GameStateAILost = 5 ) const ( ImageCross string = "cross" ImageNought = "nought" ) const ( WinnerNone int = 0 WinnerAI = 1 WinnerUser = 2 ) var field2point = map[int][2]int{ 1: {0, 0}, 2: {0, 1}, 3: {0, 2}, 4: {1, 0}, 5: {1, 1}, 6: {1, 2}, 7: {2, 0}, 8: {2, 1}, 9: {2, 2}, } var FieldClass = map[int]string{ 1: "tt-item br bb", 2: "tt-item bb", 3: "tt-item bl bb", 4: "tt-item br", 5: "tt-item", 6: "tt-item bl", 7: "tt-item bt br", 8: "tt-item bt", 9: "tt-item bl bt", } var winner = [][3]int{ {1, 2, 3}, {4, 5, 6}, {7, 8, 9}, {1, 4, 7}, {2, 5, 8}, {3, 6, 9}, {1, 5, 9}, {7, 5, 3}, } type Field struct { disabled bool image string line bool } type Game struct { gameFlow string aiSecond bool aiFields []int userFields []int fields map[int]Field state int winnerFields [3]int winner int } func newGame(gameFlow string, aiSecond bool) *Game { fields := make(map[int]Field) for i := 1; i < 10; i++ { field := &Field{ disabled: false, } fields[i] = *field } game := &Game{ gameFlow: gameFlow, aiSecond: aiSecond, fields: fields, winner: WinnerNone, } for i, f := range str2array(game.gameFlow) { fieldNum, _ := strconv.ParseInt(f, 0, 16) if field, ok := game.fields[int(fieldNum)]; ok { field.disabled = true if i%2 == 0 { field.image = ImageCross } else { field.image = ImageNought } game.fields[int(fieldNum)] = field } if (i%2 == 0) == game.aiSecond { game.userFields = append(game.userFields, int(fieldNum)) } else { game.aiFields = append(game.aiFields, int(fieldNum)) } } game.calculateState() if game.isFinished() && game.winner != WinnerNone { for _, f := range game.winnerFields { if field, ok := game.fields[f]; ok { field.line = true game.fields[f] = field } } for i := 1; i < 10; i++ { if field, ok := game.fields[i]; ok { field.disabled = true game.fields[i] = field } } } return game } func (game *Game) isFinished() bool { return game.state > GameStateWaitingUser } func (game *Game) calculateState() { game.state = GameStateInProgress if "0" == game.gameFlow { game.state = GameStateWaitingUser return } for _, w := range winner { if len(game.aiFields) >= 3 && isSubArray(w[:], game.aiFields) { game.state = GameStateAIWon game.winnerFields = w game.winner = WinnerAI return } if len(game.userFields) >= 3 && isSubArray(w[:], game.userFields) { game.state = GameStateAILost game.winnerFields = w game.winner = WinnerUser return } } if len(game.gameFlow) == 9 { game.state = GameStateDraw } } func isSubArray(a, b []int) bool { mb := make(map[int]struct{}, len(b)) for _, x := range b { mb[x] = struct{}{} } var diff []int for _, x := range a { if _, found := mb[x]; !found { diff = append(diff, x) } } return len(diff) == 0 }