Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- package main
- import (
- "bufio"
- "errors"
- "fmt"
- "os"
- "strconv"
- "strings"
- "unicode"
- )
- const (
- boardSize = 3
- p1 int = 1
- p2 int = 2
- cell string = "|%s"
- boardSquare = boardSize * boardSize
- )
- var (
- turn int = p1
- board [boardSquare]int = [boardSquare]int{}
- icon map[int]string = map[int]string{
- 0: " ",
- 1: "X",
- 2: "O",
- }
- roof string = ""
- floor string = strings.Repeat("-", (boardSize*2)+1)
- minChar string = "a"
- maxChar string = string('a' + boardSize)
- )
- func readLine() (string, error) {
- scanner := bufio.NewScanner(os.Stdin)
- text := ""
- if scanner.Scan() {
- text = scanner.Text()
- }
- if err := scanner.Err(); err != nil {
- return "", err
- }
- text = strings.ReplaceAll(text, "\r", "")
- text = strings.ReplaceAll(text, "\n", "")
- return text, nil
- }
- func nextPlayer() {
- if turn == p1 {
- turn = p2
- return
- }
- turn = p1
- }
- func gameState() {
- fmt.Printf(" %v\n", roof)
- for i := 0; i < boardSquare; i++ {
- if i%boardSize == 0 {
- row := i / boardSize
- rowLetter := string('a' + row)
- fmt.Print(rowLetter)
- }
- fmt.Printf(cell, icon[board[i]])
- if (i+1)%boardSize == 0 {
- fmt.Printf("|\n")
- }
- }
- fmt.Printf(" %v\n", floor)
- }
- func resetBoard() {
- for i := 0; i < boardSquare; i++ {
- board[i] = 0
- }
- turn = p1
- }
- func flush() {
- fmt.Print("\033[H\033[2J")
- }
- func promptRepeat() bool {
- fmt.Println("Would you like to play again? Y/N")
- in, err := readLine()
- if err != nil {
- return false
- }
- return strings.ToLower(in) == "y"
- }
- func turnStringInt(turnString string) (int, error) {
- if len(turnString) != 2 {
- return 0, errors.New("turn string must be 2 chars")
- }
- r := turnString[0]
- if !unicode.IsLetter(rune(r)) {
- return 0, errors.New("first char must be a letter")
- }
- row := rune(r) - 'a'
- if row > boardSize || row < 0 {
- return 0, fmt.Errorf("row must be between %s and %s", minChar, maxChar)
- }
- c := turnString[1]
- if !unicode.IsDigit(rune(c)) {
- return 0, errors.New("second char must be a digit")
- }
- col, err := strconv.Atoi(string(c))
- if err != nil {
- return 0, errors.New("second char must be a digit")
- }
- if col > boardSize+1 || col < 0 {
- return 0, fmt.Errorf("column must be between 1 and %v", boardSize+1)
- }
- return (int(row) * boardSize) + (col - 1), nil
- }
- func takeTurn() error {
- fmt.Printf("Player %v enter your turn:\n", turn)
- turnString, err := readLine()
- if err != nil {
- return err
- }
- i, err := turnStringInt(turnString)
- if err != nil {
- return err
- }
- if board[i] != 0 {
- return fmt.Errorf("space at %v is occupied", turnString)
- }
- board[i] = turn
- return nil
- }
- func initRoofString() {
- for i := 1; i <= boardSize; i++ {
- roof = fmt.Sprintf("%v %v", roof, i)
- }
- roof = fmt.Sprintf(
- "%v\n %v",
- roof,
- fmt.Sprintf(
- "%v",
- strings.Repeat("_", (boardSize*2)+1),
- ),
- )
- }
- func checkWinner() bool {
- for i := 0; i < boardSize; i++ {
- rowMatch := true
- colMatch := true
- rowPivot := board[i*boardSize]
- colPivot := board[i]
- if rowPivot == 0 {
- rowMatch = false
- }
- if colPivot == 0 {
- colMatch = false
- }
- for j := 1; j < boardSize; j++ {
- if rowMatch && board[i*boardSize+j] != rowPivot {
- rowMatch = false
- }
- if colMatch && board[j*boardSize+i] != colPivot {
- colMatch = false
- }
- if !rowMatch && !colMatch {
- break
- }
- }
- if rowMatch || colMatch {
- return true
- }
- }
- lDiagPivot := board[0]
- if lDiagPivot != 0 {
- lDiagMatch := true
- for i := 1; i < boardSize; i++ {
- if board[i*boardSize+i] != lDiagPivot {
- lDiagMatch = false
- break
- }
- }
- if lDiagMatch {
- return true
- }
- }
- rDiagPivot := board[boardSize-1]
- if rDiagPivot != 0 {
- rDiagMatch := true
- for i := 1; i < boardSize; i++ {
- if board[i*boardSize+(boardSize-1-i)] != rDiagPivot {
- rDiagMatch = false
- break
- }
- }
- if rDiagMatch {
- return true
- }
- }
- return false
- }
- func main() {
- initRoofString()
- play := true
- for play {
- fmt.Println("Starting a new game:")
- resetBoard()
- for {
- gameState()
- for err := takeTurn(); err != nil; err = takeTurn() {
- fmt.Printf("Error: %v\n", err)
- }
- flush()
- gameState()
- if checkWinner() {
- fmt.Printf("Player %v has won!\n", turn)
- break
- }
- nextPlayer()
- flush()
- }
- play = promptRepeat()
- flush()
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment