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 |