-
Notifications
You must be signed in to change notification settings - Fork 0
/
ttt.go
135 lines (124 loc) · 2.58 KB
/
ttt.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
package main
import (
"bufio"
"errors"
"fmt"
"os"
"regexp"
"strings"
)
type PlayField struct {
Player int
Board [][]string
}
func NewPlayField() (pf *PlayField) {
pf = &PlayField{
Player: 1,
Board: [][]string{
{"1", "2", "3"},
{"4", "5", "6"},
{"7", "8", "9"},
},
}
return pf
}
func (pf *PlayField) printBoard() {
fmt.Println()
fmt.Println("-------")
for _, row := range pf.Board {
fmt.Printf("|%s|%s|%s|\n", row[0], row[1], row[2])
fmt.Println("-------")
}
}
func (pf *PlayField) makePlay(pos string) error {
for i, row := range pf.Board {
for j := range row {
if pf.Board[i][j] == pos {
if pf.Player == 1 {
pf.Board[i][j] = "X"
return nil
}
pf.Board[i][j] = "O"
return nil
}
}
}
return fmt.Errorf("%s is not a legal play", pos)
}
func (pf *PlayField) takeTurn(r *bufio.Reader) (winner bool, err error) {
pf.printBoard()
fmt.Printf("Ready player %d!\n", pf.Player)
fmt.Print("> ")
text, _ := r.ReadString('\n')
text = strings.TrimSpace(text)
err = pf.makePlay(text)
if err != nil {
return false, nil
}
winner, err = pf.checkForWinner()
if err != nil {
return false, err
}
if winner {
return true, nil
}
if pf.Player == 1 {
pf.Player = 2
return false, nil
}
pf.Player = 1
return false, nil
}
func (pf *PlayField) checkForWinner() (winner bool, err error) {
var rows string
var cols string
var diags string
for i, row := range pf.Board {
for j := range row {
rows = rows + pf.Board[i][j]
cols = cols + pf.Board[j][i]
}
rows = rows + ","
cols = cols + ","
}
diags = diags + pf.Board[0][0] + pf.Board[1][1] + pf.Board[2][2] + ","
diags = diags + pf.Board[0][2] + pf.Board[1][1] + pf.Board[2][0]
if strings.Contains(rows, "XXX") || strings.Contains(rows, "OOO") {
return true, nil
}
if strings.Contains(cols, "XXX") || strings.Contains(cols, "OOO") {
return true, nil
}
if strings.Contains(diags, "XXX") || strings.Contains(diags, "OOO") {
return true, nil
}
all := rows + cols
re := regexp.MustCompile("[0-9]+")
if re.MatchString(all) {
return false, nil
}
return false, errors.New("no moves left")
}
func ticTacToe() {
pf := NewPlayField()
r := bufio.NewReader(os.Stdin)
for {
winner, err := pf.takeTurn(r)
if err != nil {
fmt.Println("No more moves remaining, starting new game!")
pf = NewPlayField()
}
if winner {
pf.printBoard()
fmt.Printf("Player %d won!\n", pf.Player)
fmt.Println("Enter p to play again, anything else to quit")
t, _ := r.ReadString('\n')
t = strings.TrimSpace(t)
if t == "p" {
pf = NewPlayField()
} else {
return
}
}
}
}