Documentation
¶
Index ¶
- Constants
- func AssertCoordinate(t testing.TB, got Coordinate, want Coordinate)
- func AssertCoordinates(t testing.TB, got []Coordinate, want []Coordinate)
- func AssertDirection(t testing.TB, got Direction, want Direction)
- func AssertError(t testing.TB, got error, want error)
- func AssertNoError(t testing.TB, got error)
- func Has(d, flag Direction) bool
- func NewSnakeInvalidMoveErr(face, move Direction) error
- func WaitAndReceiveGameChannels(t testing.TB, g *Game) (snakeCoordinate []Coordinate, gameResult *bool, foodCoordinate *Coordinate)
- type Cloak
- type Controller
- type Coordinate
- type DefaultCloak
- type Direction
- type Food
- type FoodError
- type FoodGenerator
- type FoodStub
- type FoodStubValue
- type Game
- func (g *Game) Quit()
- func (g *Game) ReceiveFoodCoordinate() <-chan Coordinate
- func (g *Game) ReceiveGameResult() <-chan bool
- func (g *Game) ReceiveSnakeCoordinates() <-chan []Coordinate
- func (g *Game) Restart(d time.Duration)
- func (g *Game) SendMove(d Direction)
- func (g *Game) Start(d time.Duration)
- type GameDirector
- type Snake
- type SnakeErr
- type SnakeInvalidMoveErr
- type View
- func (v *View) DisplayLose()
- func (v *View) DisplayWin()
- func (v *View) ReceiveDirection() <-chan Direction
- func (v *View) ReceiveNewGameSignal() <-chan struct{}
- func (v *View) ReceiveQuitSignal() <-chan struct{}
- func (v *View) Refresh(snakeCoordinates *[]Coordinate, foodCoordinate *Coordinate)
- func (v *View) Release()
- type ViewHandler
Constants ¶
const ( ErrHeadOutOfBoard = SnakeErr("snake: head out of board") ErrSnakeMustMoveBeforeGrowing = SnakeErr("snake: must move before growing") ErrHeadHitBody = SnakeErr("snake: head hit body") )
const BodyBackgroundColor = tcell.ColorGray
const BodyForegroundColor = tcell.ColorWhite
const BodyRune = '▮'
const (
ErrBoardFull = FoodError("snake: food: board full, can not generate food coordinate")
)
const FoodBackgroundColor = tcell.ColorBlack
const FoodForegroundColor = tcell.ColorRed
const FoodRune = '◆'
const LoseMessage = "Game lost! Press SPACEBAR to start a new game or press Q to quit..."
const WinMessage = "Game won! Press SPACEBAR to start a new game or press Q to quit..."
Variables ¶
This section is empty.
Functions ¶
func AssertCoordinate ¶
func AssertCoordinate(t testing.TB, got Coordinate, want Coordinate)
AssertCoordinate asserts that got coordinate and want coordiante are equal.
func AssertCoordinates ¶
func AssertCoordinates(t testing.TB, got []Coordinate, want []Coordinate)
AssertCoordinates asserts that got and want coordinates are deep equal.
func AssertDirection ¶
AssertDirection asserts that the direction I got is the direction I want.
func AssertError ¶
AssertError asserts that got is the error I want.
func AssertNoError ¶
AssertNoError asserts that got is nil.
func NewSnakeInvalidMoveErr ¶
func WaitAndReceiveGameChannels ¶
func WaitAndReceiveGameChannels(t testing.TB, g *Game) (snakeCoordinate []Coordinate, gameResult *bool, foodCoordinate *Coordinate)
WaitAndReceiveGameChannels returns a ([]Coordinate, *bool, *Coordinate) tuple with snake coordinates or game result or food coordinate. It waits to receive values from the game exposed receive channels.
Types ¶
type Cloak ¶
Cloak is the interface that wraps a ticker.
Start starts the ticker.
Tick wraps the ticker receive channel.
Stop stops the ticker.
type Controller ¶
type Controller struct {
// contains filtered or unexported fields
}
Controller struct coordinates a snake game with a view.
func NewController ¶
func NewController(game GameDirector, view ViewHandler) *Controller
NewController returns a Controller pointer initializing the game and the view.
func (*Controller) Start ¶
func (c *Controller) Start(d time.Duration)
Start starts the controller internal game, then loops and waits on the view direction channel, on the game snake coordinates receiver channel, on the game food coordinate receiver channel and on the game result receiver channel. When it receives a new direction from the view it sends it to the game. When it receives new snake or food coordinates it refreshes the view screen. When it receives a game result it display win or lose accordingly to the result.
Should be used as a go routine.
func (*Controller) WaitForQuitSignal ¶
func (c *Controller) WaitForQuitSignal() <-chan struct{}
WaitForQuitSignal returns an empty struct receiver channel on which the controller sends when it has received a quit signal from view. After calling Controller.Start on the main go routine the consumer should wait on this channel.
type DefaultCloak ¶
type DefaultCloak struct {
// contains filtered or unexported fields
}
Ticker wrapper implementation
func NewCloak ¶
func NewCloak() *DefaultCloak
NewCloak returns a pointer to DefaultCloak. Start must be called in order to receive ticks.
NewCloak initializes an internal sync.WaitGroup which allows to start the internal ticker on a later time.
func (*DefaultCloak) Start ¶
func (c *DefaultCloak) Start(d time.Duration)
Start initializes the internal time.Ticker releasing the internal sync.WaitGroup.
func (*DefaultCloak) Stop ¶
func (c *DefaultCloak) Stop()
Stop stops the internal ticker after waiting for the cloak to start.
func (*DefaultCloak) Tick ¶
func (c *DefaultCloak) Tick() <-chan time.Time
Tick returns the internal time.Ticker.C receive channel waiting for the cloak start.
type Food ¶
type Food struct {
// contains filtered or unexported fields
}
Food struct which implements snake food coordinate random generation.
func (*Food) Generate ¶
func (f *Food) Generate(c []Coordinate) (Coordinate, error)
Generate returns a random coordinate for the food which is not in c Coordinates. If c length is equal to all the available cells in the board it returns ErrBoardFull.
type FoodGenerator ¶
type FoodGenerator interface { // Generate should return the coordinate of the next food // to spawn on the board (this new coordinate should not be contained // in c), or should return error if the board is full. Generate(c []Coordinate) (Coordinate, error) }
FoodGenerator interface describes a food producer.
Generate should return the coordinate of the next food to spawn on the board (this new coordinate should not be contained in c), or should return error if the board is full.
type FoodStub ¶
type FoodStub struct {
// contains filtered or unexported fields
}
FoodStub stubs a food generator
func (*FoodStub) Generate ¶
func (s *FoodStub) Generate(c []Coordinate) (Coordinate, error)
Generate returns the first food stub value from FoodStub internal array, then pops it from the array.
func (*FoodStub) Seed ¶
func (s *FoodStub) Seed(c []FoodStubValue)
Seed loads the c food values into FoodStub internal array.
type FoodStubValue ¶
type FoodStubValue struct { Coord Coordinate Err error }
FoodStubValue stores the coordinate and the error returned from FoodStub Generate.
type Game ¶
type Game struct {
// contains filtered or unexported fields
}
Game coordinates the snake behaviour with the cloak ticks.
func NewGame ¶
func NewGame(snake *Snake, cloak Cloak, foodProducer FoodGenerator) *Game
NewGame returns a pointer to Game, which handles snake methods on cloak ticks
func (*Game) Quit ¶
func (g *Game) Quit()
Quit stops the game internal go routine, then closes all the internal channels.
func (*Game) ReceiveFoodCoordinate ¶
func (g *Game) ReceiveFoodCoordinate() <-chan Coordinate
ReceiveFoodCoordinate returns the food coordinate receive channel.
func (*Game) ReceiveGameResult ¶
ReceiveGameResult returns the game result receive channel.
func (*Game) ReceiveSnakeCoordinates ¶
func (g *Game) ReceiveSnakeCoordinates() <-chan []Coordinate
ReceiveSnakeCoordinates returns the snake coordinates receive channel.
func (*Game) Restart ¶
Restart stops the game internal go routine, reset the snake and starts a new game event loop internal go routine.
type GameDirector ¶
type GameDirector interface { // Start should exec a new snake move after an interval, should handle // snake collision with food, should handle new food generation and should // change snake face direction on user input. // // Start should run a go routine which does the above operations. Start(d time.Duration) // SendMove should send the new direction in an internal channel. SendMove(d Direction) // ReceiveSnakeCoordinates should expose a receiver channel which emits // the new snake coordinates after each interval. ReceiveSnakeCoordinates() <-chan []Coordinate // ReceiveFoodCoordinate should expose a receiver channel which emits // the new food coordinate after the snake eats the food. ReceiveFoodCoordinate() <-chan Coordinate // ReceiveGameResult should expose a receiver channel which emits // when the game is won or is lost. ReceiveGameResult() <-chan bool // Restart should stop the game internal go routine, should reset the snake // and should start a new internal go routine event loop Restart(d time.Duration) // Quit should stop the game internal go routine and then release resources. Quit() }
GameDirector interface defines how to coordinate the snake and food interaction in a game.
type Snake ¶
type Snake struct {
// contains filtered or unexported fields
}
Snake is the struct which implements the snake behaviour.
func NewSnake ¶
NewSnake returns a new Snake struct pointer initializing snake coordinates and setting width and height of the board and snake length 3.
func NewSnakeOfLength ¶
NewSnakeOfLength returns a new Snake struct pointer initializing snake coordinates and setting width and height of the board and snake length.
func (*Snake) GetCoordinates ¶
func (s *Snake) GetCoordinates() []Coordinate
GetCoordinates returns the snake internal coordinates.
func (*Snake) Grow ¶
Grow grows snake tail appending the last cutted tail. If snake did not move before growing, it returns ErrSnakeMustMoveBeforeGrowing error.
func (*Snake) IsValidMove ¶
IsValidMove tests if direction is valid for next snake move.
func (*Snake) Move ¶
Move moves the snake head towards direction d, cutting tail coordinate and appending new coordinate on head. Returns ErrHeadOutOfBoard error when head would move out of the board. Returns SnakeInvalidMoveErr error if direction d is inconsistent with face direction. Returns ErrHeadHitBody error if the head would move above a body coordinate.
type SnakeInvalidMoveErr ¶
SnakeInvalidMoveErr implements invalid move direction error
func (SnakeInvalidMoveErr) Error ¶
func (e SnakeInvalidMoveErr) Error() string
type View ¶
type View struct {
// contains filtered or unexported fields
}
View struct which prints the snake game elements on terminal.
func NewView ¶
func NewView(screen tcell.Screen) *View
NewView returns a View struct pointer setting the screen, starting the screen events loop channel in a go routine and starts polling the screen events channel for directions in another go routine.
func (*View) DisplayLose ¶
func (v *View) DisplayLose()
DisplayLose clears the screen and displays a lose message.
func (*View) DisplayWin ¶
func (v *View) DisplayWin()
DisplayWin clears the screen and displays a win message.
func (*View) ReceiveDirection ¶
ReceiveDirection returns a Direction receiver channel which will be fed when the screen will receive directional key events.
func (*View) ReceiveNewGameSignal ¶
func (v *View) ReceiveNewGameSignal() <-chan struct{}
ReceiveNewGameSignal returns an empty struct receiver channel which will signal when the user presses SPACEBAR to request a game restart.
func (*View) ReceiveQuitSignal ¶
func (v *View) ReceiveQuitSignal() <-chan struct{}
ReceiveQuitSignal returns an empty struct receiver channel which will signal when the user presses the Q button to request to exit from the game.
func (*View) Refresh ¶
func (v *View) Refresh(snakeCoordinates *[]Coordinate, foodCoordinate *Coordinate)
Refresh clears the screen, then prints the snake body on the snake coordinates and the food on the food coordinates. The snake body will be printed overwriting the food, if their coordinates overlap. It will not print the respective coordinates if the snake or the food coordinates are nil.
type ViewHandler ¶
type ViewHandler interface { // Refresh should receive the snake and food coordinates and should display them. Refresh(snakeCoordinates *[]Coordinate, foodCoordinate *Coordinate) // ReceiveDirection should return a Direction receiver channel on which the ViewHandler // should send new change direction input from the user. ReceiveDirection() <-chan Direction // DisplayWin should display a win screen. DisplayWin() // DisplayLose should display a lose screen. DisplayLose() // ReceiveNewGameSignal should return an empty struct receiver channel on which // the ViewHandler should send new game input from the user. ReceiveNewGameSignal() <-chan struct{} // ReceiveQuitSignal should returna an empty struct receiver channel on which // the ViewHandler should send quit game input from the user. ReceiveQuitSignal() <-chan struct{} }
ViewHandler interface defines how a view should handle screen refresh and how should expose snake's change direction input.