Gameloop functions implemented to play the game
This commit is contained in:
parent
562e390db1
commit
83fe41b820
121
game/gameloop.go
121
game/gameloop.go
|
@ -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()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -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)
|
||||||
|
|
Loading…
Reference in New Issue