This is a tic-tac-toe game.
To run the game go run main.go
| package main | |
| import ( | |
| "fmt" | |
| "strconv" | |
| "strings" | |
| ) | |
| func main() { | |
| fmt.Println("\nPlease input a number that will be the length of the tic tac toe board(the rows and columns will be zero indexed):") | |
| var n int | |
| fmt.Scan(&n) | |
| board := make([][]int, n) | |
| for i := 0; i < n; i++ { | |
| board[i] = make([]int, n) | |
| } | |
| m := map[[2]int]int{} | |
| lastMoveX, lastMoveY := 0, 0 | |
| count := 0 | |
| for { | |
| printBoard(board, "-") | |
| if ifGameDone(board, lastMoveX, lastMoveY, count, n) { | |
| break | |
| } | |
| fmt.Println("Player 1, input your row and column you want to place your token on (ie. \"0 0\"):") | |
| x, y := 0, 0 | |
| fmt.Scan(&y, &x) | |
| if x >= n || x < 0 || y >= n || y < 0 || m[[2]int{x, y}] > 0 { | |
| fmt.Println("That is an invalid action, this turn has been skipped") | |
| } else { | |
| board[y][x] = 1 | |
| printBoard(board, "-") | |
| m[[2]int{x, y}] = 1 | |
| lastMoveX, lastMoveY = x, y | |
| count++ | |
| } | |
| if ifGameDone(board, lastMoveX, lastMoveY, count, n) { | |
| break | |
| } | |
| fmt.Println("Player 2, input your row and column you want to place your token on (ie. \"0 0\"):") | |
| x1, y1 := 0, 0 | |
| fmt.Scan(&y1, &x1) | |
| if x1 >= n || x1 < 0 || y1 >= n || y1 < 0 || m[[2]int{x1, y1}] > 0 { | |
| fmt.Println("That is an invalid action, this turn has been skipped") | |
| } else { | |
| board[y1][x1] = 2 | |
| lastMoveX, lastMoveY = x1, y1 | |
| m[[2]int{x1, y1}] = 1 | |
| count++ | |
| } | |
| } | |
| } | |
| // ifGameDone checks if the game is done | |
| func ifGameDone(board [][]int, lastMoveX int, lastMoveY int, count int, n int) bool { | |
| if solved, winner := checkWinner(board, lastMoveX, lastMoveY); solved { | |
| fmt.Println("Player " + strconv.Itoa(winner) + " is the winner") | |
| return true | |
| } | |
| if count == n*n { | |
| fmt.Println("Its a draw!") | |
| return true | |
| } | |
| return false | |
| } | |
| // printBoard prints the board | |
| func printBoard(board [][]int, line string) { | |
| for _, i := range board { | |
| s := "" | |
| line = "-" | |
| for _, j := range i { | |
| line += strings.Repeat("-", 4) | |
| if j == 1 { | |
| s += " | X" | |
| } | |
| if j == 2 { | |
| s += " | O" | |
| } | |
| if j == 0 { | |
| s += " | " | |
| } | |
| } | |
| fmt.Println(line) | |
| fmt.Println(s[1:] + " |") | |
| } | |
| fmt.Println(line) | |
| } | |
| // checkWinner checks if the game is done, and if so outputs the winner. | |
| func checkWinner(board [][]int, lastMoveX, lastMoveY int) (bool, int) { | |
| // check row for winner | |
| first := board[lastMoveY][0] | |
| flag := true | |
| for i := 0; i < len(board); i++ { | |
| if board[lastMoveY][i] != first { | |
| flag = false | |
| break | |
| } | |
| } | |
| if flag && first != 0 { | |
| return true, first | |
| } | |
| // check column for winner | |
| first = board[0][lastMoveX] | |
| flag = true | |
| for i := 0; i < len(board); i++ { | |
| if board[i][lastMoveX] != first { | |
| flag = false | |
| break | |
| } | |
| } | |
| if flag && first != 0 { | |
| return true, first | |
| } | |
| // check diagonal for winner | |
| flag, first = true, board[0][len(board)-1] | |
| for i, j := 0, len(board)-1; i < len(board); i, j = i+1, j-1 { | |
| if board[i][j] != first { | |
| flag = false | |
| break | |
| } | |
| } | |
| if flag && first != 0 { | |
| return true, first | |
| } | |
| // check other diagonal for winner | |
| flag, first = true, board[0][0] | |
| for i, j := 0, 0; i < len(board); i, j = i+1, j+1 { | |
| if board[i][j] != first { | |
| flag = false | |
| break | |
| } | |
| } | |
| if flag && first != 0 { | |
| return true, first | |
| } | |
| return false, 0 | |
| } |
| package main | |
| import "testing" | |
| func Test_checkwinner(t *testing.T) { | |
| type args struct { | |
| board [][]int | |
| lastMoveX int | |
| lastMoveY int | |
| } | |
| tests := []struct { | |
| name string | |
| args args | |
| want bool | |
| want1 int | |
| }{ | |
| { | |
| // create test | |
| name: "emptyBoard", | |
| args: args{ | |
| board: [][]int{ | |
| {0, 0, 0}, | |
| {0, 0, 0}, | |
| {0, 0, 0}, | |
| }, | |
| lastMoveX: 0, | |
| lastMoveY: 0, | |
| }, | |
| want: false, | |
| want1: 0, | |
| }, | |
| { | |
| // create test | |
| name: "fullBoard- row winner", | |
| args: args{ | |
| board: [][]int{ | |
| {1, 2, 2}, | |
| {1, 1, 1}, | |
| {2, 1, 1}, | |
| }, | |
| lastMoveX: 0, | |
| lastMoveY: 1, | |
| }, | |
| want: true, | |
| want1: 1, | |
| }, | |
| { | |
| // create test | |
| name: "fullBoard- column winner", | |
| args: args{ | |
| board: [][]int{ | |
| {1, 2, 2}, | |
| {1, 2, 1}, | |
| {1, 1, 2}, | |
| }, | |
| lastMoveX: 0, | |
| lastMoveY: 0, | |
| }, | |
| want: true, | |
| want1: 1, | |
| }, | |
| { | |
| // create test | |
| name: "fullBoard- no winner", | |
| args: args{ | |
| board: [][]int{ | |
| {1, 2, 1}, | |
| {1, 2, 1}, | |
| {2, 1, 2}, | |
| }, | |
| lastMoveX: 0, | |
| lastMoveY: 0, | |
| }, | |
| want: false, | |
| want1: 0, | |
| }, | |
| { | |
| // create test | |
| name: "fullBoard- diagonal winner", | |
| args: args{ | |
| board: [][]int{ | |
| {2, 2, 1}, | |
| {1, 2, 1}, | |
| {2, 1, 2}, | |
| }, | |
| lastMoveX: 0, | |
| lastMoveY: 0, | |
| }, | |
| want: true, | |
| want1: 2, | |
| }, | |
| { | |
| // create test | |
| name: "fullBoard- other diagonal winner", | |
| args: args{ | |
| board: [][]int{ | |
| {2, 2, 1}, | |
| {2, 1, 1}, | |
| {1, 1, 2}, | |
| }, | |
| lastMoveX: 0, | |
| lastMoveY: 2, | |
| }, | |
| want: true, | |
| want1: 1, | |
| }, | |
| } | |
| for _, tt := range tests { | |
| t.Run(tt.name, func(t *testing.T) { | |
| got, got1 := checkWinner(tt.args.board, tt.args.lastMoveX, tt.args.lastMoveY) | |
| if got != tt.want { | |
| t.Errorf("checkWinner() got = %v, want %v", got, tt.want) | |
| } | |
| if got1 != tt.want1 { | |
| t.Errorf("checkWinner() got1 = %v, want %v", got1, tt.want1) | |
| } | |
| }) | |
| } | |
| } |