package main import ( "github.com/gdamore/tcell/v2" ) // initSnake Initialize the snake func initSnake(snakex *int, snakey *int) Snake { var x, y int = *snakex, *snakey snake := Snake{ head: Position{ x: x, y: y, }, tail: []Position{ { x: x - 1, y: y, }, { x: x - 2, y: y, }, { x: x - 3, y: y, }, }, length: 3, direction: 1, } return snake } func drawSnake(screen tcell.Screen, style tcell.Style, snake *Snake) { var tail []rune // Reverse tail, chop of the excesses, snake.tail = ReverseSlice(snake.tail) if len(snake.tail) > snake.length { snake.tail = snake.tail[:snake.length] } // reverse it back to the original order, replace the tail in `snake` snake.tail = ReverseSlice(snake.tail) for i, j := range snake.tail { // The Tail end if i == 0 { left := getDirection(j, snake.tail[i+1]) right := getDirection(j, snake.tail[i+1]) tail = append(tail, getLineType(left, right)) // The Bit behind the head } else if i == len(snake.tail)-1 { left := getDirection(j, snake.tail[i-1]) right := getDirection(j, snake.head) tail = append(tail, getLineType(left, right)) // The body of the snake } else { left := getDirection(j, snake.tail[i-1]) right := getDirection(j, snake.tail[i+1]) tail = append(tail, getLineType(left, right)) } } // Draw the body for i, segment := range snake.tail { screen.SetContent(segment.x, segment.y, tail[i], nil, style) } // Draw the head, make sure it is on top of everything screen.SetContent(snake.head.x, snake.head.y, '0', nil, style) } func snakeDirection(press int, snake *Snake) { if press == Left { snake.head.x-- snake.tail = append(snake.tail, Position{x: snake.head.x + 1, y: snake.head.y}) snake.direction = press } else if press == Right { snake.head.x++ snake.tail = append(snake.tail, Position{x: snake.head.x - 1, y: snake.head.y}) snake.direction = press } else if press == Up { snake.head.y-- snake.tail = append(snake.tail, Position{x: snake.head.x, y: snake.head.y + 1}) snake.direction = press } else if press == Down { snake.head.y++ snake.tail = append(snake.tail, Position{x: snake.head.x, y: snake.head.y - 1}) snake.direction = press } } // Check if a pos hits the tail func hitsTail(snake *Snake, x int, y int) bool { var hit bool = false for _, segment := range snake.tail { if segment.x == x && segment.y == y { hit = true } } return hit } func ReverseSlice[T comparable](s []T) []T { var r []T for i := len(s) - 1; i >= 0; i-- { r = append(r, s[i]) } return r } func validateDirection(snake *Snake, direction int) bool { if snake.direction == direction { return true } else if snake.direction == Left && direction == Right { return false } else if snake.direction == Right && direction == Left { return false } else if snake.direction == Up && direction == Down { return false } else if snake.direction == Down && direction == Up { return false } else { return true } } func getDirection(from Position, to Position) int { var direction int if from.x-to.x == 1 { direction = Left } else if from.x-to.x == -1 { direction = Right } else if from.y-to.y == 1 { direction = Up } else if from.y-to.y == -1 { direction = Down } return direction } func getLineType(from int, to int) rune { var lineType rune if (from == Left && to == Down) || (from == Down && to == Left) { lineType = '┐' } else if (from == Up && to == Right) || (from == Right && to == Up) { lineType = '└' } else if (from == Left && to == Right) || (from == Right && to == Left) { lineType = '─' } else if (from == Left && to == Up) || (from == Up && to == Left) { lineType = '┘' } else if (from == Right && to == Down) || (from == Down && to == Right) { lineType = '┌' } else if (from == Up && to == Down) || (from == Down && to == Up) { lineType = '│' } return lineType }