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 {
|
||||
// prime
|
||||
case n == 2 || n == 3:
|
||||
case n == 2, n == 3:
|
||||
fmt.Print(n, " ")
|
||||
continue
|
||||
|
||||
// not a prime
|
||||
case n <= 1 || n%2 == 0 || n%3 == 0:
|
||||
case n <= 1, n%2 == 0, n%3 == 0:
|
||||
continue
|
||||
}
|
||||
|
||||
|
@ -1,3 +1,10 @@
|
||||
// For more tutorials: https://blog.learngoprogramming.com
|
||||
//
|
||||
// Copyright © 2018 Inanc Gumus
|
||||
// Learn Go Programming Course
|
||||
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
|
||||
//
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
@ -7,6 +14,26 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
// 1.
|
||||
// var a int
|
||||
// var b int
|
||||
|
||||
// 2.
|
||||
// var (
|
||||
// a int
|
||||
// b int
|
||||
// )
|
||||
|
||||
// 3.
|
||||
// var a, b int
|
||||
|
||||
// 1.
|
||||
// fmt.Println(a, "+", b, "=", a+b)
|
||||
|
||||
// 2.
|
||||
// fmt.Printf("%v + %v = %v\n", a, b, a+b)
|
||||
|
||||
// ----
|
||||
// lesson: multi-return funcs, %v, and _
|
||||
|
||||
a, _ := strconv.Atoi(os.Args[1])
|
||||
|
@ -7,7 +7,7 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
// lesson: floats encompass integers too
|
||||
// lesson: len(), floats encompass integers too
|
||||
|
||||
if len(os.Args) != 3 {
|
||||
fmt.Println("Usage: calc <number1> <number2>")
|
||||
|
@ -26,5 +26,12 @@ func main() {
|
||||
return
|
||||
}
|
||||
|
||||
// err1 := ...
|
||||
// err2 := ...
|
||||
// if err1 != nil || err2 != nil {
|
||||
// fmt.Println("Please provide a valid number")
|
||||
// return
|
||||
// }
|
||||
|
||||
fmt.Printf("%v + %v = %v\n", a, b, a+b)
|
||||
}
|
||||
|
@ -26,7 +26,9 @@ func main() {
|
||||
return
|
||||
}
|
||||
|
||||
// multiple declare
|
||||
var (
|
||||
// declare & assign
|
||||
op = os.Args[2]
|
||||
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