Untitled

mail@pastecode.io avatar
unknown
golang
2 years ago
2.9 kB
2
Indexable
Never
package main

import (
	"fmt"
	"strings"
)

type GameBoard = [][]string
type BoardRow = []string
type GameSymbol = string
type Patterns = [][]int

type PointPosition struct {
	row    uint
	column uint
}

var winPatterns Patterns = Patterns{
	{0, 1, 2},
	{3, 4, 5},
	{6, 7, 8},
	{0, 3, 6},
	{1, 4, 7},
	{2, 5, 8},
	{0, 4, 8},
	{2, 4, 6},
}

/*

0: 0 1 2
1: 0 1 2
2: 0 1 2

*/

var board GameBoard = GameBoard{
	BoardRow{"_", "_", "_"},
	BoardRow{"_", "_", "_"},
	BoardRow{"_", "_", "_"},
}

var currentSymbol string = "X"

func transformTo2dPosition(position int) (int, int) {
	row := position / 3
	fmt.Println("row: ", row)
	column := position - 3*row
	fmt.Println("column: ", column)
	return row, column
}

func playerWonGame() bool {
	for line := 0; line < len(winPatterns); line++ {
		matchedItems := 0
		for item := 0; item < len(winPatterns[line]); item++ {
			row, col := transformTo2dPosition(winPatterns[line][item])
			// fmt.Println("current pattern: ", winPatterns[line][item])
			// fmt.Println("current position: ", row, col)
			if board[row][col] == currentSymbol {
				matchedItems += 1
			}
			fmt.Println(matchedItems)
			if matchedItems == 3 {
				return true
			}
		}
	}
	return false
}

func drawBoard(board GameBoard) {
	fmt.Println("Current board: ")
	for i := 0; i < len(board); i++ {
		fmt.Printf("%s\n", strings.Join(board[i], " "))
	}
}

func updateBoardField(board GameBoard, position PointPosition, symbol string) {
	board[position.row][position.column] = symbol
}

func nextGameSymbol(previousSymbol string) string {
	if previousSymbol == "X" {
		return "O"
	} else {
		return "X"
	}
}

func readUserMove() PointPosition {
	var userChoice PointPosition
	_, err := fmt.Scan(&userChoice.row, &userChoice.column)
	if err != nil || userChoice.row >= 3 || userChoice.column >= 3 {
		clearConsole()
		fmt.Println("Wrong position.. try again..")
		return readUserMove()
	}
	return userChoice
}

func updateSymbol(newValue string) {
	currentSymbol = newValue
}

func clearConsole() {
	// simpliest way for all kinds of systems.
	fmt.Println("\033[2J")
}
func gameEngine(board GameBoard, currentSymbol string) {
	clearConsole()
	drawBoard(board)
	fmt.Println("Enter coordinates separated by space | x = row, y = column")
	userMove := readUserMove()
	updateBoardField(board, userMove, currentSymbol)
	if playerWonGame() {
		fmt.Println("Player won the game")
	}
	updateSymbol(nextGameSymbol(currentSymbol))
}

func isGameBoardEmpty() bool {
	spaces := 0
	for row := 0; row < len(board); row++ {
		for col := 0; col < len(board[row]); col++ {
			currentField := board[row][col]
			if currentField == "X" || currentField == "O" {
				spaces += 1
			}
		}
	}
	return spaces == 9
}

func main() {
	for !isGameBoardEmpty() {
		gameEngine(board, currentSymbol)
		result := playerWonGame()
		fmt.Println(result)
		if result {
			fmt.Printf("Player with symbol %s won the game!", currentSymbol)
			break
		}
	}
	fmt.Println("Draw!")
}