ticktacktoe.go
                        
                             · 4.6 KiB · Go
                        
                    
                    
                      
                        Bruto
                      
                      
                        
                          
                        
                    
                    
                
                
            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 |