add: replay logic to tictactoe

This commit is contained in:
Inanc Gumus
2019-05-13 18:22:38 +03:00
parent 90c5e5a866
commit 2169fa0f05

View File

@ -3,103 +3,68 @@ package main
import ( import (
"bufio" "bufio"
"fmt" "fmt"
"io/ioutil"
"os" "os"
"strconv" "strconv"
"strings" "strings"
rainbow "github.com/guineveresaenger/golang-rainbow"
) )
const ( const (
maxTurn = 9
// skin options :-) // skin options :-)
emptyMark = "" empty = " "
mark1 = "💀" player1 = " X "
mark2 = "🎈" player2 = " O "
header = "---+---+---"
footer = "---+---+---"
separator = "|"
banner = ` banner = `
~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~
TIC~TAC~TOE TIC~TAC~TOE
~~~~~~~~~~~~~~~` ~~~~~~~~~~~~~~~`
maxTurn = 9
prompt = "\n%s [1-9]: "
) )
func main() {
// ------------------------------------------------- // -------------------------------------------------
// INITIALIZE THE GAME // INITIALIZE THE GAME
// ------------------------------------------------- // -------------------------------------------------
fmt.Println(banner)
in := bufio.NewScanner(os.Stdin)
var ( var (
turn int turn int
player = mark1 won bool
board = [3][3]string{ board = [3][3]string{
{emptyMark, emptyMark, emptyMark}, {empty, empty, empty},
{emptyMark, emptyMark, emptyMark}, {empty, empty, empty},
{emptyMark, emptyMark, emptyMark}, {empty, empty, empty},
} }
player = player1
// for saving the replay.log
inputs []byte
) )
game: func main() {
rainbow.Rainbow(banner, strings.Count(banner, "\n"))
in := bufio.NewScanner(os.Stdin)
for { for {
// ------------------------------------------------- // -------------------------------------------------
// PRINT THE BOARD AND THE PROMPT // PRINT THE BOARD AND THE PROMPT
// ------------------------------------------------- // -------------------------------------------------
fmt.Println() fmt.Printf("\n %s\n", header)
fmt.Println("---+----+---")
for _, line := range board { for _, line := range board {
fmt.Printf("%s\n", strings.Join(line[:], " | ")) fmt.Printf(" %s\n", strings.Join(line[:], separator))
fmt.Println("---+----+---") fmt.Printf(" %s\n", footer)
} }
fmt.Printf(prompt, player)
// get the input
if !in.Scan() {
break
}
// -------------------------------------------------
// CHECK THE MOVE AND PLAY
// -------------------------------------------------
var (
pos int
row, col int
)
// Atoi already return 0 on error; no need to check
// it for the following switch to work
pos, _ = strconv.Atoi(in.Text())
switch {
case pos >= 7 && pos <= 9:
row = 2
case pos >= 4 && pos <= 6:
row = 1
case pos >= 1 && pos <= 3:
row = 0
default:
fmt.Println("\n>>>", "wrong position!")
continue
}
col = pos - row*3 - 1
if board[row][col] != emptyMark {
fmt.Println("\n>>>", "already played!")
continue
}
// put a mark on the board
board[row][col] = player
// ------------------------------------------------- // -------------------------------------------------
// IS THERE A WINNER? OR IS IT A TIE? // IS THERE A WINNER? OR IS IT A TIE?
// ------------------------------------------------- // -------------------------------------------------
var won bool for _, m := range [2]string{player1, player2} {
for _, m := range [2]string{mark1, mark2} {
b, mmm := board, strings.Repeat(m, 3) b, mmm := board, strings.Repeat(m, 3)
won = /* horizontals */ won = /* horizontals */
@ -117,25 +82,69 @@ game:
b[0][2]+b[1][1]+b[2][0] == mmm b[0][2]+b[1][1]+b[2][0] == mmm
if won { if won {
player = m
break break
} }
} }
if won { if won {
fmt.Printf("\nWINNER: %s\n", player) player = strings.TrimSpace(player)
break game fmt.Printf("\n>>> WINNER: %s\n", player)
} else if turn++; turn == maxTurn { break
fmt.Printf("\nTIE!\n") } else if turn++; turn == maxTurn+1 {
break game fmt.Printf("\n>>> TIE!\n")
break
} }
// ------------------------------------------------- // -------------------------------------------------
// CHANGE THE MARKER TO THE NEXT PLAYER // CHECK THE MOVE AND PLAY
// ------------------------------------------------- // -------------------------------------------------
if player == mark1 {
player = mark2 // get the input
fmt.Printf("\nPLAYER: %q [1-9]: ", player)
if !in.Scan() {
break
}
// Atoi already return 0 on error; no need to check
// it for the following switch to work
pos, _ := strconv.Atoi(in.Text())
// Save the input for replaying
inputs = append(inputs, byte(pos+48), '\n')
var row int
switch {
case pos >= 1 && pos <= 3:
row = 0
case pos >= 4 && pos <= 6:
row = 1
case pos >= 7 && pos <= 9:
row = 2
default:
fmt.Println("\n>>>", "wrong position!")
continue
}
col := pos - row*3 - 1
if board[row][col] != empty {
fmt.Println("\n>>>", "already played!")
continue
}
// put a mark on the board
board[row][col] = player
// switch to the next player
if player == player1 {
player = player2
} else { } else {
player = mark1 player = player1
} }
} }
if err := ioutil.WriteFile("replay.log", inputs, 0644); err != nil {
fmt.Fprintf(os.Stderr, "Cannot save replay: ", err)
}
} }