ticktacktoe.go
· 4.6 KiB · Go
Raw
package main
import (
"fmt"
"strconv"
"strings"
)
const (
skipBoardCreation = false
skipUserCreation = false
)
func createBoard(size int) [][]string {
board := make([][]string, size)
for r := 0; r < size; r++ {
rowSlice := make([]string, size)
for i := range rowSlice {
rowSlice[i] = " "
}
board[r] = rowSlice
}
return board
}
func getBoardDimensions(board [][]string) (rows, columns int) {
rows = len(board)
columns = 0
for _, row := range board {
if len(row) > columns {
columns = len(row)
}
}
return
}
func boardToString(board [][]string) string {
maxRowLength := 0
rowStrings := make([]string, len(board)+1)
for i, row := range board {
if len(row) > maxRowLength {
maxRowLength = len(row)
}
rowIndex := strconv.Itoa(i)
if i < 10 {
rowIndex += " "
}
rowStrings[i+1] = rowIndex + strings.Join(row, "|")
}
columnIndices := make([]string, maxRowLength)
for i := 0; i < maxRowLength; i++ {
rowIndex := strconv.Itoa(i)
if i < 10 {
rowIndex = " " + rowIndex
}
columnIndices[i] = rowIndex
}
rowStrings[0] = "/" + strings.Join(columnIndices, "")
return strings.Join(rowStrings, "\n")
}
func createBoardUserInput() [][]string {
var size int
for {
fmt.Print("canvas size? ")
fmt.Scanln(&size)
if size < 100 {
return createBoard(size)
} else {
fmt.Println("There can't be more than 99 rows.")
}
}
}
func createUsersUserInput() []string {
users := []string{}
existingUsers := map[string]bool{}
fmt.Println("Add users to the game. Users are a single alphabetical char.\nIf you're done submit an empty user.")
for {
fmt.Print("new user: ")
var input string
fmt.Scanln(&input)
input = strings.Trim(input, " \n")
if len(input) == 0 {
if len(users) == 0 {
fmt.Println("You need to add at least one user.")
} else {
break
}
}
if len(input) == 1 {
newUser := strings.ToUpper(input)
if _, ok := existingUsers[newUser]; ok {
fmt.Println("This user already exists.")
} else {
existingUsers[newUser] = false
users = append(users, newUser)
}
} else {
fmt.Println("The input can only be one character.")
}
}
return users
}
func changeCellUserInput(board [][]string, user string) {
var row []string
for {
var rowIndex int
fmt.Print("row: ")
fmt.Scanln(&rowIndex)
if 0 <= rowIndex && rowIndex < len(board) {
row = board[rowIndex]
break
} else {
fmt.Println("The value needs to be in the range of the board rows.")
continue
}
}
for {
var colIndex int
fmt.Print("col: ")
fmt.Scanln(&colIndex)
if 0 <= colIndex && colIndex < len(row) {
if row[colIndex] != " " {
fmt.Println("This cell is already occupied.")
defer changeCellUserInput(board, user)
break
}
row[colIndex] = user
break
} else {
fmt.Println("The value needs to be in the range of the board columns.")
continue
}
}
}
func analyzeWin(board [][]string) string {
for r := range board {
didWin := true
firstItem := board[r][0]
for c := range board[r] {
if board[r][c] != firstItem {
didWin = false
break
}
}
if didWin && firstItem != " " {
return firstItem
}
}
for c := range board[0] {
didWin := true
firstItem := board[0][c]
for r := range board {
if board[r][c] != firstItem {
didWin = false
break
}
}
if didWin && firstItem != " " {
return firstItem
}
}
size := len(board)
{
didWin := true
firstItem := board[0][0]
for i := 0; i < size; i++ {
if board[i][i] != firstItem {
didWin = false
break
}
}
if didWin && firstItem != " " {
return firstItem
}
}
{
didWin := true
firstItem := board[0][size-1]
for i := 0; i < size; i++ {
if board[i][size-i-1] != firstItem {
didWin = false
break
}
}
if didWin && firstItem != " " {
return firstItem
}
}
return ""
}
func main() {
var board [][]string
if skipBoardCreation {
board = createBoard(3)
} else {
board = createBoardUserInput()
fmt.Println()
}
var users []string
if skipUserCreation {
users = []string{"X", "O"}
} else {
users = createUsersUserInput()
fmt.Println()
}
printStats := func() {
fmt.Println("Users playing:", strings.Join(users, " "))
rows, columns := getBoardDimensions(board)
fmt.Println("Board Dimension:", rows, columns)
fmt.Println(boardToString(board))
}
currentUser := 0
for {
fmt.Println()
printStats()
didWin := analyzeWin(board)
if didWin != "" {
fmt.Println()
fmt.Println(didWin + " WINS!!")
break
}
fmt.Println()
fmt.Println("it's the turn of " + users[currentUser])
changeCellUserInput(board, users[currentUser])
currentUser = (currentUser + 1) % len(users)
}
}
1 | package main |
2 | |
3 | import ( |
4 | "fmt" |
5 | "strconv" |
6 | "strings" |
7 | ) |
8 | |
9 | const ( |
10 | skipBoardCreation = false |
11 | skipUserCreation = false |
12 | ) |
13 | |
14 | func createBoard(size int) [][]string { |
15 | board := make([][]string, size) |
16 | |
17 | for r := 0; r < size; r++ { |
18 | rowSlice := make([]string, size) |
19 | for i := range rowSlice { |
20 | rowSlice[i] = " " |
21 | } |
22 | |
23 | board[r] = rowSlice |
24 | } |
25 | |
26 | return board |
27 | } |
28 | |
29 | func getBoardDimensions(board [][]string) (rows, columns int) { |
30 | rows = len(board) |
31 | columns = 0 |
32 | |
33 | for _, row := range board { |
34 | if len(row) > columns { |
35 | columns = len(row) |
36 | } |
37 | } |
38 | |
39 | return |
40 | } |
41 | |
42 | func boardToString(board [][]string) string { |
43 | maxRowLength := 0 |
44 | rowStrings := make([]string, len(board)+1) |
45 | for i, row := range board { |
46 | if len(row) > maxRowLength { |
47 | maxRowLength = len(row) |
48 | } |
49 | |
50 | rowIndex := strconv.Itoa(i) |
51 | if i < 10 { |
52 | rowIndex += " " |
53 | } |
54 | rowStrings[i+1] = rowIndex + strings.Join(row, "|") |
55 | } |
56 | |
57 | columnIndices := make([]string, maxRowLength) |
58 | for i := 0; i < maxRowLength; i++ { |
59 | rowIndex := strconv.Itoa(i) |
60 | if i < 10 { |
61 | rowIndex = " " + rowIndex |
62 | } |
63 | columnIndices[i] = rowIndex |
64 | } |
65 | rowStrings[0] = "/" + strings.Join(columnIndices, "") |
66 | |
67 | return strings.Join(rowStrings, "\n") |
68 | } |
69 | |
70 | func createBoardUserInput() [][]string { |
71 | var size int |
72 | for { |
73 | fmt.Print("canvas size? ") |
74 | fmt.Scanln(&size) |
75 | if size < 100 { |
76 | return createBoard(size) |
77 | } else { |
78 | fmt.Println("There can't be more than 99 rows.") |
79 | } |
80 | } |
81 | } |
82 | |
83 | func createUsersUserInput() []string { |
84 | users := []string{} |
85 | existingUsers := map[string]bool{} |
86 | |
87 | fmt.Println("Add users to the game. Users are a single alphabetical char.\nIf you're done submit an empty user.") |
88 | for { |
89 | fmt.Print("new user: ") |
90 | var input string |
91 | fmt.Scanln(&input) |
92 | input = strings.Trim(input, " \n") |
93 | |
94 | if len(input) == 0 { |
95 | if len(users) == 0 { |
96 | fmt.Println("You need to add at least one user.") |
97 | } else { |
98 | break |
99 | } |
100 | } |
101 | |
102 | if len(input) == 1 { |
103 | newUser := strings.ToUpper(input) |
104 | if _, ok := existingUsers[newUser]; ok { |
105 | fmt.Println("This user already exists.") |
106 | } else { |
107 | existingUsers[newUser] = false |
108 | users = append(users, newUser) |
109 | } |
110 | } else { |
111 | fmt.Println("The input can only be one character.") |
112 | } |
113 | } |
114 | return users |
115 | } |
116 | |
117 | func changeCellUserInput(board [][]string, user string) { |
118 | var row []string |
119 | |
120 | for { |
121 | var rowIndex int |
122 | fmt.Print("row: ") |
123 | fmt.Scanln(&rowIndex) |
124 | |
125 | if 0 <= rowIndex && rowIndex < len(board) { |
126 | row = board[rowIndex] |
127 | break |
128 | } else { |
129 | fmt.Println("The value needs to be in the range of the board rows.") |
130 | continue |
131 | } |
132 | } |
133 | |
134 | for { |
135 | var colIndex int |
136 | fmt.Print("col: ") |
137 | fmt.Scanln(&colIndex) |
138 | |
139 | if 0 <= colIndex && colIndex < len(row) { |
140 | if row[colIndex] != " " { |
141 | fmt.Println("This cell is already occupied.") |
142 | defer changeCellUserInput(board, user) |
143 | break |
144 | } |
145 | |
146 | row[colIndex] = user |
147 | break |
148 | } else { |
149 | fmt.Println("The value needs to be in the range of the board columns.") |
150 | continue |
151 | } |
152 | } |
153 | } |
154 | |
155 | func analyzeWin(board [][]string) string { |
156 | for r := range board { |
157 | didWin := true |
158 | firstItem := board[r][0] |
159 | for c := range board[r] { |
160 | if board[r][c] != firstItem { |
161 | didWin = false |
162 | break |
163 | } |
164 | } |
165 | |
166 | if didWin && firstItem != " " { |
167 | return firstItem |
168 | } |
169 | } |
170 | |
171 | for c := range board[0] { |
172 | didWin := true |
173 | firstItem := board[0][c] |
174 | for r := range board { |
175 | if board[r][c] != firstItem { |
176 | didWin = false |
177 | break |
178 | } |
179 | } |
180 | |
181 | if didWin && firstItem != " " { |
182 | return firstItem |
183 | } |
184 | } |
185 | |
186 | size := len(board) |
187 | { |
188 | didWin := true |
189 | firstItem := board[0][0] |
190 | for i := 0; i < size; i++ { |
191 | if board[i][i] != firstItem { |
192 | didWin = false |
193 | break |
194 | } |
195 | } |
196 | |
197 | if didWin && firstItem != " " { |
198 | return firstItem |
199 | } |
200 | } |
201 | |
202 | { |
203 | didWin := true |
204 | firstItem := board[0][size-1] |
205 | for i := 0; i < size; i++ { |
206 | if board[i][size-i-1] != firstItem { |
207 | didWin = false |
208 | break |
209 | } |
210 | } |
211 | |
212 | if didWin && firstItem != " " { |
213 | return firstItem |
214 | } |
215 | } |
216 | |
217 | return "" |
218 | } |
219 | |
220 | func main() { |
221 | var board [][]string |
222 | if skipBoardCreation { |
223 | board = createBoard(3) |
224 | } else { |
225 | board = createBoardUserInput() |
226 | fmt.Println() |
227 | } |
228 | |
229 | var users []string |
230 | if skipUserCreation { |
231 | users = []string{"X", "O"} |
232 | } else { |
233 | users = createUsersUserInput() |
234 | fmt.Println() |
235 | } |
236 | |
237 | printStats := func() { |
238 | fmt.Println("Users playing:", strings.Join(users, " ")) |
239 | rows, columns := getBoardDimensions(board) |
240 | fmt.Println("Board Dimension:", rows, columns) |
241 | fmt.Println(boardToString(board)) |
242 | } |
243 | |
244 | currentUser := 0 |
245 | for { |
246 | fmt.Println() |
247 | printStats() |
248 | |
249 | didWin := analyzeWin(board) |
250 | if didWin != "" { |
251 | fmt.Println() |
252 | fmt.Println(didWin + " WINS!!") |
253 | break |
254 | } |
255 | |
256 | fmt.Println() |
257 | fmt.Println("it's the turn of " + users[currentUser]) |
258 | changeCellUserInput(board, users[currentUser]) |
259 | currentUser = (currentUser + 1) % len(users) |
260 | } |
261 | } |
262 |