Commit d772eb15 authored by Boris Mühmer's avatar Boris Mühmer
Browse files

stupid bot version is working



Signed-off-by: default avatarBoris Mühmer <boris@muehmer.de>
parent f6578b1d
Loading
Loading
Loading
Loading
+31 −0
Original line number Diff line number Diff line
package main

import (
	"flag"
	"fmt"
	"math/rand"
	"os"
	"time"

	"repositories.muehmer.net/bsmrgo/tic-tac-toe/pkg/ttt/game"
	"repositories.muehmer.net/bsmrgo/tic-tac-toe/pkg/ttt/grid"
)

func main() {
	var seed int64
	var name1 string
	var name2 string

	flag.Int64Var(&seed, "seed", time.Now().Unix(), "the seed used for rand.Seed()")
	flag.StringVar(&name1, "name1", "Alexander Shafto Douglas", "the name for player 1")
	flag.StringVar(&name2, "name2", "Maurice Wilkes", "the name for player 2")
	flag.Parse()

	fmt.Fprintf(os.Stderr, "Seed: %d\n", seed)
	rand.Seed(seed)

	g := game.New()
	g.AddPlayer(name1, &grid.Cross{})
	g.AddPlayer(name2, &grid.Nought{})
	g.Run()
}

pkg/ttt/game/game.go

0 → 100644
+87 −0
Original line number Diff line number Diff line
package game

import (
	"fmt"
	"os"

	"repositories.muehmer.net/bsmrgo/tic-tac-toe/pkg/ttt/grid"
	"repositories.muehmer.net/bsmrgo/tic-tac-toe/pkg/ttt/player"
	"repositories.muehmer.net/bsmrgo/tic-tac-toe/pkg/ttt/players/bot"
)

// Game ...
type Game struct {
	Grid    *grid.Grid
	Players map[int]player.Player
}

// New ...
func New() *Game {
	return &Game{
		Grid:    grid.New(),
		Players: make(map[int]player.Player),
	}
}

// AddPlayer ...
func (g *Game) AddPlayer(name string, cell grid.Cell) error {
	c := len(g.Players)
	g.Players[c] = bot.New(name, cell)
	return nil
}

// Run ...
func (g *Game) Run() {
	for i := 0; i < 9; i++ {
		pl := i % 2
		p := g.Players[pl]
		pos := p.Next(g.Grid)
		g.Grid.Data[pos] = p.Cell()

		c0 := g.Grid.Data[grid.Pos(0, 0)]
		c1 := g.Grid.Data[grid.Pos(1, 0)]
		c2 := g.Grid.Data[grid.Pos(2, 0)]
		if (c0 == c1) && (c1 == c2) && (c0 == c2) {

		}

		fmt.Fprintf(os.Stderr, "Round %d: %s\n%s", i+1, p.Name(), g.Grid)

		if checkLines(g.Grid) {
			fmt.Fprintf(os.Stderr, "Player %s has won!\n", p.Name())
			return
		}
	}
	fmt.Fprintf(os.Stderr, "No winner.\n")
}

func checkLines(g *grid.Grid) bool {
	for _, p := range []struct{ x0, y0, x1, y1, x2, y2 int }{
		// rows
		{0, 0, 1, 0, 2, 0},
		{0, 1, 1, 1, 2, 1},
		{0, 2, 1, 2, 2, 2},
		// columns
		{0, 0, 0, 1, 0, 2},
		{1, 0, 1, 1, 1, 2},
		{2, 0, 2, 1, 2, 2},
		// diagonals
		{0, 0, 1, 1, 2, 2},
		{0, 2, 1, 1, 2, 0},
	} {
		if line(g, p.x0, p.y0, p.x1, p.y1, p.x2, p.y2) {
			return true
		}
	}
	return false
}

func line(g *grid.Grid, x0, y0, x1, y1, x2, y2 int) bool {
	c0 := g.Data[grid.Pos(x0, y0)]
	c1 := g.Data[grid.Pos(x1, y1)]
	c2 := g.Data[grid.Pos(x2, y2)]
	if (!c0.IsEmpty()) && (c0 == c1) && (c1 == c2) && (c0 == c2) {
		return true
	}
	return false
}
+22 −0
Original line number Diff line number Diff line
package game

import (
	"math/rand"
	"testing"

	"repositories.muehmer.net/bsmrgo/tic-tac-toe/pkg/ttt/grid"
)

func TestGame(t *testing.T) {
	//seed := time.Now().Unix()
	seed := int64(1557681173)
	rand.Seed(seed)

	c1 := &grid.Cross{}
	c2 := &grid.Nought{}

	g := New()
	g.AddPlayer("Player 1", c1)
	g.AddPlayer("Player 2", c2)
	g.Run()
}

pkg/ttt/grid/grid.go

0 → 100644
+140 −0
Original line number Diff line number Diff line
package grid

import "strings"

// Grid ...
type Grid struct {
	Data map[Position]Cell
}

// Position ...
type Position struct {
	X int
	Y int
}

// Cell ...
type Cell interface {
	Symbol() string
	IsEmpty() bool
	IsNought() bool
	IsCross() bool
}

// Empty ...
type Empty struct{}

// Symbol ...
func (e *Empty) Symbol() string {
	return " "
}

// IsEmpty ...
func (e *Empty) IsEmpty() bool {
	return true
}

// IsNought ...
func (e *Empty) IsNought() bool {
	return false
}

// IsCross ...
func (e *Empty) IsCross() bool {
	return false
}

// Nought ...
type Nought struct{}

// Symbol ...
func (n *Nought) Symbol() string {
	return "○"
}

// IsEmpty ...
func (n *Nought) IsEmpty() bool {
	return false
}

// IsNought ...
func (n *Nought) IsNought() bool {
	return true
}

// IsCross ...
func (n *Nought) IsCross() bool {
	return false
}

// Cross ...
type Cross struct{}

// Symbol ...
func (c *Cross) Symbol() string {
	return "×"
}

// IsEmpty ...
func (c *Cross) IsEmpty() bool {
	return false
}

// IsNought ...
func (c *Cross) IsNought() bool {
	return false
}

// IsCross ...
func (c *Cross) IsCross() bool {
	return true
}

// New ...
func New() *Grid {
	g := &Grid{
		Data: make(map[Position]Cell),
	}

	for y := 0; y < 3; y++ {
		for x := 0; x < 3; x++ {
			g.Data[Pos(x, y)] = &Empty{}
		}
	}

	return g
}

// Pos ...
func Pos(x, y int) Position {
	return Position{X: x, Y: y}
}

// String ...
func (g *Grid) String() string {
	var sb strings.Builder

	//×┃×┃▢
	//━╋━╋━
	//▢┃○┃▢
	//━╋━╋━
	//▢┃▢┃▢

	for y := 0; y < 3; y++ {
		for x := 0; x < 3; x++ {
			sb.WriteString(g.Data[Pos(x, y)].Symbol())
			switch x {
			case 0, 1:
				sb.WriteString("┃")
			case 2:
				sb.WriteString("\n")
			}
		}
		switch y {
		case 0, 1:
			sb.WriteString("━╋━╋━\n")
		}
	}

	return sb.String()
}
+15 −0
Original line number Diff line number Diff line
package grid

import (
	"strings"
	"testing"
)

func TestDisplayGrid(t *testing.T) {
	g := New()
	s := g.String()
	r := " ┃ ┃ \n━╋━╋━\n ┃ ┃ \n━╋━╋━\n ┃ ┃ \n"
	if strings.Compare(s, r) != 0 {
		t.Errorf("grid is \"%s\", expected \"%s\"", s, r)
	}
}
Loading