add: new tictactoe game

add: testing to tictactoe

rename: tictactoe

add: tictactoe steps

refactor: tictactoe const names

refactor: tictactoe loop

add: tictactoe bad switch example (fallthrough)

refactor: tictactoe loop skin

remove: tictactoe changable skin

refactor: tictactoe all

remove: tictactoe unnecessary base dir

add: tictactoe slices

add: tictactoe slices

remove: tictactoe fallthrough

rename: tictactoe slices 10 -> 09

update: loops skin tictactoe

add: tictactoe randomization

add: tictactoe infinite loop and labeled break

refactor: tictactoe rand and infinite loop

add: tictactoe buggy winning algo

add: tictactoe more tests

rename: tictactoe wrongPlay to wrongMove

add: tictactoe even more tests

fix: tictactoe

rename: tictactoe waitForInput to wait

add: tictactoe os.args gameSpeed

remove: tictactoe unnecessary files

rename: tictactoe game messages

refactor: tictactoe main loop

add: types and arrays
This commit is contained in:
Inanc Gumus
2019-07-27 18:16:17 +03:00
parent e191567e1f
commit eb8f9987a8
97 changed files with 3457 additions and 3 deletions

View File

@ -0,0 +1,51 @@
// For more tutorials: https://blog.learngoprogramming.com
//
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
package main
import (
"fmt"
"math"
"os"
"runtime"
"time"
)
func main() {
// int, float64, bool, string
var (
cpus int
path, dir string
max float64
)
cpus = runtime.NumCPU()
path = os.Getenv("PATH")
max = math.Max(1.5, 2.5)
dir, _ = os.Getwd()
now := time.Now()
// cpus := runtime.NumCPU()
// path := os.Getenv("PATH")
// max := math.Max(1.5, 2.5)
// dir, _ := os.Getwd()
// dir = `"` + dir + `"`
// dir = strconv.Quote(dir)
// cpus++
// cpus *= 2.5
// max++
// max /= 2.5
// paths = strings.Split(path, ":")
// path = paths[0]
fmt.Printf("# of CPUS : %d\n", cpus)
fmt.Printf("Path : %s\n", path)
fmt.Printf("max(1.5, 2.5) : %g\n", max)
fmt.Printf("Current Directory: %s\n", dir)
fmt.Printf("Current Time : %s\n", now)
}

View File

@ -36,12 +36,12 @@ main:
switch {
// prime
case n == 2 || n == 3:
case n == 2, n == 3:
fmt.Print(n, " ")
continue
// not a prime
case n <= 1 || n%2 == 0 || n%3 == 0:
case n <= 1, n%2 == 0, n%3 == 0:
continue
}

View File

@ -1,3 +1,10 @@
// For more tutorials: https://blog.learngoprogramming.com
//
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
package main
import (
@ -7,6 +14,26 @@ import (
)
func main() {
// 1.
// var a int
// var b int
// 2.
// var (
// a int
// b int
// )
// 3.
// var a, b int
// 1.
// fmt.Println(a, "+", b, "=", a+b)
// 2.
// fmt.Printf("%v + %v = %v\n", a, b, a+b)
// ----
// lesson: multi-return funcs, %v, and _
a, _ := strconv.Atoi(os.Args[1])

View File

@ -7,7 +7,7 @@ import (
)
func main() {
// lesson: floats encompass integers too
// lesson: len(), floats encompass integers too
if len(os.Args) != 3 {
fmt.Println("Usage: calc <number1> <number2>")

View File

@ -26,5 +26,12 @@ func main() {
return
}
// err1 := ...
// err2 := ...
// if err1 != nil || err2 != nil {
// fmt.Println("Please provide a valid number")
// return
// }
fmt.Printf("%v + %v = %v\n", a, b, a+b)
}

View File

@ -26,7 +26,9 @@ func main() {
return
}
// multiple declare
var (
// declare & assign
op = os.Args[2]
res float64
)

View File

@ -0,0 +1,70 @@
// For more tutorials: https://blog.learngoprogramming.com
//
// Copyright © 2018 Inanc Gumus
// Learn Go Programming Course
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
//
package main
import (
"fmt"
"net"
"os"
"strings"
)
const (
missingHost = "Please provide at least one domain. --help for more information."
help = `
Host to IP Lookup:
------------------
It finds the ip addresses of the given hosts. You can provide hosts by separating them with spaces.
Example:
host google.com
host google.com uber.com`
)
func main() {
// url := "google.com"
var message string
args := os.Args
switch l := len(args); {
// case len(args) == 1:
case l == 1:
message = missingHost
case l == 2 && args[1] == "--help":
message = strings.TrimSpace(help)
}
if message != "" {
fmt.Println(message)
return
}
// for i := 0; i < len(args); i++ {}
// for i, url := range args {
for _, url := range args[1:] {
// if i == 0 {
// continue
// }
ips, err := net.LookupIP(url)
if err != nil {
fmt.Printf("%-20s => %s\n", url, err)
// break
continue
}
for _, ip := range ips {
if ip = ip.To4(); ip != nil {
fmt.Printf("%-20s => %s\n", url, ip)
}
}
}
}

View File

@ -0,0 +1,42 @@
package main
import (
"fmt"
"io/ioutil"
"log"
"net/http"
"os"
)
const base = "https://swapi.co/api/"
func main() {
if len(os.Args) != 2 {
fmt.Println("Please provide a Ship ID")
return
}
url := base + "starships/" + os.Args[1]
response, err := http.Get(url)
if err != nil {
fmt.Println(err)
return
}
if code := response.StatusCode; code != http.StatusOK {
fmt.Println("Error:", http.StatusText(code))
return
}
// var r *http.Response
// _ = r
bodyBytes, err := ioutil.ReadAll(response.Body)
if err != nil {
log.Fatal(err)
}
body := string(bodyBytes)
fmt.Println(body)
}

View File

@ -0,0 +1,149 @@
package main
import (
"fmt"
"math/rand"
"strings"
"time"
rainbow "github.com/guineveresaenger/golang-rainbow"
)
const (
maxTurn = 9
// skin options :-)
empty = " "
player1 = " X "
player2 = " O "
header = "---+---+---"
footer = "---+---+---"
separator = "|"
banner = `
~~~~~~~~~~~~~~~
TIC~TAC~TOE
~~~~~~~~~~~~~~~`
)
// -------------------------------------------------
// INITIALIZE THE GAME
// -------------------------------------------------
var (
turn int
won bool
board = [][]string{
{empty, empty, empty},
{empty, empty, empty},
{empty, empty, empty},
}
player = player1
)
func main() {
rand.Seed(time.Now().UnixNano())
rainbow.Rainbow(banner, strings.Count(banner, "\n"))
for {
// -------------------------------------------------
// PRINT THE BOARD AND THE PROMPT
// -------------------------------------------------
fmt.Printf("\n %s\n", header)
for _, line := range board {
fmt.Printf(" %s\n", strings.Join(line, separator))
fmt.Printf(" %s\n", footer)
}
// -------------------------------------------------
// IS THERE A WINNER? OR IS IT A TIE?
// -------------------------------------------------
for i := 1; i <= 2; i++ {
m := player2
if i == 1 {
m = player1
}
b, mmm := board, strings.Repeat(m, 3)
/* horizontals */
hor := strings.Join(b[0], "") == mmm ||
strings.Join(b[1], "") == mmm ||
strings.Join(b[2], "") == mmm
/* verticals */
ver := b[0][0]+b[1][0]+b[2][0] == mmm ||
b[0][1]+b[1][1]+b[2][1] == mmm ||
b[0][2]+b[1][2]+b[2][2] == mmm
/* diagonals */
diag := b[0][0]+b[1][1]+b[2][2] == mmm ||
b[0][2]+b[1][1]+b[2][0] == mmm
won = hor || ver || diag
if won {
player = m
break
}
}
if won {
player = strings.TrimSpace(player)
fmt.Printf("\n>>> WINNER: %s\n", player)
break
} else if turn == maxTurn {
fmt.Printf("\n>>> TIE!\n")
break
}
// -------------------------------------------------
// PLAY
// -------------------------------------------------
pos := rand.Intn(9) + 1
fmt.Printf("\nPlayer %s plays to %d\n", player, pos)
// -------------------------------------------------
// IS IT A VALID MOVE?
// -------------------------------------------------
var row int
switch {
case pos <= 3:
row = 0
case pos <= 6:
row = 1
case pos <= 9:
row = 2
default:
fmt.Println(">>>", "wrong position!")
continue
}
col := pos - row*3 - 1
if board[row][col] != empty {
fmt.Println(">>>", "already played!")
continue
}
// -------------------------------------------------
// MARK THE MOVE AND INCREMENT THE TURN
// -------------------------------------------------
// put a mark on the board
board[row][col] = player
// switch to the next player
if player == player1 {
player = player2
} else {
player = player1
}
turn++
// time.Sleep(time.Millisecond * 100)
}
}

View File

@ -0,0 +1,50 @@
package main
import "fmt"
/*
~ TICTACTOE GAME IN GO ~
+ This example uses the very basics of the Go language.
+ The goal is learning all the basics.
*/
func main() {
// VERSION #1: String Concat +
/*
fmt.Print("" +
" TIC~TAC~TOE\n" +
"\n" +
"/---+---+---\\\n" +
"| X | O | X |\n" +
"+---+---+---+\n" +
"| X | X | |\n" +
"+---+---+---+\n" +
"| O | O | O |\n" +
"\\---+---+---/\n")
*/
// VERSION #2: String Concat +
/*
fmt.Println("" +
" TIC~TAC~TOE\n" +
"\n" +
"/---+---+---\\\n" +
"| X | O | X |\n" +
"+---+---+---+\n" +
"| X | X | |\n" +
"+---+---+---+\n" +
"| O | O | O |\n" +
"\\---+---+---/")
*/
// VERSION #3: Raw Literals (multi line strings)
fmt.Println(`
TIC~TAC~TOE
/---+---+---\
| X | O | X |
+---+---+---+
| X | X | |
+---+---+---+
| O | O | O |
\---+---+---/`)
}

View File

@ -0,0 +1,96 @@
package main
import "fmt"
/*
~ TICTACTOE GAME IN GO ~
+ This example uses the very basics of the Go language.
+ The goal is learning all the basics.
*/
func main() {
/*
VERSION #1: Declare variables
Every type has a zero-value:
numeric types => 0
bool => false
string => ""
*/
// var banner string
// var board string
// var turn int
// var maxTurns int
// var won bool
/*
VERSION #2: Declare variables parallel (same as above)
turn and lastPos are int
won and wrongMove are bool
*/
// var banner, board string
// var turn, maxTurns int
// var won bool
/*
VERSION #3: Declare variables in a group and parallel (same as above)
*/
// var (
// banner, board string
// turn, maxTurns int
// won bool
// )
/*
VERSION #4: Declare variables in a group (same as above)
*/
var (
banner string // tictactoe banner
board string // tictactoe board
turn int // total valid turns played
maxTurns int // maximum number of turns
won bool // is there any winner?
progress float64 // remaining progress
)
/*
#5: Assignment
*/
banner = " TIC~TAC~TOE"
board = `
/---+---+---\
| | X | |
+---+---+---+
| | O | |
+---+---+---+
| | | |
\---+---+---/`
// maxTurns = 9
// turn = 2
// multiple assignment
maxTurns, turn = 9, 2
// cannot assign int to float
// progress = 1 - (turn / maxTurns) * 100
// convert ints to float so that the result will be float
// literals are typeless: they automatically get converted to the surrounding operands
progress = (1 - (float64(turn) / float64(maxTurns))) * 100
fmt.Println(banner)
fmt.Println(board)
fmt.Println()
fmt.Printf("Current Turn : %d\n", turn)
fmt.Printf("Is there a winner : %t\n", won)
fmt.Printf("Turns left : %.1f%%\n", progress)
// This is also valid: the expression is evaluated on the fly.
// fmt.Printf("Turns left : %.1f%%\n",
// (1 - (float64(turn) / float64(maxTurns))) * 100)
}

View File

@ -0,0 +1,33 @@
package main
import "fmt"
/*
~ TICTACTOE GAME IN GO ~
+ This example uses the very basics of the Go language.
+ The goal is learning all the basics.
*/
func main() {
var won bool // is there any winner?
banner := " TIC~TAC~TOE"
board := `
/---+---+---\
| | | |
+---+---+---+
| | | |
+---+---+---+
| | | |
\---+---+---/`
// short declaration (type-inference)
maxTurns, turn := 9, 0
progress := (1 - (float64(turn) / float64(maxTurns))) * 100
fmt.Println(banner)
fmt.Println(board)
fmt.Println()
fmt.Printf("Current Turn : %d\n", turn)
fmt.Printf("Is there a winner : %t\n", won)
fmt.Printf("Turns left : %.1f%%\n", progress)
}

View File

@ -0,0 +1,71 @@
package main
import "fmt"
/*
~ TICTACTOE GAME IN GO ~
+ This example uses the very basics of the Go language.
+ The goal is learning all the basics.
*/
func main() {
var (
won bool
turn int
)
// VERSION 1
// const banner = " TIC~TAC~TOE"
// const board = `
// /---+---+---\
// | X | O | X |
// +---+---+---+
// | X | X | |
// +---+---+---+
// | O | O | O |
// \---+---+---/`
//
// const maxTurns = 9
// VERSION 2
// Benefit of constants:
// + Resolved to literals at compile-time
// + Fast at runtime
// + Provides overwriting unlike variables
// + Typeless: Can change type
const (
banner = `
TIC~TAC~TOE
/---+---+---\
| X | O | X |
+---+---+---+
| X | X | |
+---+---+---+
| O | O | O |
\---+---+---/`
maxTurns = 9
)
// Constants have default types
// 1 => int
// 1.5 => float64
// true => bool
// "hi" => string
// 'a' => rune
// You cannot assign to constants
// banner = "TIC TAC TOE"
// maxTurns = 10
// no need: float64(maxTurns) — constants are typeless (like basic literals)
// if maxTurns was `const maxTurns int`; then it'd be needed.
progress := (1 - (float64(turn) / maxTurns)) * 100
fmt.Println(banner)
// fmt.Println(board)
fmt.Println()
fmt.Printf("Current Turn : %d\n", turn)
fmt.Printf("Is there a winner : %t\n", won)
fmt.Printf("Turns left : %.1f%%\n", progress)
}

View File

@ -0,0 +1,52 @@
package main
import "fmt"
/*
~ TICTACTOE GAME IN GO ~
+ This example uses the very basics of the Go language.
+ The goal is learning all the basics.
*/
const (
banner = `
TIC~TAC~TOE
/---+---+---\
| X | O | X |
+---+---+---+
| X | X | |
+---+---+---+
| O | O | O |
\---+---+---/`
maxTurns = 9
)
var (
won bool
turn int
)
func main() {
// you need to call the other functions but the main
printBoard()
printStatus()
}
// printBoard cannot use the banner
func printBoard() {
// it can only use the package-level names (identifiers)
fmt.Println(banner)
}
// printStatus prints the current status of the game
// it cannot access to the names (vars, consts, etc) inside any other func
func printStatus() {
fmt.Println()
progress := (1 - (float64(turn) / maxTurns)) * 100
fmt.Printf("Current Turn : %d\n", turn)
fmt.Printf("Is there a winner : %t\n", won)
fmt.Printf("Turns left : %.1f%%\n", progress)
}

View File

@ -0,0 +1,23 @@
package main
// Examples are normally used for showing how to use your package.
// But you can also use them as output testing.
func ExamplePrintBoard() {
// let the printBoard function print an output
printBoard()
// the output should exactly match the following (after Output:)
// Output:
// TIC~TAC~TOE
//
// /---+---+---\
// | | | |
// +---+---+---+
// | | | |
// +---+---+---+
// | | | |
// \---+---+---/
}

View File

@ -0,0 +1,52 @@
package main
import "fmt"
/*
~ TICTACTOE GAME IN GO ~
+ This example uses the very basics of the Go language.
+ The goal is learning all the basics.
*/
const (
banner = `
TIC~TAC~TOE
/---+---+---\
| | | |
+---+---+---+
| | | |
+---+---+---+
| | | |
\---+---+---/`
maxTurns = 9
)
var (
won bool
turn int
)
func main() {
// you need to call the other functions but the main
printBoard()
printStatus()
}
// printBoard cannot use the banner
func printBoard() {
// it can only use the package-level names (identifiers)
fmt.Println(banner)
}
// printStatus prints the current status of the game
// it cannot access to the names (vars, consts, etc) inside any other func
func printStatus() {
fmt.Println()
progress := (1 - (float64(turn) / maxTurns)) * 100
fmt.Printf("Current Turn : %d\n", turn)
fmt.Printf("Is there a winner : %t\n", won)
fmt.Printf("Turns left : %.1f%%\n", progress)
}

View File

@ -0,0 +1,23 @@
package main
// Examples are normally used for showing how to use your package.
// But you can also use them as output testing.
func ExamplePrintBoard() {
// let the printBoard function print an output
printBoard()
// the output should exactly match the following (after Output:)
// Output:
// TIC~TAC~TOE
//
// /---+---+---\
// | | | |
// +---+---+---+
// | | | |
// +---+---+---+
// | | | |
// \---+---+---/
}

View File

@ -0,0 +1,87 @@
package main
import "fmt"
/*
~ TICTACTOE GAME IN GO ~
+ This example uses the very basics of the Go language.
+ The goal is learning all the basics.
*/
const (
banner = `
TIC~TAC~TOE
/---+---+---\
| | | |
+---+---+---+
| | | |
+---+---+---+
| | | |
\---+---+---/`
maxTurns = 9
)
var (
won bool
turn int
)
func main() {
// you need to call the other functions but the main
printBoard()
printStatus()
printEnding()
}
// printBoard cannot use the banner
func printBoard() {
// it can only use the package-level names (identifiers)
fmt.Println(banner)
}
// printStatus prints the current status of the game
// it cannot access to the names (vars, consts, etc) inside any other func
func printStatus() {
fmt.Println()
progress := (1 - (float64(turn) / maxTurns)) * 100
fmt.Printf("Current Turn : %d\n", turn)
fmt.Printf("Is there a winner : %t\n", won)
fmt.Printf("Turns left : %.1f%%\n", progress)
}
func printEnding() {
fmt.Println()
// creates a new variable that belongs to printEnding()
// current player
player := "X"
// accesses to the package-level vars: won, turn
// won = true
// turn = maxTurns
// if won {
// fmt.Printf(">>> WINNER: %s\n", player)
// } else if turn == maxTurns { // != >= <= < >
// fmt.Println(">>> TIE!")
// } else {
// fmt.Println(">> NEXT TURN!")
// }
switch {
case won:
// player := "X"
fmt.Printf(">>> WINNER: %s\n", player)
case turn == maxTurns:
fmt.Println(">>> TIE!")
default:
fmt.Println(">> NEXT TURN!", player)
}
// invalid if the player is within the scope of the switch:
// fmt.Println(">> Current Player: ", player)
}

View File

@ -0,0 +1,54 @@
package main
import "fmt"
// printBoard prints the board
func printBoard() {
// ~~~~~~~~~~~~~~~
// TIC~TAC~TOE
// ~~~~~~~~~~~~~~~
//
// /---+---+---\
// | X | O | X |
// +---+---+---+
// | O | X | O |
// +---+---+---+
// | X | O | X |
// \---+---+---/
const cellsPerLine = 3
// Prevents the Println '\n' warning
fmt.Printf("%s\n\n", banner)
fmt.Printf("%s\n", sepHeader)
for i := 0; i < maxTurns; i++ {
lineStarts := i%cellsPerLine == 0
lineEnds := (i+1)%cellsPerLine == 0
lastLine := (i + 1) == maxTurns
if lineStarts {
fmt.Print(sepCell)
}
switchPlayer()
fmt.Printf(" %s ", player)
if lineEnds {
fmt.Println(sepCell)
}
if lineEnds && !lastLine {
fmt.Println(sepLine)
}
if lineEnds {
continue // prevents printing the sepCell below
}
// print the cell separator until 3 cells per line
fmt.Print(sepCell)
}
fmt.Printf("%s\n", sepFooter)
}

View File

@ -0,0 +1,25 @@
package main
// Examples are normally used for showing how to use your package.
// But you can also use them as output testing.
func ExamplePrintBoard() {
// let the printBoard function print an output
printBoard()
// the output should exactly match the following (after Output:)
// Output:
// ~~~~~~~~~~~~~~~
// TIC~TAC~TOE
// ~~~~~~~~~~~~~~~
//
// /---+---+---\
// | X | O | X |
// +---+---+---+
// | O | X | O |
// +---+---+---+
// | X | O | X |
// \---+---+---/
}

View File

@ -0,0 +1,61 @@
package main
import "fmt"
/*
~ TICTACTOE GAME IN GO ~
+ This example uses the very basics of the Go language.
+ The goal is learning all the basics.
*/
const maxTurns = 9
var (
won bool
turn int
player string // current player
)
func main() {
player = player1
turn = maxTurns
// you need to call the other functions but the main
printBoard()
printStatus()
printEnding()
}
// printStatus prints the current status of the game
// it cannot access to the names (vars, consts, etc) inside any other func
func printStatus() {
fmt.Println()
progress := (1 - (float64(turn) / maxTurns)) * 100
fmt.Printf("Current Turn : %d\n", turn)
fmt.Printf("Is there a winner : %t\n", won)
fmt.Printf("Turns left : %.1f%%\n", progress)
}
func printEnding() {
fmt.Println()
switch {
case won:
fmt.Printf(">>> WINNER: %s\n", player)
case turn == maxTurns:
fmt.Println(">>> TIE!")
default:
fmt.Println(">> NEXT TURN!", player)
}
}
// switchPlayer switches to the next player
func switchPlayer() {
// switch the player
if player == player1 {
player = player2
} else {
player = player1
}
}

View File

@ -0,0 +1,25 @@
package main
const (
banner = `
~~~~~~~~~~~~~~~
TIC~TAC~TOE
~~~~~~~~~~~~~~~`
// skin options :-)
player1, player2 = "X", "O"
sepHeader = `/---+---+---\`
sepLine = `+---+---+---+`
sepFooter = `\---+---+---/`
sepCell = "|"
/*
Try it with this instead :)
sepHeader = "╔═══╦═══╦═══╗"
sepLine = "╠═══╬═══╬═══╣"
sepFooter = "╚═══╩═══╩═══╝"
sepCell = "║"
*/
)

View File

@ -0,0 +1,37 @@
package main
import "fmt"
// printBoard prints the board
func printBoard() {
// ~~~~~~~~~~~~~~~
// TIC~TAC~TOE
// ~~~~~~~~~~~~~~~
//
// /---+---+---\
// | X | O | X |
// +---+---+---+
// | O | X | O |
// +---+---+---+
// | X | O | X |
// \---+---+---/
fmt.Printf("%s\n\n", banner)
fmt.Printf("%s\n", sepHeader)
for i, step := 0, 3; i < maxTurns; i += step {
fmt.Print(sepCell)
for j := 0; j < step; j++ {
switchPlayer()
fmt.Printf(" %s %s", player, sepCell)
}
fmt.Println()
if lastLine := (i + step); lastLine != maxTurns {
fmt.Println(sepLine)
}
}
fmt.Printf("%s\n", sepFooter)
}

View File

@ -0,0 +1,25 @@
package main
// Examples are normally used for showing how to use your package.
// But you can also use them as output testing.
func ExamplePrintBoard() {
// let the printBoard function print an output
printBoard()
// the output should exactly match the following (after Output:)
// Output:
// ~~~~~~~~~~~~~~~
// TIC~TAC~TOE
// ~~~~~~~~~~~~~~~
//
// /---+---+---\
// | X | O | X |
// +---+---+---+
// | O | X | O |
// +---+---+---+
// | X | O | X |
// \---+---+---/
}

View File

@ -0,0 +1,62 @@
package main
import "fmt"
/*
~ TICTACTOE GAME IN GO ~
+ This example uses the very basics of the Go language.
+ The goal is learning all the basics.
*/
const maxTurns = 9
var (
won bool
turn int
player string // current player
)
func main() {
player = player1
turn = maxTurns
// you need to call the other functions but the main
printBoard()
printStatus()
printEnding()
}
// printStatus prints the current status of the game
// it cannot access to the names (vars, consts, etc) inside any other func
func printStatus() {
fmt.Println()
progress := (1 - (float64(turn) / maxTurns)) * 100
fmt.Printf("Current Turn : %d\n", turn)
fmt.Printf("Is there a winner : %t\n", won)
fmt.Printf("Turns left : %.1f%%\n", progress)
}
func printEnding() {
fmt.Println()
switch {
case won:
fmt.Printf(">>> WINNER: %s\n", player)
case turn == maxTurns:
fmt.Println(">>> TIE!")
default:
switchPlayer()
fmt.Println(">> NEXT TURN!", player)
}
}
// switchPlayer switches to the next player
func switchPlayer() {
// switch the player
if player == player1 {
player = player2
} else {
player = player1
}
}

View File

@ -0,0 +1,16 @@
package main
const (
banner = `
~~~~~~~~~~~~~~~
TIC~TAC~TOE
~~~~~~~~~~~~~~~`
// skin options :-)
player1, player2 = "X", "O"
sepHeader = `/---+---+---\`
sepLine = `+---+---+---+`
sepFooter = `\---+---+---/`
sepCell = "|"
)

View File

@ -0,0 +1,26 @@
package main
import "fmt"
// printBoard prints the board
func printBoard() {
fmt.Printf("%s\n\n", banner)
fmt.Printf("%s\n", sepHeader)
for i, step := 0, 3; i < len(cells); i += step {
fmt.Print(sepCell)
for j := 0; j < step; j++ {
move := cells[i+j]
fmt.Printf(" %s %s", move, sepCell)
}
fmt.Println()
if lastLine := (i + step); lastLine != len(cells) {
fmt.Println(sepLine)
}
}
fmt.Printf("%s\n", sepFooter)
}

View File

@ -0,0 +1,44 @@
package main
// Examples are normally used for showing how to use your package.
// But you can also use them as output testing.
func ExamplePrintBoard() {
initCells()
printBoard()
// Output:
// ~~~~~~~~~~~~~~~
// TIC~TAC~TOE
// ~~~~~~~~~~~~~~~
//
// /---+---+---\
// | | | |
// +---+---+---+
// | | | |
// +---+---+---+
// | | | |
// \---+---+---/
}
func ExamplePrintBoardCells() {
initCells()
cells[0] = player1
cells[4] = player2
cells[8] = player1
printBoard()
// Output:
// ~~~~~~~~~~~~~~~
// TIC~TAC~TOE
// ~~~~~~~~~~~~~~~
//
// /---+---+---\
// | X | | |
// +---+---+---+
// | | O | |
// +---+---+---+
// | | | X |
// \---+---+---/
}

View File

@ -0,0 +1,33 @@
package main
// initCells initialize the played cells to empty
func initCells() {
// // create a string with empty cells
// // " , , , , , , , , ,"
// var s string
// // number of cells = maxTurns
// for i := 1; i <= maxTurns; i++ {
// s += emptyCell // add an empty move
// s += "," // separate the cells with a comma
// }
// // strings are immutable — you should create a new one
// // fortunately: most of this happens in the stack memory
// // " , , , , , , , , ," -> // " , , , , , , , , "
// s = strings.TrimSuffix(s, ",")
// // store the cells in a slice (slice = list, array in other langs)
// // Split() returns a list of strings: []string (a string slice)
// // [" ", " ", " ", " ", " ", " ", " ", " ", " " ]
// cells = strings.Split(s, ",")
// Right way:
// cells = []string{" ", " ", " ", " ", " ", " ", " ", " ", " "}
//
// Or:
cells = make([]string, maxTurns)
for i := range cells {
cells[i] = emptyCell
}
}

View File

@ -0,0 +1,55 @@
package main
import "fmt"
/*
~ TICTACTOE GAME IN GO ~
+ This example uses the very basics of the Go language.
+ The goal is learning all the basics.
*/
const maxTurns = 9
var (
won bool // is there any winner?
turn int // total valid turns played
player string // current player
cells []string // used to draw the board: contains the players' moves
)
func main() {
player = player1
initCells()
play()
printBoard()
printStatus()
printEnding()
}
// printStatus prints the current status of the game
// it cannot access to the names (vars, consts, etc) inside any other func
func printStatus() {
fmt.Println()
progress := (1 - (float64(turn) / maxTurns)) * 100
fmt.Printf("Current Turn : %d\n", turn)
fmt.Printf("Is there a winner : %t\n", won)
fmt.Printf("Turns left : %.1f%%\n", progress)
}
func printEnding() {
fmt.Println()
switch {
case won:
fmt.Printf(">>> WINNER: %s\n", player)
case turn == maxTurns:
fmt.Println(">>> TIE!")
default:
switchPlayer()
fmt.Println(">> NEXT TURN!", player)
}
}

View File

@ -0,0 +1,38 @@
package main
// play plays the game for the current player.
// + registers the player's move in the board.
// if the move is valid:
// + increases the turn.
func play() {
// [" ", " ", " ", " ", " ", " ", " ", " ", " " ] -> cells slice
// 0 1 2 3 4 5 6 7 8 -> indexes
// /---+---+---\
// | 0 | 1 | 2 |
// +---+---+---+
// | 3 | 4 | 5 |
// +---+---+---+
// | 6 | 7 | 8 |
// \---+---+---/
// current player plays to the 4th position (index)
// play to a fixed position "for now".
pos := 4
// register the move: put the player's sign on the board
cells[pos] = player
// increment the current turns
turn++
}
// switchPlayer switches to the next player
func switchPlayer() {
// switch the player
if player == player1 {
player = player2
} else {
player = player1
}
}

View File

@ -0,0 +1,17 @@
package main
const (
banner = `
~~~~~~~~~~~~~~~
TIC~TAC~TOE
~~~~~~~~~~~~~~~`
// skin options :-)
player1, player2 = "X", "O"
emptyCell = " "
sepHeader = `/---+---+---\`
sepLine = `+---+---+---+`
sepFooter = `\---+---+---/`
sepCell = "|"
)

View File

@ -0,0 +1,26 @@
package main
import "fmt"
// printBoard prints the board
func printBoard() {
fmt.Printf("%s\n\n", banner)
fmt.Printf("%s\n", sepHeader)
for i, step := 0, 3; i < len(cells); i += step {
fmt.Print(sepCell)
for j := 0; j < step; j++ {
move := cells[i+j]
fmt.Printf(" %s %s", move, sepCell)
}
fmt.Println()
if lastLine := (i + step); lastLine != len(cells) {
fmt.Println(sepLine)
}
}
fmt.Printf("%s\n", sepFooter)
}

View File

@ -0,0 +1,44 @@
package main
// Examples are normally used for showing how to use your package.
// But you can also use them as output testing.
func ExamplePrintBoard() {
initCells()
printBoard()
// Output:
// ~~~~~~~~~~~~~~~
// TIC~TAC~TOE
// ~~~~~~~~~~~~~~~
//
// /---+---+---\
// | | | |
// +---+---+---+
// | | | |
// +---+---+---+
// | | | |
// \---+---+---/
}
func ExamplePrintBoardCells() {
initCells()
cells[0] = player1
cells[4] = player2
cells[8] = player1
printBoard()
// Output:
// ~~~~~~~~~~~~~~~
// TIC~TAC~TOE
// ~~~~~~~~~~~~~~~
//
// /---+---+---\
// | X | | |
// +---+---+---+
// | | O | |
// +---+---+---+
// | | | X |
// \---+---+---/
}

View File

@ -0,0 +1,8 @@
package main
// initCells initialize the played cells to empty
func initCells() {
for i := range cells {
cells[i] = emptyCell
}
}

View File

@ -0,0 +1,55 @@
package main
import "fmt"
/*
~ TICTACTOE GAME IN GO ~
+ This example uses the very basics of the Go language.
+ The goal is learning all the basics.
*/
const maxTurns = 9
var (
won bool // is there any winner?
turn int // total valid turns played
player string // current player
cells [maxTurns]string // used to draw the board: contains the players' moves
)
func main() {
player = player1
initCells()
play()
printBoard()
printStatus()
printEnding()
}
// printStatus prints the current status of the game
// it cannot access to the names (vars, consts, etc) inside any other func
func printStatus() {
fmt.Println()
progress := (1 - (float64(turn) / maxTurns)) * 100
fmt.Printf("Current Turn : %d\n", turn)
fmt.Printf("Is there a winner : %t\n", won)
fmt.Printf("Turns left : %.1f%%\n", progress)
}
func printEnding() {
fmt.Println()
switch {
case won:
fmt.Printf(">>> WINNER: %s\n", player)
case turn == maxTurns:
fmt.Println(">>> TIE!")
default:
switchPlayer()
fmt.Println(">> NEXT TURN!", player)
}
}

View File

@ -0,0 +1,38 @@
package main
// play plays the game for the current player.
// + registers the player's move in the board.
// if the move is valid:
// + increases the turn.
func play() {
// [" ", " ", " ", " ", " ", " ", " ", " ", " " ] -> cells slice
// 0 1 2 3 4 5 6 7 8 -> indexes
// /---+---+---\
// | 0 | 1 | 2 |
// +---+---+---+
// | 3 | 4 | 5 |
// +---+---+---+
// | 6 | 7 | 8 |
// \---+---+---/
// current player plays to the 4th position (index)
// play to a fixed position "for now".
pos := 4
// register the move: put the player's sign on the board
cells[pos] = player
// increment the current turns
turn++
}
// switchPlayer switches to the next player
func switchPlayer() {
// switch the player
if player == player1 {
player = player2
} else {
player = player1
}
}

View File

@ -0,0 +1,17 @@
package main
const (
banner = `
~~~~~~~~~~~~~~~
TIC~TAC~TOE
~~~~~~~~~~~~~~~`
// skin options :-)
player1, player2 = "X", "O"
emptyCell = " "
sepHeader = `/---+---+---\`
sepLine = `+---+---+---+`
sepFooter = `\---+---+---/`
sepCell = "|"
)

View File

@ -0,0 +1,26 @@
package main
import "fmt"
// printBoard prints the board
func printBoard() {
fmt.Printf("%s\n\n", banner)
fmt.Printf("%s\n", sepHeader)
for i, step := 0, 3; i < len(cells); i += step {
fmt.Print(sepCell)
for j := 0; j < step; j++ {
move := cells[i+j]
fmt.Printf(" %s %s", move, sepCell)
}
fmt.Println()
if lastLine := (i + step); lastLine != len(cells) {
fmt.Println(sepLine)
}
}
fmt.Printf("%s\n", sepFooter)
}

View File

@ -0,0 +1,41 @@
package main
// Examples are normally used for showing how to use your package.
// But you can also use them as output testing.
func ExamplePrintBoard() {
printBoard()
// Output:
// ~~~~~~~~~~~~~~~
// TIC~TAC~TOE
// ~~~~~~~~~~~~~~~
//
// /---+---+---\
// | | | |
// +---+---+---+
// | | | |
// +---+---+---+
// | | | |
// \---+---+---/
}
func ExamplePrintBoardCells() {
cells[0] = player1
cells[4] = player2
cells[8] = player1
printBoard()
// Output:
// ~~~~~~~~~~~~~~~
// TIC~TAC~TOE
// ~~~~~~~~~~~~~~~
//
// /---+---+---\
// | X | | |
// +---+---+---+
// | | O | |
// +---+---+---+
// | | | X |
// \---+---+---/
}

View File

@ -0,0 +1,20 @@
package main
import (
"math/rand"
"time"
)
// init is another special function
// Go calls it before the main function
func init() {
rand.Seed(time.Now().UnixNano())
initCells()
}
// initCells initialize the played cells to empty
func initCells() {
for i := range cells {
cells[i] = emptyCell
}
}

View File

@ -0,0 +1,69 @@
package main
import "fmt"
/*
~ TICTACTOE GAME IN GO ~
+ This example uses the very basics of the Go language.
+ The goal is learning all the basics.
*/
const maxTurns = 9
var (
won bool // is there any winner?
turn int // total valid turns played
player string // current player
cells [maxTurns]string // used to draw the board: contains the players' moves
lastPos int // last played position
wrongMove bool // was the last move wrong?
)
func main() {
player = player1
printBoard()
for i := 0; i < 4; i++ {
wait()
play()
printBoard()
fmt.Printf("\n>>> PLAYER %q PLAYS to %d\n", player, lastPos+1)
printEnding()
}
}
func wait() {
fmt.Println()
fmt.Scanln()
}
// printStatus prints the current status of the game
// it cannot access to the names (vars, consts, etc) inside any other func
func printStatus() {
fmt.Println()
progress := (1 - (float64(turn) / maxTurns)) * 100
fmt.Printf("Current Turn : %d\n", turn)
fmt.Printf("Is there a winner : %t\n", won)
fmt.Printf("Turns left : %.1f%%\n", progress)
}
func printEnding() {
switch {
default:
switchPlayer()
printStatus()
case wrongMove:
fmt.Printf(">>> CELL IS OCCUPIED: PLAY AGAIN!\n")
wrongMove = false // reset for the next turn
case won:
fmt.Printf(">>> WINNER: %s\n", player)
case turn == maxTurns:
fmt.Println(">>> TIE!")
}
}

View File

@ -0,0 +1,48 @@
package main
import "math/rand"
// play plays the game for the current player.
// + registers the player's move in the board.
// if the move is valid:
// + increases the turn.
func play() {
// [" ", " ", " ", " ", " ", " ", " ", " ", " " ] -> cells slice
// 0 1 2 3 4 5 6 7 8 -> indexes
// /---+---+---\
// | 0 | 1 | 2 |
// +---+---+---+
// | 3 | 4 | 5 |
// +---+---+---+
// | 6 | 7 | 8 |
// \---+---+---/
// pick a random move (very intelligent AI!)
// it can play to the same position!
lastPos = rand.Intn(maxTurns)
// is it a valid move?
if cells[lastPos] != emptyCell {
wrongMove = true
// skip the rest of the function from running
return
}
// register the move: put the player's sign on the board
cells[lastPos] = player
// increment the current turns
turn++
}
// switchPlayer switches to the next player
func switchPlayer() {
// switch the player
if player == player1 {
player = player2
} else {
player = player1
}
}

View File

@ -0,0 +1,17 @@
package main
const (
banner = `
~~~~~~~~~~~~~~~
TIC~TAC~TOE
~~~~~~~~~~~~~~~`
// skin options :-)
player1, player2 = "X", "O"
emptyCell = " "
sepHeader = `/---+---+---\`
sepLine = `+---+---+---+`
sepFooter = `\---+---+---/`
sepCell = "|"
)

View File

@ -0,0 +1,26 @@
package main
import "fmt"
// printBoard prints the board
func printBoard() {
fmt.Printf("%s\n\n", banner)
fmt.Printf("%s\n", sepHeader)
for i, step := 0, 3; i < len(cells); i += step {
fmt.Print(sepCell)
for j := 0; j < step; j++ {
move := cells[i+j]
fmt.Printf(" %s %s", move, sepCell)
}
fmt.Println()
if lastLine := (i + step); lastLine != len(cells) {
fmt.Println(sepLine)
}
}
fmt.Printf("%s\n", sepFooter)
}

View File

@ -0,0 +1,41 @@
package main
// Examples are normally used for showing how to use your package.
// But you can also use them as output testing.
func ExamplePrintBoard() {
printBoard()
// Output:
// ~~~~~~~~~~~~~~~
// TIC~TAC~TOE
// ~~~~~~~~~~~~~~~
//
// /---+---+---\
// | | | |
// +---+---+---+
// | | | |
// +---+---+---+
// | | | |
// \---+---+---/
}
func ExamplePrintBoardCells() {
cells[0] = player1
cells[4] = player2
cells[8] = player1
printBoard()
// Output:
// ~~~~~~~~~~~~~~~
// TIC~TAC~TOE
// ~~~~~~~~~~~~~~~
//
// /---+---+---\
// | X | | |
// +---+---+---+
// | | O | |
// +---+---+---+
// | | | X |
// \---+---+---/
}

View File

@ -0,0 +1,20 @@
package main
import (
"math/rand"
"time"
)
// init is another special function
// Go calls it before the main function
func init() {
rand.Seed(time.Now().UnixNano())
initCells()
}
// initCells initialize the played cells to empty
func initCells() {
for i := range cells {
cells[i] = emptyCell
}
}

View File

@ -0,0 +1,74 @@
package main
import "fmt"
/*
~ TICTACTOE GAME IN GO ~
+ This example uses the very basics of the Go language.
+ The goal is learning all the basics.
*/
const maxTurns = 9
var (
won bool // is there any winner?
turn int // total valid turns played
player = player1 // current player
cells [maxTurns]string // used to draw the board: contains the players' moves
lastPos int // last played position
wrongMove bool // was the last move wrong?
)
func main() {
printBoard()
// alternative:
// for won || tie {}
// this a label: it can be used by break, continue and goto
theGameLoop:
// loop forever until the game ends (tie or win)
for {
wait()
play()
printBoard()
fmt.Printf("\n>>> PLAYER %q PLAYS to %d\n", player, lastPos+1)
// simple statement
switch tie := turn == maxTurns; {
default:
switchPlayer()
printStatus()
case wrongMove:
fmt.Printf(">>> CELL IS OCCUPIED: PLAY AGAIN!\n")
wrongMove = false // reset for the next turn
case won, tie:
if won {
fmt.Println(">>> WINNER:", player)
} else {
fmt.Println(">>> TIE!")
}
break theGameLoop
}
}
}
func wait() {
fmt.Println()
fmt.Scanln()
}
// printStatus prints the current status of the game
// it cannot access to the names (vars, consts, etc) inside any other func
func printStatus() {
fmt.Println()
progress := (1 - (float64(turn) / maxTurns)) * 100
fmt.Printf("Current Turn : %d\n", turn)
fmt.Printf("Is there a winner : %t\n", won)
fmt.Printf("Turns left : %.1f%%\n", progress)
}

View File

@ -0,0 +1,48 @@
package main
import "math/rand"
// play plays the game for the current player.
// + registers the player's move in the board.
// if the move is valid:
// + increases the turn.
func play() {
// [" ", " ", " ", " ", " ", " ", " ", " ", " " ] -> cells slice
// 0 1 2 3 4 5 6 7 8 -> indexes
// /---+---+---\
// | 0 | 1 | 2 |
// +---+---+---+
// | 3 | 4 | 5 |
// +---+---+---+
// | 6 | 7 | 8 |
// \---+---+---/
// pick a random move (very intelligent AI!)
// it can play to the same position!
lastPos = rand.Intn(maxTurns)
// is it a valid move?
if cells[lastPos] != emptyCell {
wrongMove = true
// skip the rest of the function from running
return
}
// register the move: put the player's sign on the board
cells[lastPos] = player
// increment the current turns
turn++
}
// switchPlayer switches to the next player
func switchPlayer() {
// switch the player
if player == player1 {
player = player2
} else {
player = player1
}
}

View File

@ -0,0 +1,17 @@
package main
const (
banner = `
~~~~~~~~~~~~~~~
TIC~TAC~TOE
~~~~~~~~~~~~~~~`
// skin options :-)
player1, player2 = "X", "O"
emptyCell = " "
sepHeader = `/---+---+---\`
sepLine = `+---+---+---+`
sepFooter = `\---+---+---/`
sepCell = "|"
)

View File

@ -0,0 +1,26 @@
package main
import "fmt"
// printBoard prints the board
func printBoard() {
fmt.Printf("%s\n\n", banner)
fmt.Printf("%s\n", sepHeader)
for i, step := 0, 3; i < len(cells); i += step {
fmt.Print(sepCell)
for j := 0; j < step; j++ {
move := cells[i+j]
fmt.Printf(" %s %s", move, sepCell)
}
fmt.Println()
if lastLine := (i + step); lastLine != len(cells) {
fmt.Println(sepLine)
}
}
fmt.Printf("%s\n", sepFooter)
}

View File

@ -0,0 +1,41 @@
package main
// Examples are normally used for showing how to use your package.
// But you can also use them as output testing.
func ExamplePrintBoard() {
printBoard()
// Output:
// ~~~~~~~~~~~~~~~
// TIC~TAC~TOE
// ~~~~~~~~~~~~~~~
//
// /---+---+---\
// | | | |
// +---+---+---+
// | | | |
// +---+---+---+
// | | | |
// \---+---+---/
}
func ExamplePrintBoardCells() {
cells[0] = player1
cells[4] = player2
cells[8] = player1
printBoard()
// Output:
// ~~~~~~~~~~~~~~~
// TIC~TAC~TOE
// ~~~~~~~~~~~~~~~
//
// /---+---+---\
// | X | | |
// +---+---+---+
// | | O | |
// +---+---+---+
// | | | X |
// \---+---+---/
}

View File

@ -0,0 +1,55 @@
package main
// -------------------------------------------------
// IS THERE A WINNER? OR IS IT A TIE?
// -------------------------------------------------
// /---+---+---\
// | 0 | 1 | 2 |
// +---+---+---+
// | 3 | 4 | 5 |
// +---+---+---+
// | 6 | 7 | 8 |
// \---+---+---/
func checkWinOrTie() {
// intentional bug: tie shouldn't happen before winning detection
if tie = turn == maxTurns; tie {
// if tie don't check for the winning
return
}
// loop over all the players
for i := 1; i <= 2; i++ {
// check for the next player
p := player2
if i == 1 {
p = player1
}
/* check horizontals */
hor := (cells[0] == p && cells[1] == p && cells[2] == p) ||
(cells[3] == p && cells[4] == p && cells[5] == p) ||
(cells[6] == p && cells[7] == p && cells[8] == p)
/* check verticals */
ver := (cells[0] == p && cells[3] == p && cells[6] == p) ||
(cells[1] == p && cells[4] == p && cells[7] == p) ||
(cells[2] == p && cells[5] == p && cells[8] == p)
/* check diagonals */
diag := (cells[0] == p && cells[4] == p && cells[8] == p) ||
(cells[2] == p && cells[4] == p && cells[6] == p)
// any winner?
if hor || ver || diag {
won = true
// this player wins
player = p
// there is a winner so don't check for tie!
return
}
}
}

View File

@ -0,0 +1,20 @@
package main
import (
"math/rand"
"time"
)
// init is another special function
// Go calls it before the main function
func init() {
rand.Seed(time.Now().UnixNano())
initCells()
}
// initCells initialize the played cells to empty
func initCells() {
for i := range cells {
cells[i] = emptyCell
}
}

View File

@ -0,0 +1,124 @@
package main
import "fmt"
/*
~ TICTACTOE GAME IN GO ~
+ This example uses the very basics of the Go language.
+ The goal is learning all the basics.
*/
const maxTurns = 9
var (
won, tie bool // is there any winner or a tie?
turn int // total valid turns played
player = player1 // current player
cells [maxTurns]string // used to draw the board: contains the players' moves
lastPos int // last played position
wrongMove bool // was the last move wrong?
)
//
// VERSION 2: HELPER FUNC
//
func main() {
printBoard()
wait()
for nextTurn() {
wait()
}
// loop forever until the game ends (tie or win)
// for {
// // wait()
// if !nextTurn() {
// break
// }
// }
}
func nextTurn() bool {
play()
printBoard()
fmt.Printf("\n>>> PLAYER %q PLAYS to %d\n", player, lastPos+1)
// the switch below is about winning and tie conditions.
// so it is good have checkWinOrTie() as a simple statement.
// totally optional.
switch checkWinOrTie(); {
default:
switchPlayer()
printStatus()
case wrongMove:
fmt.Printf(">>> CELL IS OCCUPIED: PLAY AGAIN!\n")
wrongMove = false // reset for the next turn
case won, tie:
if won {
fmt.Println(">>> WINNER:", player)
} else {
fmt.Println(">>> TIE!")
}
return false
}
return true
}
//
// VERSION 1: LABELED BREAK
//
// func main() {
// printBoard()
// // this a label: it can be used by break, continue and goto
// theGameLoop:
// // loop forever until game ends (tie or win)
// for {
// // wait()
// play()
// printBoard()
// fmt.Printf("\n>>> PLAYER %q PLAYS to %d\n", player, lastPos+1)
// // the switch below is about winning and tie conditions.
// // so it is good have checkWinOrTie() as a simple statement.
// // totally optional.
// switch checkWinOrTie(); {
// default:
// printStatus()
// case wrongMove:
// fmt.Printf(">>> CELL IS OCCUPIED: PLAY AGAIN!\n")
// wrongMove = false // reset for the next turn
// case won, tie:
// if won {
// fmt.Println(">>> WINNER:", player)
// } else {
// fmt.Println(">>> TIE!")
// }
// break theGameLoop
// }
// }
// }
func wait() {
fmt.Println()
fmt.Scanln()
}
// printStatus prints the current status of the game
// it cannot access to the names (vars, consts, etc) inside any other func
func printStatus() {
fmt.Println()
progress := (1 - (float64(turn) / maxTurns)) * 100
fmt.Printf("Current Turn : %d\n", turn)
fmt.Printf("Is there a winner : %t\n", won)
fmt.Printf("Turns left : %.1f%%\n", progress)
}

View File

@ -0,0 +1,37 @@
package main
import "math/rand"
// play plays the game for the current player.
// + registers the player's move in the board.
// if the move is valid:
// + increases the turn.
func play() {
// pick a random move (very intelligent AI!)
// it can play to the same position!
lastPos = rand.Intn(maxTurns)
// is it a valid move?
if cells[lastPos] != emptyCell {
wrongMove = true
// skip the rest of the function from running
return
}
// register the move: put the player's sign on the board
cells[lastPos] = player
// increment the current turns
turn++
}
// switchPlayer switches to the next player
func switchPlayer() {
// switch the player
if player == player1 {
player = player2
} else {
player = player1
}
}

View File

@ -0,0 +1,17 @@
package main
const (
banner = `
~~~~~~~~~~~~~~~
TIC~TAC~TOE
~~~~~~~~~~~~~~~`
// skin options :-)
player1, player2 = "X", "O"
emptyCell = " "
sepHeader = `/---+---+---\`
sepLine = `+---+---+---+`
sepFooter = `\---+---+---/`
sepCell = "|"
)

View File

@ -0,0 +1,26 @@
package main
import "fmt"
// printBoard prints the board
func printBoard() {
fmt.Printf("%s\n\n", banner)
fmt.Printf("%s\n", sepHeader)
for i, step := 0, 3; i < len(cells); i += step {
fmt.Print(sepCell)
for j := 0; j < step; j++ {
move := cells[i+j]
fmt.Printf(" %s %s", move, sepCell)
}
fmt.Println()
if lastLine := (i + step); lastLine != len(cells) {
fmt.Println(sepLine)
}
}
fmt.Printf("%s\n", sepFooter)
}

View File

@ -0,0 +1,41 @@
package main
// Examples are normally used for showing how to use your package.
// But you can also use them as output testing.
func ExamplePrintBoard() {
printBoard()
// Output:
// ~~~~~~~~~~~~~~~
// TIC~TAC~TOE
// ~~~~~~~~~~~~~~~
//
// /---+---+---\
// | | | |
// +---+---+---+
// | | | |
// +---+---+---+
// | | | |
// \---+---+---/
}
func ExamplePrintBoardCells() {
cells[0] = player1
cells[4] = player2
cells[8] = player1
printBoard()
// Output:
// ~~~~~~~~~~~~~~~
// TIC~TAC~TOE
// ~~~~~~~~~~~~~~~
//
// /---+---+---\
// | X | | |
// +---+---+---+
// | | O | |
// +---+---+---+
// | | | X |
// \---+---+---/
}

View File

@ -0,0 +1,58 @@
package main
// -------------------------------------------------
// IS THERE A WINNER? OR IS IT A TIE?
// -------------------------------------------------
// /---+---+---\
// | 0 | 1 | 2 |
// +---+---+---+
// | 3 | 4 | 5 |
// +---+---+---+
// | 6 | 7 | 8 |
// \---+---+---/
func checkWinOrTie() {
// intentional bug: tie shouldn't happen before winning detection
// if tie = turn == maxTurns; tie {
// // if tie don't check for the winning
// return
// }
// loop over all the players
for i := 1; i <= 2; i++ {
// check for the next player
p := player2
if i == 1 {
p = player1
}
/* check horizontals */
hor := (cells[0] == p && cells[1] == p && cells[2] == p) ||
(cells[3] == p && cells[4] == p && cells[5] == p) ||
(cells[6] == p && cells[7] == p && cells[8] == p)
/* check verticals */
ver := (cells[0] == p && cells[3] == p && cells[6] == p) ||
(cells[1] == p && cells[4] == p && cells[7] == p) ||
(cells[2] == p && cells[5] == p && cells[8] == p)
/* check diagonals */
diag := (cells[0] == p && cells[4] == p && cells[8] == p) ||
(cells[2] == p && cells[4] == p && cells[6] == p)
// any winner?
if hor || ver || diag {
won = true
// this player wins
player = p
// there is a winner so don't check for tie!
return
}
}
// check for tie
tie = turn == maxTurns
}

View File

@ -0,0 +1,59 @@
package main
import "testing"
func TestWin(t *testing.T) {
// /---+---+---\
// | O | X | X |
// +---+---+---+
// | O | O | X |
// +---+---+---+
// | X | O | X |
// \---+---+---/
cells[0] = player2
cells[1] = player1
cells[2] = player1
cells[3] = player2
cells[4] = player2
cells[5] = player1
cells[6] = player1
cells[7] = player2
cells[8] = player1
turn = maxTurns
if checkWinOrTie(); !won {
t.Errorf("won = %t; want true", won)
}
// TestWin was messing up with the results.
// Test ordering shouldn't be important.
initCells()
}
func TestTie(t *testing.T) {
// /---+---+---\
// | O | X | X |
// +---+---+---+
// | X | O | O |
// +---+---+---+
// | X | O | X |
// \---+---+---/
cells[0] = player2
cells[1] = player1
cells[2] = player1
cells[3] = player1
cells[4] = player2
cells[5] = player2
cells[6] = player1
cells[7] = player2
cells[8] = player1
turn = maxTurns
if checkWinOrTie(); !tie {
t.Errorf("tie = %t; want true", tie)
}
initCells()
}

View File

@ -0,0 +1,20 @@
package main
import (
"math/rand"
"time"
)
// init is another special function
// Go calls it before the main function
func init() {
rand.Seed(time.Now().UnixNano())
initCells()
}
// initCells initialize the played cells to empty
func initCells() {
for i := range cells {
cells[i] = emptyCell
}
}

View File

@ -0,0 +1,78 @@
package main
import "fmt"
/*
~ TICTACTOE GAME IN GO ~
+ This example uses the very basics of the Go language.
+ The goal is learning all the basics.
*/
const maxTurns = 9
var (
won, tie bool // is there any winner or a tie?
turn int // total valid turns played
player = player1 // current player
cells [maxTurns]string // used to draw the board: contains the players' moves
lastPos int // last played position
wrongMove bool // was the last move wrong?
)
// main is only responsible for the game loop, that's it.
func main() {
printBoard()
wait()
for nextTurn() {
wait()
}
}
// nextTurn prints the board for the next turn and checks for the winning conditions.
// if win or tie: returns false, otherwise true.
func nextTurn() bool {
play()
printBoard()
fmt.Printf("\n>>> PLAYER %q PLAYS to %d\n", player, lastPos+1)
// the switch below is about winning and tie conditions.
// so it is good have checkWinOrTie() as a simple statement.
// totally optional.
switch checkWinOrTie(); {
default:
switchPlayer()
printStatus()
case wrongMove:
fmt.Printf(">>> CELL IS OCCUPIED: PLAY AGAIN!\n")
wrongMove = false // reset for the next turn
case won, tie:
if won {
fmt.Println(">>> WINNER:", player)
} else {
fmt.Println(">>> TIE!")
}
return false
}
return true
}
func wait() {
fmt.Println()
fmt.Scanln()
}
// printStatus prints the current status of the game
// it cannot access to the names (vars, consts, etc) inside any other func
func printStatus() {
fmt.Println()
progress := (1 - (float64(turn) / maxTurns)) * 100
fmt.Printf("Current Turn : %d\n", turn)
fmt.Printf("Is there a winner : %t\n", won)
fmt.Printf("Turns left : %.1f%%\n", progress)
}

View File

@ -0,0 +1,37 @@
package main
import "math/rand"
// play plays the game for the current player.
// + registers the player's move in the board.
// if the move is valid:
// + increases the turn.
func play() {
// pick a random move (very intelligent AI!)
// it can play to the same position!
lastPos = rand.Intn(maxTurns)
// is it a valid move?
if cells[lastPos] != emptyCell {
wrongMove = true
// skip the rest of the function from running
return
}
// register the move: put the player's sign on the board
cells[lastPos] = player
// increment the current turns
turn++
}
// switchPlayer switches to the next player
func switchPlayer() {
// switch the player
if player == player1 {
player = player2
} else {
player = player1
}
}

View File

@ -0,0 +1,26 @@
package main
import "testing"
func TestWrongMove(t *testing.T) {
// /---+---+---\
// | X | X | X |
// +---+---+---+
// | X | X | X |
// +---+---+---+
// | X | X | X |
// \---+---+---/
// fill the board with artificial cells
for i := range cells {
cells[i] = player1
}
// any move beyond this point is wrong.
// reason: every cell is occupied.
if play(); !wrongMove {
t.Errorf("wrongMove = %t; want true", wrongMove)
}
initCells()
}

View File

@ -0,0 +1,17 @@
package main
const (
banner = `
~~~~~~~~~~~~~~~
TIC~TAC~TOE
~~~~~~~~~~~~~~~`
// skin options :-)
player1, player2 = "X", "O"
emptyCell = " "
sepHeader = `/---+---+---\`
sepLine = `+---+---+---+`
sepFooter = `\---+---+---/`
sepCell = "|"
)

View File

@ -0,0 +1,26 @@
package main
import "fmt"
// printBoard prints the board
func printBoard() {
fmt.Printf("%s\n\n", banner)
fmt.Printf("%s\n", sepHeader)
for i, step := 0, 3; i < len(cells); i += step {
fmt.Print(sepCell)
for j := 0; j < step; j++ {
move := cells[i+j]
fmt.Printf(" %s %s", move, sepCell)
}
fmt.Println()
if lastLine := (i + step); lastLine != len(cells) {
fmt.Println(sepLine)
}
}
fmt.Printf("%s\n", sepFooter)
}

View File

@ -0,0 +1,41 @@
package main
// Examples are normally used for showing how to use your package.
// But you can also use them as output testing.
func ExamplePrintBoard() {
printBoard()
// Output:
// ~~~~~~~~~~~~~~~
// TIC~TAC~TOE
// ~~~~~~~~~~~~~~~
//
// /---+---+---\
// | | | |
// +---+---+---+
// | | | |
// +---+---+---+
// | | | |
// \---+---+---/
}
func ExamplePrintBoardCells() {
cells[0] = player1
cells[4] = player2
cells[8] = player1
printBoard()
// Output:
// ~~~~~~~~~~~~~~~
// TIC~TAC~TOE
// ~~~~~~~~~~~~~~~
//
// /---+---+---\
// | X | | |
// +---+---+---+
// | | O | |
// +---+---+---+
// | | | X |
// \---+---+---/
}

View File

@ -0,0 +1,58 @@
package main
// -------------------------------------------------
// IS THERE A WINNER? OR IS IT A TIE?
// -------------------------------------------------
// /---+---+---\
// | 0 | 1 | 2 |
// +---+---+---+
// | 3 | 4 | 5 |
// +---+---+---+
// | 6 | 7 | 8 |
// \---+---+---/
func checkWinOrTie() {
// intentional bug: tie shouldn't happen before winning detection
// if tie = turn == maxTurns; tie {
// // if tie don't check for the winning
// return
// }
// loop over all the players
for i := 1; i <= 2; i++ {
// check for the next player
p := player2
if i == 1 {
p = player1
}
/* check horizontals */
hor := (cells[0] == p && cells[1] == p && cells[2] == p) ||
(cells[3] == p && cells[4] == p && cells[5] == p) ||
(cells[6] == p && cells[7] == p && cells[8] == p)
/* check verticals */
ver := (cells[0] == p && cells[3] == p && cells[6] == p) ||
(cells[1] == p && cells[4] == p && cells[7] == p) ||
(cells[2] == p && cells[5] == p && cells[8] == p)
/* check diagonals */
diag := (cells[0] == p && cells[4] == p && cells[8] == p) ||
(cells[2] == p && cells[4] == p && cells[6] == p)
// any winner?
if hor || ver || diag {
won = true
// this player wins
player = p
// there is a winner so don't check for tie!
return
}
}
// check for tie
tie = turn == maxTurns
}

View File

@ -0,0 +1,59 @@
package main
import "testing"
func TestWin(t *testing.T) {
// /---+---+---\
// | O | X | X |
// +---+---+---+
// | O | O | X |
// +---+---+---+
// | X | O | X |
// \---+---+---/
cells[0] = player2
cells[1] = player1
cells[2] = player1
cells[3] = player2
cells[4] = player2
cells[5] = player1
cells[6] = player1
cells[7] = player2
cells[8] = player1
turn = maxTurns
if checkWinOrTie(); !won {
t.Errorf("won = %t; want true", won)
}
// TestWin was messing up with the results.
// Test ordering shouldn't be important.
initCells()
}
func TestTie(t *testing.T) {
// /---+---+---\
// | O | X | X |
// +---+---+---+
// | X | O | O |
// +---+---+---+
// | X | O | X |
// \---+---+---/
cells[0] = player2
cells[1] = player1
cells[2] = player1
cells[3] = player1
cells[4] = player2
cells[5] = player2
cells[6] = player1
cells[7] = player2
cells[8] = player1
turn = maxTurns
if checkWinOrTie(); !tie {
t.Errorf("tie = %t; want true", tie)
}
initCells()
}

View File

@ -0,0 +1,37 @@
package main
import (
"fmt"
"math/rand"
"os"
"strconv"
"time"
)
// init is another special function
// Go calls it before the main function
func init() {
rand.Seed(time.Now().UnixNano())
initCells()
}
// initCells initialize the played cells to empty
func initCells() {
for i := range cells {
cells[i] = emptyCell
}
}
func setGameSpeed() {
// args can be used within the if block
// gs and err can be used in the else if and else branches
if args := os.Args; len(args) == 1 {
fmt.Println("Setting game speed to default.")
} else if gs, err := strconv.Atoi(args[1]); err != nil {
fmt.Println("Wrong game speed. Provide an integer.")
} else {
gameSpeed = time.Duration(gs) * time.Second
}
fmt.Printf("Game speed is %q.\n", gameSpeed)
}

View File

@ -0,0 +1,45 @@
package main
import (
"fmt"
"time"
)
/*
~ TICTACTOE GAME IN GO ~
+ This example uses the very basics of the Go language.
+ The goal is learning all the basics.
*/
const (
maxTurns = 9
defaultGameSpeed = time.Second * 2 // time between plays
)
var (
won, tie bool // is there any winner or a tie?
turn int // total valid turns played
cells [maxTurns]string // used to draw the board: contains the players' moves
lastPos int // last played position
wrongMove bool // was the last move wrong?
player = player1 // current player
gameSpeed = defaultGameSpeed // sets the default game speed
)
// main is only responsible for the game loop, that's it.
func main() {
setGameSpeed()
printBoard()
wait()
for nextTurn() {
wait()
}
}
func wait() {
fmt.Println()
time.Sleep(gameSpeed) // player thinks...
}

View File

@ -0,0 +1,37 @@
package main
import "math/rand"
// play plays the game for the current player.
// + registers the player's move in the board.
// if the move is valid:
// + increases the turn.
func play() {
// pick a random move (very intelligent AI!)
// it can play to the same position!
lastPos = rand.Intn(maxTurns)
// is it a valid move?
if cells[lastPos] != emptyCell {
wrongMove = true
// skip the rest of the function from running
return
}
// register the move: put the player's sign on the board
cells[lastPos] = player
// increment the current turns
turn++
}
// switchPlayer switches to the next player
func switchPlayer() {
// switch the player
if player == player1 {
player = player2
} else {
player = player1
}
}

View File

@ -0,0 +1,26 @@
package main
import "testing"
func TestWrongMove(t *testing.T) {
// /---+---+---\
// | X | X | X |
// +---+---+---+
// | X | X | X |
// +---+---+---+
// | X | X | X |
// \---+---+---/
// fill the board with artificial cells
for i := range cells {
cells[i] = player1
}
// any move beyond this point is wrong.
// reason: every cell is occupied.
if play(); !wrongMove {
t.Errorf("wrongMove = %t; want true", wrongMove)
}
initCells()
}

View File

@ -0,0 +1,17 @@
package main
const (
banner = `
~~~~~~~~~~~~~~~
TIC~TAC~TOE
~~~~~~~~~~~~~~~`
// skin options :-)
player1, player2 = "X", "O"
emptyCell = " "
sepHeader = `/---+---+---\`
sepLine = `+---+---+---+`
sepFooter = `\---+---+---/`
sepCell = "|"
)

View File

@ -0,0 +1,45 @@
package main
import "fmt"
// nextTurn prints the board for the next turn and checks for the winning conditions.
// if win or tie: returns false, otherwise true.
func nextTurn() bool {
play()
printBoard()
fmt.Printf("\n>>> PLAYER %q PLAYS to %d\n", player, lastPos+1)
// the switch below is about winning and tie conditions.
// so it is good have checkWinOrTie() as a simple statement.
// totally optional.
switch checkWinOrTie(); {
default:
switchPlayer()
printStatus()
case wrongMove:
fmt.Printf(">>> CELL IS OCCUPIED: PLAY AGAIN!\n")
wrongMove = false // reset for the next turn
case won, tie:
if won {
fmt.Println(">>> WINNER:", player)
} else {
fmt.Println(">>> TIE!")
}
return false
}
return true
}
// printStatus prints the current status of the game
// it cannot access to the names (vars, consts, etc) inside any other func
func printStatus() {
fmt.Println()
progress := (1 - (float64(turn) / maxTurns)) * 100
fmt.Printf("Current Turn : %d\n", turn)
fmt.Printf("Is there a winner : %t\n", won)
fmt.Printf("Turns left : %.1f%%\n", progress)
}

View File

@ -0,0 +1,26 @@
package main
import "fmt"
// printBoard prints the board
func printBoard() {
fmt.Printf("%s\n\n", banner)
fmt.Printf("%s\n", sepHeader)
for i, step := 0, 3; i < len(cells); i += step {
fmt.Print(sepCell)
for j := 0; j < step; j++ {
move := cells[i+j]
fmt.Printf(" %s %s", move, sepCell)
}
fmt.Println()
if lastLine := (i + step); lastLine != len(cells) {
fmt.Println(sepLine)
}
}
fmt.Printf("%s\n", sepFooter)
}

View File

@ -0,0 +1,41 @@
package main
// Examples are normally used for showing how to use your package.
// But you can also use them as output testing.
func ExamplePrintBoard() {
printBoard()
// Output:
// ~~~~~~~~~~~~~~~
// TIC~TAC~TOE
// ~~~~~~~~~~~~~~~
//
// /---+---+---\
// | | | |
// +---+---+---+
// | | | |
// +---+---+---+
// | | | |
// \---+---+---/
}
func ExamplePrintBoardCells() {
cells[0] = player1
cells[4] = player2
cells[8] = player1
printBoard()
// Output:
// ~~~~~~~~~~~~~~~
// TIC~TAC~TOE
// ~~~~~~~~~~~~~~~
//
// /---+---+---\
// | X | | |
// +---+---+---+
// | | O | |
// +---+---+---+
// | | | X |
// \---+---+---/
}

View File

@ -0,0 +1,58 @@
package main
// -------------------------------------------------
// IS THERE A WINNER? OR IS IT A TIE?
// -------------------------------------------------
// /---+---+---\
// | 0 | 1 | 2 |
// +---+---+---+
// | 3 | 4 | 5 |
// +---+---+---+
// | 6 | 7 | 8 |
// \---+---+---/
func checkWinOrTie() {
// intentional bug: tie shouldn't happen before winning detection
// if tie = turn == maxTurns; tie {
// // if tie don't check for the winning
// return
// }
// loop over all the players
for i := 1; i <= 2; i++ {
// check for the next player
p := player2
if i == 1 {
p = player1
}
/* check horizontals */
hor := (cells[0] == p && cells[1] == p && cells[2] == p) ||
(cells[3] == p && cells[4] == p && cells[5] == p) ||
(cells[6] == p && cells[7] == p && cells[8] == p)
/* check verticals */
ver := (cells[0] == p && cells[3] == p && cells[6] == p) ||
(cells[1] == p && cells[4] == p && cells[7] == p) ||
(cells[2] == p && cells[5] == p && cells[8] == p)
/* check diagonals */
diag := (cells[0] == p && cells[4] == p && cells[8] == p) ||
(cells[2] == p && cells[4] == p && cells[6] == p)
// any winner?
if hor || ver || diag {
won = true
// this player wins
player = p
// there is a winner so don't check for tie!
return
}
}
// check for tie
tie = turn == maxTurns
}

View File

@ -0,0 +1,59 @@
package main
import "testing"
func TestWin(t *testing.T) {
// /---+---+---\
// | O | X | X |
// +---+---+---+
// | O | O | X |
// +---+---+---+
// | X | O | X |
// \---+---+---/
cells[0] = player2
cells[1] = player1
cells[2] = player1
cells[3] = player2
cells[4] = player2
cells[5] = player1
cells[6] = player1
cells[7] = player2
cells[8] = player1
turn = maxTurns
if checkWinOrTie(); !won {
t.Errorf("won = %t; want true", won)
}
// TestWin was messing up with the results.
// Test ordering shouldn't be important.
initCells()
}
func TestTie(t *testing.T) {
// /---+---+---\
// | O | X | X |
// +---+---+---+
// | X | O | O |
// +---+---+---+
// | X | O | X |
// \---+---+---/
cells[0] = player2
cells[1] = player1
cells[2] = player1
cells[3] = player1
cells[4] = player2
cells[5] = player2
cells[6] = player1
cells[7] = player2
cells[8] = player1
turn = maxTurns
if checkWinOrTie(); !tie {
t.Errorf("tie = %t; want true", tie)
}
initCells()
}

View File

@ -0,0 +1,37 @@
package main
import (
"fmt"
"math/rand"
"os"
"strconv"
"time"
)
// init is another special function
// Go calls it before the main function
func init() {
rand.Seed(time.Now().UnixNano())
initCells()
}
// initCells initialize the played cells to empty
func initCells() {
for i := range cells {
cells[i] = emptyCell
}
}
func setGameSpeed() {
// args can be used within the if block
// gs and err can be used in the else if and else branches
if args := os.Args; len(args) == 1 {
fmt.Println("Setting game speed to default.")
} else if gs, err := strconv.Atoi(args[1]); err != nil {
fmt.Println("Wrong game speed. Provide an integer.")
} else {
gameSpeed = time.Duration(gs) * time.Second
}
fmt.Printf("Game speed is %q.\n", gameSpeed)
}

View File

@ -0,0 +1,45 @@
package main
import (
"fmt"
"time"
)
/*
~ TICTACTOE GAME IN GO ~
+ This example uses the very basics of the Go language.
+ The goal is learning all the basics.
*/
const (
maxTurns = 9
defaultGameSpeed = time.Second * 2 // time between plays
)
var (
won, tie bool // is there any winner or a tie?
turn int // total valid turns played
cells [maxTurns]cell // used to draw the board: contains the players' moves
lastPos int // last played position
wrongMove bool // was the last move wrong?
player = player1 // current player
gameSpeed = defaultGameSpeed // sets the default game speed
)
// main is only responsible for the game loop, that's it.
func main() {
setGameSpeed()
printBoard()
wait()
for nextTurn() {
wait()
}
}
func wait() {
fmt.Println()
time.Sleep(gameSpeed) // player thinks...
}

View File

@ -0,0 +1,37 @@
package main
import "math/rand"
// play plays the game for the current player.
// + registers the player's move in the board.
// if the move is valid:
// + increases the turn.
func play() {
// pick a random move (very intelligent AI!)
// it can play to the same position!
lastPos = rand.Intn(maxTurns)
// is it a valid move?
if cells[lastPos] != emptyCell {
wrongMove = true
// skip the rest of the function from running
return
}
// register the move: put the player's sign on the board
cells[lastPos] = player
// increment the current turns
turn++
}
// switchPlayer switches to the next player
func switchPlayer() {
// switch the player
if player == player1 {
player = player2
} else {
player = player1
}
}

View File

@ -0,0 +1,26 @@
package main
import "testing"
func TestWrongMove(t *testing.T) {
// /---+---+---\
// | X | X | X |
// +---+---+---+
// | X | X | X |
// +---+---+---+
// | X | X | X |
// \---+---+---/
// fill the board with artificial cells
for i := range cells {
cells[i] = player1
}
// any move beyond this point is wrong.
// reason: every cell is occupied.
if play(); !wrongMove {
t.Errorf("wrongMove = %t; want true", wrongMove)
}
initCells()
}

View File

@ -0,0 +1,19 @@
package main
// cell represents a tictactoe board cell
type cell string
// skin options :-)
const (
banner = `
~~~~~~~~~~~~~~~
TIC~TAC~TOE
~~~~~~~~~~~~~~~`
player1, player2, emptyCell cell = "X", "O", " "
sepHeader = `/---+---+---\`
sepLine = `+---+---+---+`
sepFooter = `\---+---+---/`
sepCell = "|"
)

View File

@ -0,0 +1,45 @@
package main
import "fmt"
// nextTurn prints the board for the next turn and checks for the winning conditions.
// if win or tie: returns false, otherwise true.
func nextTurn() bool {
play()
printBoard()
fmt.Printf("\n>>> PLAYER %q PLAYS to %d\n", player, lastPos+1)
// the switch below is about winning and tie conditions.
// so it is good have checkWinOrTie() as a simple statement.
// totally optional.
switch checkWinOrTie(); {
default:
switchPlayer()
printStatus()
case wrongMove:
fmt.Printf(">>> CELL IS OCCUPIED: PLAY AGAIN!\n")
wrongMove = false // reset for the next turn
case won, tie:
if won {
fmt.Println(">>> WINNER:", player)
} else {
fmt.Println(">>> TIE!")
}
return false
}
return true
}
// printStatus prints the current status of the game
// it cannot access to the names (vars, consts, etc) inside any other func
func printStatus() {
fmt.Println()
progress := (1 - (float64(turn) / maxTurns)) * 100
fmt.Printf("Current Turn : %d\n", turn)
fmt.Printf("Is there a winner : %t\n", won)
fmt.Printf("Turns left : %.1f%%\n", progress)
}