Gameloop functions implemented to play the game

This commit is contained in:
Falko Victor Habel 2024-04-23 21:12:46 +02:00
parent 562e390db1
commit 83fe41b820
2 changed files with 127 additions and 5 deletions

View File

@ -1 +1,122 @@
package game package game
import (
"tictactoe/gamecontrol"
"tictactoe/opponent"
"fyne.io/fyne/v2"
"fyne.io/fyne/v2/container"
"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
func MakeButtonGrid(rows, cols int) *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++ {
button := CreateButton(row, col)
gridContainer.Add(button)
}
}
return gridContainer
}
// create the button grid and adds key press handler for each grid-button
func CreateButton(row, col int) *widget.Button {
button := widget.NewButton(" ", nil)
button.OnTapped = func() {
if button.Text == " " {
button.SetText(PLAYER_X)
Gameloop(row, col)
}
}
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)
TextLabel.SetText("TicTacToe")
}
// 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
func Gameloop(row, col int) {
// starting with the human making a move
board[row][col] = PLAYER_X
// checking if the game has been won by the human player
if gamecontrol.PlayerHasWon(board, PLAYER_X) {
TextLabel.SetText("X Wins")
}
// checking if the game is a draw
if gamecontrol.BoardisFull(board) {
TextLabel.SetText("Draw")
}
// 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
if gamecontrol.PlayerHasWon(board, PLAYER_O) {
TextLabel.SetText("O Wins")
DisableAllButtons(gridContainer)
}
// checking if the game is a draw
if gamecontrol.BoardisFull(board) {
TextLabel.SetText("Draw")
}
}
// 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()
}
}
}

View File

@ -20,17 +20,18 @@ func CreateWindow() fyne.Window {
// Set the text of our TextLabel to TicTacToe // Set the text of our TextLabel to TicTacToe
TextLabel = widget.NewLabel("TicTacToe") TextLabel = widget.NewLabel("TicTacToe")
// create the 3x3 Button grid
// Create a new button with the text "Restart" and a handler function, if it gets pressed. matchField := MakeButtonGrid(3, 3)
// Create a new button and a handler function, if it gets pressed.
restartButton := widget.NewButton("Restart", func() { restartButton := widget.NewButton("Restart", func() {
// Add logic here to restart the game. ResetButtonTexts(matchField)
}) })
// vertical box layout containg the top Items, here the textlabel and the button. // vertical box layout containg the top Items, here the textlabel and the button.
topItems := container.NewVBox(TextLabel, restartButton) topItems := container.NewVBox(TextLabel, restartButton)
// Generate content for the window using a border layout with the topItems as the only child. // Generate content for the window using a border layout with the topItems and matchField as the children
content := container.New(layout.NewBorderLayout(topItems, nil, nil, nil), topItems) content := container.New(layout.NewBorderLayout(topItems, nil, nil, nil), topItems, matchField)
// Set the content and size of the window. // Set the content and size of the window.
myWindow.SetContent(content) myWindow.SetContent(content)