From 8ad948bc5156b0f903a063e9339c1eb05b3508cd Mon Sep 17 00:00:00 2001 From: Evgeniy Fedorov Date: Sat, 1 Jul 2023 13:33:59 +0300 Subject: [PATCH 1/2] Refactored global state. --- hw5/game.go | 45 +++++++++++++++++++++++++-------------------- hw5/gameLoop.go | 36 ++++++++++++++++++++---------------- hw5/main.go | 19 +++++++++---------- 3 files changed, 54 insertions(+), 46 deletions(-) diff --git a/hw5/game.go b/hw5/game.go index 771d525..b118365 100644 --- a/hw5/game.go +++ b/hw5/game.go @@ -4,13 +4,18 @@ import ( "errors" ) -type game struct{ grid *grid } +type game struct { + playerX *player + playerO *player + grid *grid +} -// Game constructor. -func NewGame() *game { - return &game{grid: NewGrid()} +func NewGame(playerX *player, playerO *player, grid *grid) *game { + return &game{playerX: playerX, playerO: playerO, grid: grid} } +// Game constructor. + // Game methods. func (g *game) Set(player *player, row int, col int) error { if err := g.validateCoords(row, col); err != nil { @@ -62,11 +67,11 @@ func (g *game) WhoWon() *player { for _, cell := range row { rowSum += cell.value } - if rowSum == playerX.winningSumCols { - return playerX + if rowSum == g.playerX.winningSumCols { + return g.playerX } - if rowSum == playerO.winningSumCols { - return playerO + if rowSum == g.playerO.winningSumCols { + return g.playerO } rowSum = 0 } @@ -79,11 +84,11 @@ func (g *game) WhoWon() *player { for r := 0; r < rows; r++ { colSum += g.grid[r][c].value } - if colSum == playerX.winningSumCols { - return playerX + if colSum == g.playerX.winningSumCols { + return g.playerX } - if colSum == playerO.winningSumCols { - return playerO + if colSum == g.playerO.winningSumCols { + return g.playerO } colSum = 0 } @@ -95,11 +100,11 @@ func (g *game) WhoWon() *player { for c := 0; c < cols; c++ { diag1Sum += g.grid[c][c].value } - if diag1Sum == playerX.winningSumCols { - return playerX + if diag1Sum == g.playerX.winningSumCols { + return g.playerX } - if diag1Sum == playerO.winningSumCols { - return playerO + if diag1Sum == g.playerO.winningSumCols { + return g.playerO } // Calculate win over second horizontal (right - left). @@ -111,11 +116,11 @@ func (g *game) WhoWon() *player { diag2Sum += g.grid[r][c].value c++ } - if diag2Sum == playerX.winningSumCols { - return playerX + if diag2Sum == g.playerX.winningSumCols { + return g.playerX } - if diag2Sum == playerO.winningSumCols { - return playerO + if diag2Sum == g.playerO.winningSumCols { + return g.playerO } return nil diff --git a/hw5/gameLoop.go b/hw5/gameLoop.go index ba7e7c6..3936011 100644 --- a/hw5/gameLoop.go +++ b/hw5/gameLoop.go @@ -11,13 +11,17 @@ import ( type gameLoop struct { game *game + score *map[string]int player1 *player player2 *player currentTurnPlayer *player } -func NewGameLoop(g *game) *gameLoop { - return &gameLoop{game: g} +func NewGameLoop(g *game, score *map[string]int) *gameLoop { + return &gameLoop{ + game: g, + score: score, + } } func (l *gameLoop) run() { @@ -38,11 +42,11 @@ func (l *gameLoop) makeMoves() { fmt.Println("The winner is player " + winner.name) // Record the score. - _, ok := score[winner.name] + _, ok := (*l.score)[winner.name] if !ok { - score[winner.name] = 1 + (*l.score)[winner.name] = 1 } else { - score[winner.name]++ + (*l.score)[winner.name]++ } break @@ -98,10 +102,10 @@ func (l *gameLoop) drawGrid() { fmt.Printf(" %s |", strconv.Itoa(rowIndex)) for _, cell := range row { switch cell.value { - case playerX.value: - fmt.Printf(" %s |", playerX.name) - case playerO.value: - fmt.Printf(" %s |", playerO.name) + case l.game.playerX.value: + fmt.Printf(" %s |", l.game.playerX.name) + case l.game.playerO.value: + fmt.Printf(" %s |", l.game.playerO.name) default: fmt.Printf(" %s |", " ") } @@ -115,16 +119,16 @@ func (l *gameLoop) choosePlayer1Side() { name: for { l.clearScreen() - fmt.Printf("Player1 (%s) or (%s) ? ", playerX.name, playerO.name) + fmt.Printf("Player1 (%s) or (%s) ? ", l.game.playerX.name, l.game.playerO.name) scanner.Scan() switch scanner.Text() { - case playerX.name: - l.player1 = playerX - l.player2 = playerO + case l.game.playerX.name: + l.player1 = l.game.playerX + l.player2 = l.game.playerO break name - case playerO.name: - l.player1 = playerO - l.player2 = playerX + case l.game.playerO.name: + l.player1 = l.game.playerO + l.player2 = l.game.playerX break name default: continue diff --git a/hw5/main.go b/hw5/main.go index 9c903c6..40e2ab6 100644 --- a/hw5/main.go +++ b/hw5/main.go @@ -6,21 +6,20 @@ import ( "os" ) -var playerX *player -var playerO *player -var score map[string]int - func main() { - // Game sore and players. - score = make(map[string]int) - playerX = &player{value: 10, name: "X", winningSumCols: Edge * 10} - playerO = &player{value: 100, name: "O", winningSumCols: Edge * 100} + // Game sore. + score := make(map[string]int) scanner := bufio.NewScanner(os.Stdin) + // Outer game loop. for { - game := NewGame() - loop := NewGameLoop(game) + game := NewGame( + &player{value: 10, name: "X", winningSumCols: Edge * 10}, + &player{value: 100, name: "O", winningSumCols: Edge * 100}, + NewGrid(), + ) + loop := NewGameLoop(game, &score) loop.run() // Print score and continue? From 8edb93144332cdc82e3c3981ea2fe9cb29f559a9 Mon Sep 17 00:00:00 2001 From: Evgeniy Fedorov Date: Sat, 1 Jul 2023 14:21:47 +0300 Subject: [PATCH 2/2] Refactored user input error handling --- hw5/gameLoop.go | 65 +++++++++++++++++++++++++++---------------------- 1 file changed, 36 insertions(+), 29 deletions(-) diff --git a/hw5/gameLoop.go b/hw5/gameLoop.go index 3936011..e26de59 100644 --- a/hw5/gameLoop.go +++ b/hw5/gameLoop.go @@ -30,61 +30,68 @@ func (l *gameLoop) run() { } func (l *gameLoop) makeMoves() { - var error string - scanner := bufio.NewScanner(os.Stdin) for l.game.hasEmptyCells() { + // Clear screen. l.clearScreen() + // Draw game grid. l.drawGrid() - // Check if we have a winner. - if winner := l.game.WhoWon(); winner != nil { + // Exit loop if we have a winner. + if winner := l.weHaveAWinner(); winner != nil { fmt.Println("The winner is player " + winner.name) - - // Record the score. - _, ok := (*l.score)[winner.name] - if !ok { - (*l.score)[winner.name] = 1 - } else { - (*l.score)[winner.name]++ - } - break } - // Print error, if any. - if error != "" { - fmt.Println("Error: " + error) + // Get user input. + l.userInput() + + // Pass turn to the other player. + if l.currentTurnPlayer == l.player1 { + l.currentTurnPlayer = l.player2 + } else if l.currentTurnPlayer == l.player2 { + l.currentTurnPlayer = l.player1 } + } - fmt.Print("Player " + l.currentTurnPlayer.name + " choose your cell (row,col): ") +} + +func (l *gameLoop) userInput() { + scanner := bufio.NewScanner(os.Stdin) + fmt.Print("Player " + l.currentTurnPlayer.name + " choose your cell (row,col): ") + for { scanner.Scan() // Validate coordinates input. row, col, isValid := l.validateCoordInput(scanner.Text()) if !isValid { - error = "Incorrect coordinates." + fmt.Println("Error: Incorrect coordinates.") continue - } else { - error = "" } + // Check that coordinates are valid (in bounds). err := l.game.Set(l.currentTurnPlayer, row, col) if err != nil { - error = err.Error() + fmt.Println("Error: " + err.Error()) continue - } else { - error = "" } + break + } - // Pass turn to the other player. - if l.currentTurnPlayer == l.player1 { - l.currentTurnPlayer = l.player2 - } else if l.currentTurnPlayer == l.player2 { - l.currentTurnPlayer = l.player1 +} +func (l *gameLoop) weHaveAWinner() *player { + + if winner := l.game.WhoWon(); winner != nil { + // Record the score. + _, ok := (*l.score)[winner.name] + if !ok { + (*l.score)[winner.name] = 1 + } else { + (*l.score)[winner.name]++ } + return winner } - + return nil } func (l *gameLoop) gridHeader() string {