tictactoe-in-go/game/gameloop.go

131 lines
3.3 KiB
Go
Raw Permalink Normal View History

package game
import (
2024-04-24 19:28:48 +00:00
"tictactoe/gameControl"
"tictactoe/opponent"
"fyne.io/fyne/v2"
"fyne.io/fyne/v2/container"
2024-04-29 08:19:59 +00:00
"fyne.io/fyne/v2/dialog"
"fyne.io/fyne/v2/layout"
"fyne.io/fyne/v2/widget"
)
var board = [3][3]string{
{" ", " ", " "},
{" ", " ", " "},
{" ", " ", " "},
}
const (
PLAYER_X = "X"
PLAYER_O = "O"
)
var gridContainer *fyne.Container
// creates the button grid for the tictactoe game
2024-04-29 08:19:59 +00:00
func MakeButtonGrid(rows, cols int, Window fyne.Window) *fyne.Container {
// generates layout and grid container
gridLayout := layout.NewGridLayout(cols)
gridContainer = container.New(gridLayout)
// create the 3x3 Button grid
for row := 0; row < rows; row++ {
for col := 0; col < cols; col++ {
2024-04-29 08:19:59 +00:00
button := CreateButton(row, col, Window)
gridContainer.Add(button)
}
}
return gridContainer
}
// create the button grid and adds key press handler for each grid-button
2024-04-29 08:19:59 +00:00
func CreateButton(row, col int, Window fyne.Window) *widget.Button {
button := widget.NewButton(" ", nil)
button.OnTapped = func() {
if button.Text == " " {
button.SetText(PLAYER_X)
2024-04-29 08:19:59 +00:00
Gameloop(row, col, Window)
}
}
return button
}
// reset the game by clearing the buttons and the board array
func ResetButtonTexts(container *fyne.Container) {
for _, child := range container.Objects {
if btn, ok := child.(*widget.Button); ok {
btn.SetText(" ")
}
}
board = [3][3]string{
{" ", " ", " "},
{" ", " ", " "},
{" ", " ", " "},
}
EnableAllButtons(gridContainer)
}
// apply AI opponent text to the button
func ChangeButtonText(row, col int) {
gridContainer.Objects[col+row*3].(*widget.Button).SetText("O")
}
// gameloop function for the game process:
// human makes a move, AI counters
2024-04-29 08:19:59 +00:00
func Gameloop(row, col int, Window fyne.Window) {
const gameOverText string = "Game Over"
// starting with the human making a move
board[row][col] = PLAYER_X
// checking if the game has been won by the human player
2024-04-24 19:28:48 +00:00
if gameControl.PlayerHasWon(board, PLAYER_X) {
2024-04-29 08:19:59 +00:00
dialog.ShowInformation(gameOverText, "X has won!", Window)
DisableAllButtons(gridContainer)
return
}
// checking if the game is a draw
2024-04-24 19:28:48 +00:00
if gameControl.BoardisFull(board) {
2024-04-29 08:19:59 +00:00
dialog.ShowInformation(gameOverText, "It's a draw!", Window)
DisableAllButtons(gridContainer)
return
}
// AI opponent makes a move
bestMove := opponent.Minimax(board, 0, true, PLAYER_O)
// add the move to the board
board[bestMove.Row][bestMove.Col] = PLAYER_O
ChangeButtonText(bestMove.Row, bestMove.Col)
// check if AI opponent has won the game
2024-04-24 19:28:48 +00:00
if gameControl.PlayerHasWon(board, PLAYER_O) {
2024-04-29 08:19:59 +00:00
dialog.ShowInformation(gameOverText, "O has won!", Window)
DisableAllButtons(gridContainer)
return
}
// checking if the game is a draw
2024-04-24 19:28:48 +00:00
if gameControl.BoardisFull(board) {
2024-04-29 08:19:59 +00:00
dialog.ShowInformation(gameOverText, "It's a draw!", Window)
DisableAllButtons(gridContainer)
return
}
}
// function to disable all buttons inside the grid
func DisableAllButtons(container *fyne.Container) {
for _, child := range container.Objects {
if btn, ok := child.(*widget.Button); ok {
btn.Disable()
}
}
}
// function to enable all buttons inside the grid
func EnableAllButtons(container *fyne.Container) {
for _, child := range container.Objects {
if btn, ok := child.(*widget.Button); ok {
btn.Enable()
}
}
}