Skip to content

Instantly share code, notes, and snippets.

@anotherjesse
Created April 5, 2024 21:37
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save anotherjesse/4403e14ef66c5ea2e96616d40b1718e6 to your computer and use it in GitHub Desktop.
Save anotherjesse/4403e14ef66c5ea2e96616d40b1718e6 to your computer and use it in GitHub Desktop.
package main
import (
"fmt"
"math/rand"
"os"
"os/signal"
)
const (
rows = 6
columns = 7
)
type Game struct {
board [rows][columns]int // 0 for empty, 1 for player 1, 2 for player 2
turn int // 1 or 2
moves string
}
func (g *Game) play() {
columns := []int{1, 2, 3, 4, 5, 6, 7}
// Shuffle the slice
rand.Shuffle(len(columns), func(i, j int) {
columns[i], columns[j] = columns[j], columns[i]
})
// Iterate over the columns in random order
for _, c := range columns {
if g.canPlayColumn(c) {
g.makeMove(c)
if g.checkWin() {
fmt.Println(g.moves + "8") // Win
return
} else if g.isFull() {
fmt.Println(g.moves + "9") // Tie / Board full
return
} else {
g.play()
g.undoMove(c)
}
}
}
}
func (g *Game) canPlayColumn(column int) bool {
for r := 0; r < rows; r++ {
if g.board[r][column-1] == 0 {
return true
}
}
return false
}
func (g *Game) makeMove(column int) {
for r := rows - 1; r >= 0; r-- {
if g.board[r][column-1] == 0 {
g.board[r][column-1] = g.turn
g.moves += fmt.Sprintf("%d", column)
break
}
}
g.turn = 3 - g.turn // Switch turns after making a move
}
func (g *Game) undoMove(column int) {
for r := 0; r < rows; r++ {
if g.board[r][column-1] != 0 {
g.board[r][column-1] = 0
g.moves = g.moves[:len(g.moves)-1]
break
}
}
// No need to switch turns back here as it's handled after each makeMove call
}
func (g *Game) checkWin() bool {
for r := 0; r < rows; r++ {
for c := 0; c < columns; c++ {
player := g.board[r][c]
if player == 0 {
continue
}
// Check right
if c+3 < columns {
if player == g.board[r][c+1] && player == g.board[r][c+2] && player == g.board[r][c+3] {
return true
}
}
// Check down
if r+3 < rows {
if player == g.board[r+1][c] && player == g.board[r+2][c] && player == g.board[r+3][c] {
return true
}
}
// Check down-right
if r+3 < rows && c+3 < columns {
if player == g.board[r+1][c+1] && player == g.board[r+2][c+2] && player == g.board[r+3][c+3] {
return true
}
}
// Check down-left
if r+3 < rows && c-3 >= 0 {
if player == g.board[r+1][c-1] && player == g.board[r+2][c-2] && player == g.board[r+3][c-3] {
return true
}
}
}
}
return false
}
func (g *Game) isFull() bool {
for c := 0; c < columns; c++ {
if g.canPlayColumn(c + 1) {
return false
}
}
return true
}
func main() {
c := make(chan os.Signal, 1)
signal.Notify(c, os.Interrupt)
go func() {
for {
game := Game{turn: 1}
game.play()
}
}()
<-c // Block until Ctrl-C
fmt.Println("\nExiting...")
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment