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:
51
x-tba/foundations/02-variables/types/main.go
Normal file
51
x-tba/foundations/02-variables/types/main.go
Normal 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)
|
||||||
|
}
|
@ -36,12 +36,12 @@ main:
|
|||||||
|
|
||||||
switch {
|
switch {
|
||||||
// prime
|
// prime
|
||||||
case n == 2 || n == 3:
|
case n == 2, n == 3:
|
||||||
fmt.Print(n, " ")
|
fmt.Print(n, " ")
|
||||||
continue
|
continue
|
||||||
|
|
||||||
// not a prime
|
// not a prime
|
||||||
case n <= 1 || n%2 == 0 || n%3 == 0:
|
case n <= 1, n%2 == 0, n%3 == 0:
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@ -7,6 +14,26 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
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 _
|
// lesson: multi-return funcs, %v, and _
|
||||||
|
|
||||||
a, _ := strconv.Atoi(os.Args[1])
|
a, _ := strconv.Atoi(os.Args[1])
|
||||||
|
@ -7,7 +7,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
// lesson: floats encompass integers too
|
// lesson: len(), floats encompass integers too
|
||||||
|
|
||||||
if len(os.Args) != 3 {
|
if len(os.Args) != 3 {
|
||||||
fmt.Println("Usage: calc <number1> <number2>")
|
fmt.Println("Usage: calc <number1> <number2>")
|
||||||
|
@ -26,5 +26,12 @@ func main() {
|
|||||||
return
|
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)
|
fmt.Printf("%v + %v = %v\n", a, b, a+b)
|
||||||
}
|
}
|
||||||
|
@ -26,7 +26,9 @@ func main() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// multiple declare
|
||||||
var (
|
var (
|
||||||
|
// declare & assign
|
||||||
op = os.Args[2]
|
op = os.Args[2]
|
||||||
res float64
|
res float64
|
||||||
)
|
)
|
||||||
|
70
x-tba/foundations/lookup/main.go
Normal file
70
x-tba/foundations/lookup/main.go
Normal 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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
42
x-tba/swapi-api-client/fetch/main.go
Normal file
42
x-tba/swapi-api-client/fetch/main.go
Normal 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)
|
||||||
|
}
|
149
x-tba/tictactoe-experiments/00-without-bufio/main.go
Normal file
149
x-tba/tictactoe-experiments/00-without-bufio/main.go
Normal 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)
|
||||||
|
}
|
||||||
|
}
|
50
x-tba/tictactoe/00-print/main.go
Normal file
50
x-tba/tictactoe/00-print/main.go
Normal 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 |
|
||||||
|
\---+---+---/`)
|
||||||
|
}
|
96
x-tba/tictactoe/01-vars/main.go
Normal file
96
x-tba/tictactoe/01-vars/main.go
Normal 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)
|
||||||
|
}
|
33
x-tba/tictactoe/02-short-decl/main.go
Normal file
33
x-tba/tictactoe/02-short-decl/main.go
Normal 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)
|
||||||
|
}
|
71
x-tba/tictactoe/03-consts/main.go
Normal file
71
x-tba/tictactoe/03-consts/main.go
Normal 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)
|
||||||
|
}
|
52
x-tba/tictactoe/04-funcs/main.go
Normal file
52
x-tba/tictactoe/04-funcs/main.go
Normal 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)
|
||||||
|
}
|
23
x-tba/tictactoe/05-testing/board_test.go
Normal file
23
x-tba/tictactoe/05-testing/board_test.go
Normal 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
|
||||||
|
//
|
||||||
|
// /---+---+---\
|
||||||
|
// | | | |
|
||||||
|
// +---+---+---+
|
||||||
|
// | | | |
|
||||||
|
// +---+---+---+
|
||||||
|
// | | | |
|
||||||
|
// \---+---+---/
|
||||||
|
}
|
52
x-tba/tictactoe/05-testing/main.go
Normal file
52
x-tba/tictactoe/05-testing/main.go
Normal 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)
|
||||||
|
}
|
23
x-tba/tictactoe/06-if-switch/board_test.go
Normal file
23
x-tba/tictactoe/06-if-switch/board_test.go
Normal 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
|
||||||
|
//
|
||||||
|
// /---+---+---\
|
||||||
|
// | | | |
|
||||||
|
// +---+---+---+
|
||||||
|
// | | | |
|
||||||
|
// +---+---+---+
|
||||||
|
// | | | |
|
||||||
|
// \---+---+---/
|
||||||
|
}
|
87
x-tba/tictactoe/06-if-switch/main.go
Normal file
87
x-tba/tictactoe/06-if-switch/main.go
Normal 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)
|
||||||
|
}
|
54
x-tba/tictactoe/07-loop/board.go
Normal file
54
x-tba/tictactoe/07-loop/board.go
Normal 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)
|
||||||
|
}
|
25
x-tba/tictactoe/07-loop/board_test.go
Normal file
25
x-tba/tictactoe/07-loop/board_test.go
Normal 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 |
|
||||||
|
// \---+---+---/
|
||||||
|
}
|
61
x-tba/tictactoe/07-loop/main.go
Normal file
61
x-tba/tictactoe/07-loop/main.go
Normal 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
|
||||||
|
}
|
||||||
|
}
|
25
x-tba/tictactoe/07-loop/skin.go
Normal file
25
x-tba/tictactoe/07-loop/skin.go
Normal 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 = "║"
|
||||||
|
*/
|
||||||
|
)
|
37
x-tba/tictactoe/08-multi-loop/board.go
Normal file
37
x-tba/tictactoe/08-multi-loop/board.go
Normal 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)
|
||||||
|
}
|
25
x-tba/tictactoe/08-multi-loop/board_test.go
Normal file
25
x-tba/tictactoe/08-multi-loop/board_test.go
Normal 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 |
|
||||||
|
// \---+---+---/
|
||||||
|
}
|
62
x-tba/tictactoe/08-multi-loop/main.go
Normal file
62
x-tba/tictactoe/08-multi-loop/main.go
Normal 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
|
||||||
|
}
|
||||||
|
}
|
16
x-tba/tictactoe/08-multi-loop/skin.go
Normal file
16
x-tba/tictactoe/08-multi-loop/skin.go
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
const (
|
||||||
|
banner = `
|
||||||
|
~~~~~~~~~~~~~~~
|
||||||
|
TIC~TAC~TOE
|
||||||
|
~~~~~~~~~~~~~~~`
|
||||||
|
|
||||||
|
// skin options :-)
|
||||||
|
player1, player2 = "X", "O"
|
||||||
|
|
||||||
|
sepHeader = `/---+---+---\`
|
||||||
|
sepLine = `+---+---+---+`
|
||||||
|
sepFooter = `\---+---+---/`
|
||||||
|
sepCell = "|"
|
||||||
|
)
|
26
x-tba/tictactoe/09-slices/board.go
Normal file
26
x-tba/tictactoe/09-slices/board.go
Normal 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)
|
||||||
|
}
|
44
x-tba/tictactoe/09-slices/board_test.go
Normal file
44
x-tba/tictactoe/09-slices/board_test.go
Normal 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 |
|
||||||
|
// \---+---+---/
|
||||||
|
}
|
33
x-tba/tictactoe/09-slices/init.go
Normal file
33
x-tba/tictactoe/09-slices/init.go
Normal 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
|
||||||
|
}
|
||||||
|
}
|
55
x-tba/tictactoe/09-slices/main.go
Normal file
55
x-tba/tictactoe/09-slices/main.go
Normal 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)
|
||||||
|
}
|
||||||
|
}
|
38
x-tba/tictactoe/09-slices/play.go
Normal file
38
x-tba/tictactoe/09-slices/play.go
Normal 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
|
||||||
|
}
|
||||||
|
}
|
17
x-tba/tictactoe/09-slices/skin.go
Normal file
17
x-tba/tictactoe/09-slices/skin.go
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
const (
|
||||||
|
banner = `
|
||||||
|
~~~~~~~~~~~~~~~
|
||||||
|
TIC~TAC~TOE
|
||||||
|
~~~~~~~~~~~~~~~`
|
||||||
|
|
||||||
|
// skin options :-)
|
||||||
|
player1, player2 = "X", "O"
|
||||||
|
emptyCell = " "
|
||||||
|
|
||||||
|
sepHeader = `/---+---+---\`
|
||||||
|
sepLine = `+---+---+---+`
|
||||||
|
sepFooter = `\---+---+---/`
|
||||||
|
sepCell = "|"
|
||||||
|
)
|
26
x-tba/tictactoe/10-arrays/board.go
Normal file
26
x-tba/tictactoe/10-arrays/board.go
Normal 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)
|
||||||
|
}
|
44
x-tba/tictactoe/10-arrays/board_test.go
Normal file
44
x-tba/tictactoe/10-arrays/board_test.go
Normal 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 |
|
||||||
|
// \---+---+---/
|
||||||
|
}
|
8
x-tba/tictactoe/10-arrays/init.go
Normal file
8
x-tba/tictactoe/10-arrays/init.go
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
// initCells initialize the played cells to empty
|
||||||
|
func initCells() {
|
||||||
|
for i := range cells {
|
||||||
|
cells[i] = emptyCell
|
||||||
|
}
|
||||||
|
}
|
55
x-tba/tictactoe/10-arrays/main.go
Normal file
55
x-tba/tictactoe/10-arrays/main.go
Normal 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)
|
||||||
|
}
|
||||||
|
}
|
38
x-tba/tictactoe/10-arrays/play.go
Normal file
38
x-tba/tictactoe/10-arrays/play.go
Normal 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
|
||||||
|
}
|
||||||
|
}
|
17
x-tba/tictactoe/10-arrays/skin.go
Normal file
17
x-tba/tictactoe/10-arrays/skin.go
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
const (
|
||||||
|
banner = `
|
||||||
|
~~~~~~~~~~~~~~~
|
||||||
|
TIC~TAC~TOE
|
||||||
|
~~~~~~~~~~~~~~~`
|
||||||
|
|
||||||
|
// skin options :-)
|
||||||
|
player1, player2 = "X", "O"
|
||||||
|
emptyCell = " "
|
||||||
|
|
||||||
|
sepHeader = `/---+---+---\`
|
||||||
|
sepLine = `+---+---+---+`
|
||||||
|
sepFooter = `\---+---+---/`
|
||||||
|
sepCell = "|"
|
||||||
|
)
|
26
x-tba/tictactoe/11-randomization/board.go
Normal file
26
x-tba/tictactoe/11-randomization/board.go
Normal 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)
|
||||||
|
}
|
41
x-tba/tictactoe/11-randomization/board_test.go
Normal file
41
x-tba/tictactoe/11-randomization/board_test.go
Normal 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 |
|
||||||
|
// \---+---+---/
|
||||||
|
}
|
20
x-tba/tictactoe/11-randomization/init.go
Normal file
20
x-tba/tictactoe/11-randomization/init.go
Normal 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
|
||||||
|
}
|
||||||
|
}
|
69
x-tba/tictactoe/11-randomization/main.go
Normal file
69
x-tba/tictactoe/11-randomization/main.go
Normal 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!")
|
||||||
|
}
|
||||||
|
}
|
48
x-tba/tictactoe/11-randomization/play.go
Normal file
48
x-tba/tictactoe/11-randomization/play.go
Normal 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
|
||||||
|
}
|
||||||
|
}
|
17
x-tba/tictactoe/11-randomization/skin.go
Normal file
17
x-tba/tictactoe/11-randomization/skin.go
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
const (
|
||||||
|
banner = `
|
||||||
|
~~~~~~~~~~~~~~~
|
||||||
|
TIC~TAC~TOE
|
||||||
|
~~~~~~~~~~~~~~~`
|
||||||
|
|
||||||
|
// skin options :-)
|
||||||
|
player1, player2 = "X", "O"
|
||||||
|
emptyCell = " "
|
||||||
|
|
||||||
|
sepHeader = `/---+---+---\`
|
||||||
|
sepLine = `+---+---+---+`
|
||||||
|
sepFooter = `\---+---+---/`
|
||||||
|
sepCell = "|"
|
||||||
|
)
|
26
x-tba/tictactoe/12-infinite-loop/board.go
Normal file
26
x-tba/tictactoe/12-infinite-loop/board.go
Normal 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)
|
||||||
|
}
|
41
x-tba/tictactoe/12-infinite-loop/board_test.go
Normal file
41
x-tba/tictactoe/12-infinite-loop/board_test.go
Normal 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 |
|
||||||
|
// \---+---+---/
|
||||||
|
}
|
20
x-tba/tictactoe/12-infinite-loop/init.go
Normal file
20
x-tba/tictactoe/12-infinite-loop/init.go
Normal 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
|
||||||
|
}
|
||||||
|
}
|
74
x-tba/tictactoe/12-infinite-loop/main.go
Normal file
74
x-tba/tictactoe/12-infinite-loop/main.go
Normal 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)
|
||||||
|
}
|
48
x-tba/tictactoe/12-infinite-loop/play.go
Normal file
48
x-tba/tictactoe/12-infinite-loop/play.go
Normal 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
|
||||||
|
}
|
||||||
|
}
|
17
x-tba/tictactoe/12-infinite-loop/skin.go
Normal file
17
x-tba/tictactoe/12-infinite-loop/skin.go
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
const (
|
||||||
|
banner = `
|
||||||
|
~~~~~~~~~~~~~~~
|
||||||
|
TIC~TAC~TOE
|
||||||
|
~~~~~~~~~~~~~~~`
|
||||||
|
|
||||||
|
// skin options :-)
|
||||||
|
player1, player2 = "X", "O"
|
||||||
|
emptyCell = " "
|
||||||
|
|
||||||
|
sepHeader = `/---+---+---\`
|
||||||
|
sepLine = `+---+---+---+`
|
||||||
|
sepFooter = `\---+---+---/`
|
||||||
|
sepCell = "|"
|
||||||
|
)
|
26
x-tba/tictactoe/13-detect-winning/board.go
Normal file
26
x-tba/tictactoe/13-detect-winning/board.go
Normal 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)
|
||||||
|
}
|
41
x-tba/tictactoe/13-detect-winning/board_test.go
Normal file
41
x-tba/tictactoe/13-detect-winning/board_test.go
Normal 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 |
|
||||||
|
// \---+---+---/
|
||||||
|
}
|
55
x-tba/tictactoe/13-detect-winning/ending.go
Normal file
55
x-tba/tictactoe/13-detect-winning/ending.go
Normal 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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
20
x-tba/tictactoe/13-detect-winning/init.go
Normal file
20
x-tba/tictactoe/13-detect-winning/init.go
Normal 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
|
||||||
|
}
|
||||||
|
}
|
124
x-tba/tictactoe/13-detect-winning/main.go
Normal file
124
x-tba/tictactoe/13-detect-winning/main.go
Normal 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)
|
||||||
|
}
|
37
x-tba/tictactoe/13-detect-winning/play.go
Normal file
37
x-tba/tictactoe/13-detect-winning/play.go
Normal 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
|
||||||
|
}
|
||||||
|
}
|
17
x-tba/tictactoe/13-detect-winning/skin.go
Normal file
17
x-tba/tictactoe/13-detect-winning/skin.go
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
const (
|
||||||
|
banner = `
|
||||||
|
~~~~~~~~~~~~~~~
|
||||||
|
TIC~TAC~TOE
|
||||||
|
~~~~~~~~~~~~~~~`
|
||||||
|
|
||||||
|
// skin options :-)
|
||||||
|
player1, player2 = "X", "O"
|
||||||
|
emptyCell = " "
|
||||||
|
|
||||||
|
sepHeader = `/---+---+---\`
|
||||||
|
sepLine = `+---+---+---+`
|
||||||
|
sepFooter = `\---+---+---/`
|
||||||
|
sepCell = "|"
|
||||||
|
)
|
26
x-tba/tictactoe/14-more-tests/board.go
Normal file
26
x-tba/tictactoe/14-more-tests/board.go
Normal 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)
|
||||||
|
}
|
41
x-tba/tictactoe/14-more-tests/board_test.go
Normal file
41
x-tba/tictactoe/14-more-tests/board_test.go
Normal 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 |
|
||||||
|
// \---+---+---/
|
||||||
|
}
|
58
x-tba/tictactoe/14-more-tests/ending.go
Normal file
58
x-tba/tictactoe/14-more-tests/ending.go
Normal 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
|
||||||
|
}
|
59
x-tba/tictactoe/14-more-tests/ending_test.go
Normal file
59
x-tba/tictactoe/14-more-tests/ending_test.go
Normal 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()
|
||||||
|
}
|
20
x-tba/tictactoe/14-more-tests/init.go
Normal file
20
x-tba/tictactoe/14-more-tests/init.go
Normal 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
|
||||||
|
}
|
||||||
|
}
|
78
x-tba/tictactoe/14-more-tests/main.go
Normal file
78
x-tba/tictactoe/14-more-tests/main.go
Normal 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)
|
||||||
|
}
|
37
x-tba/tictactoe/14-more-tests/play.go
Normal file
37
x-tba/tictactoe/14-more-tests/play.go
Normal 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
|
||||||
|
}
|
||||||
|
}
|
26
x-tba/tictactoe/14-more-tests/play_test.go
Normal file
26
x-tba/tictactoe/14-more-tests/play_test.go
Normal 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()
|
||||||
|
}
|
17
x-tba/tictactoe/14-more-tests/skin.go
Normal file
17
x-tba/tictactoe/14-more-tests/skin.go
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
const (
|
||||||
|
banner = `
|
||||||
|
~~~~~~~~~~~~~~~
|
||||||
|
TIC~TAC~TOE
|
||||||
|
~~~~~~~~~~~~~~~`
|
||||||
|
|
||||||
|
// skin options :-)
|
||||||
|
player1, player2 = "X", "O"
|
||||||
|
emptyCell = " "
|
||||||
|
|
||||||
|
sepHeader = `/---+---+---\`
|
||||||
|
sepLine = `+---+---+---+`
|
||||||
|
sepFooter = `\---+---+---/`
|
||||||
|
sepCell = "|"
|
||||||
|
)
|
26
x-tba/tictactoe/15-os-args/board.go
Normal file
26
x-tba/tictactoe/15-os-args/board.go
Normal 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)
|
||||||
|
}
|
41
x-tba/tictactoe/15-os-args/board_test.go
Normal file
41
x-tba/tictactoe/15-os-args/board_test.go
Normal 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 |
|
||||||
|
// \---+---+---/
|
||||||
|
}
|
58
x-tba/tictactoe/15-os-args/ending.go
Normal file
58
x-tba/tictactoe/15-os-args/ending.go
Normal 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
|
||||||
|
}
|
59
x-tba/tictactoe/15-os-args/ending_test.go
Normal file
59
x-tba/tictactoe/15-os-args/ending_test.go
Normal 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()
|
||||||
|
}
|
37
x-tba/tictactoe/15-os-args/init.go
Normal file
37
x-tba/tictactoe/15-os-args/init.go
Normal 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)
|
||||||
|
}
|
45
x-tba/tictactoe/15-os-args/main.go
Normal file
45
x-tba/tictactoe/15-os-args/main.go
Normal 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...
|
||||||
|
}
|
37
x-tba/tictactoe/15-os-args/play.go
Normal file
37
x-tba/tictactoe/15-os-args/play.go
Normal 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
|
||||||
|
}
|
||||||
|
}
|
26
x-tba/tictactoe/15-os-args/play_test.go
Normal file
26
x-tba/tictactoe/15-os-args/play_test.go
Normal 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()
|
||||||
|
}
|
17
x-tba/tictactoe/15-os-args/skin.go
Normal file
17
x-tba/tictactoe/15-os-args/skin.go
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
const (
|
||||||
|
banner = `
|
||||||
|
~~~~~~~~~~~~~~~
|
||||||
|
TIC~TAC~TOE
|
||||||
|
~~~~~~~~~~~~~~~`
|
||||||
|
|
||||||
|
// skin options :-)
|
||||||
|
player1, player2 = "X", "O"
|
||||||
|
emptyCell = " "
|
||||||
|
|
||||||
|
sepHeader = `/---+---+---\`
|
||||||
|
sepLine = `+---+---+---+`
|
||||||
|
sepFooter = `\---+---+---/`
|
||||||
|
sepCell = "|"
|
||||||
|
)
|
45
x-tba/tictactoe/15-os-args/turn.go
Normal file
45
x-tba/tictactoe/15-os-args/turn.go
Normal 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)
|
||||||
|
}
|
26
x-tba/tictactoe/16-types/board.go
Normal file
26
x-tba/tictactoe/16-types/board.go
Normal 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)
|
||||||
|
}
|
41
x-tba/tictactoe/16-types/board_test.go
Normal file
41
x-tba/tictactoe/16-types/board_test.go
Normal 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 |
|
||||||
|
// \---+---+---/
|
||||||
|
}
|
58
x-tba/tictactoe/16-types/ending.go
Normal file
58
x-tba/tictactoe/16-types/ending.go
Normal 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
|
||||||
|
}
|
59
x-tba/tictactoe/16-types/ending_test.go
Normal file
59
x-tba/tictactoe/16-types/ending_test.go
Normal 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()
|
||||||
|
}
|
37
x-tba/tictactoe/16-types/init.go
Normal file
37
x-tba/tictactoe/16-types/init.go
Normal 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)
|
||||||
|
}
|
45
x-tba/tictactoe/16-types/main.go
Normal file
45
x-tba/tictactoe/16-types/main.go
Normal 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...
|
||||||
|
}
|
37
x-tba/tictactoe/16-types/play.go
Normal file
37
x-tba/tictactoe/16-types/play.go
Normal 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
|
||||||
|
}
|
||||||
|
}
|
26
x-tba/tictactoe/16-types/play_test.go
Normal file
26
x-tba/tictactoe/16-types/play_test.go
Normal 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()
|
||||||
|
}
|
19
x-tba/tictactoe/16-types/skin.go
Normal file
19
x-tba/tictactoe/16-types/skin.go
Normal 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 = "|"
|
||||||
|
)
|
45
x-tba/tictactoe/16-types/turn.go
Normal file
45
x-tba/tictactoe/16-types/turn.go
Normal 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)
|
||||||
|
}
|
Reference in New Issue
Block a user