github.com/e154/smart-home@v0.17.2-0.20240311175135-e530a6e5cd45/plugins/neural_network/game.go (about) 1 // This file is part of the Smart Home 2 // Program complex distribution https://github.com/e154/smart-home 3 // Copyright (C) 2023, Filippov Alex 4 // 5 // This library is free software: you can redistribute it and/or 6 // modify it under the terms of the GNU Lesser General Public 7 // License as published by the Free Software Foundation; either 8 // version 3 of the License, or (at your option) any later version. 9 // 10 // This library is distributed in the hope that it will be useful, 11 // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 // Library General Public License for more details. 14 // 15 // You should have received a copy of the GNU Lesser General Public 16 // License along with this library. If not, see 17 // <https://www.gnu.org/licenses/>. 18 19 package neural_network 20 21 import ( 22 "fmt" 23 ) 24 25 type GameState int 26 27 const ( 28 Empty GameState = 0 29 X GameState = 1 30 O GameState = -1 31 ) 32 33 type Game struct { 34 Board [3][3]GameState 35 Player GameState 36 } 37 38 func NewGame() *Game { 39 game := &Game{} 40 game.initBoard() 41 game.Player = X 42 return game 43 } 44 45 func (g *Game) initBoard() { 46 g.Board = [3][3]GameState{ 47 {0, 0, 0}, 48 {0, 0, 0}, 49 {0, 0, 0}, 50 } 51 } 52 53 func (g *Game) UpdateBoard(board [3][3]GameState) { 54 g.Board = board 55 } 56 57 func (g *Game) NumToCell(num int) (row, col int) { 58 row = num / 3 59 col = num - row*3 60 return 61 } 62 63 func (g *Game) MakeMove(row, col int) error { 64 if row < 0 || row >= 3 || col < 0 || col >= 3 || g.Board[row][col] != Empty { 65 return fmt.Errorf("Недопустимый ход") 66 } 67 68 g.Board[row][col] = g.Player 69 g.Player = g.Player.opponent() 70 return nil 71 } 72 73 func (g *Game) isGameOver() bool { 74 for _, row := range g.Board { 75 for _, cell := range row { 76 if cell == Empty { 77 return false 78 } 79 } 80 } 81 return true 82 } 83 84 func (g *Game) checkWinner() GameState { 85 // Проверка горизонтальных и вертикальных линий 86 for i := 0; i < 3; i++ { 87 if g.Board[i][0] != Empty && g.Board[i][0] == g.Board[i][1] && g.Board[i][0] == g.Board[i][2] { 88 return g.Board[i][0] 89 } 90 if g.Board[0][i] != Empty && g.Board[0][i] == g.Board[1][i] && g.Board[0][i] == g.Board[2][i] { 91 return g.Board[0][i] 92 } 93 } 94 95 // Проверка диагональных линий 96 if g.Board[0][0] != Empty && g.Board[0][0] == g.Board[1][1] && g.Board[0][0] == g.Board[2][2] { 97 return g.Board[0][0] 98 } 99 if g.Board[0][2] != Empty && g.Board[0][2] == g.Board[1][1] && g.Board[0][2] == g.Board[2][0] { 100 return g.Board[0][2] 101 } 102 103 return Empty 104 } 105 106 func (g *Game) PrintBoard() { 107 for _, row := range g.Board { 108 for _, cell := range row { 109 switch cell { 110 case X: 111 fmt.Print("X ") 112 case O: 113 fmt.Print("O ") 114 case Empty: 115 fmt.Print("- ") 116 } 117 } 118 fmt.Println() 119 } 120 } 121 122 func (g *Game) getRandomMove() (int, int) { 123 bestMove := findBestMove(g.Board, g.Player) 124 return bestMove.Row, bestMove.Col 125 } 126 127 func (g *Game) getBoardState() []float64 { 128 var boardState []float64 129 for _, row := range g.Board { 130 for _, cell := range row { 131 switch cell { 132 case X: 133 boardState = append(boardState, 1.0) 134 case O: 135 boardState = append(boardState, -1.0) 136 case Empty: 137 boardState = append(boardState, 0.0) 138 } 139 } 140 } 141 return boardState 142 } 143 144 func (g *Game) getMoveOutput(row, col int) []float64 { 145 return []float64{float64(row), float64(col)} 146 } 147 148 func (state GameState) opponent() GameState { 149 if state == X { 150 return O 151 } 152 return X 153 }