175 lines
		
	
	
		
			3.9 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			175 lines
		
	
	
		
			3.9 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| 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 - 3,
 | |
| 				y: y,
 | |
| 			},
 | |
| 			{
 | |
| 				x: x - 2,
 | |
| 				y: y,
 | |
| 			},
 | |
| 			{
 | |
| 				x: x - 1,
 | |
| 				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
 | |
| }
 |