snake.go 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. package main
  2. import (
  3. "github.com/gdamore/tcell/v2"
  4. )
  5. // initSnake Initialize the snake
  6. func initSnake(snakex int, snakey int) Snake {
  7. var x, y int = snakex, snakey
  8. snake := Snake{
  9. head: Position{
  10. x: x,
  11. y: y,
  12. },
  13. tail: []Position{
  14. {
  15. x: x - 3,
  16. y: y,
  17. },
  18. {
  19. x: x - 2,
  20. y: y,
  21. },
  22. {
  23. x: x - 1,
  24. y: y,
  25. },
  26. },
  27. length: 3,
  28. direction: 1,
  29. }
  30. return snake
  31. }
  32. func drawSnake(screen tcell.Screen, style tcell.Style, snake *Snake) {
  33. var tail []rune
  34. // Reverse tail, chop of the excesses,
  35. snake.tail = ReverseSlice(snake.tail)
  36. if len(snake.tail) > snake.length {
  37. snake.tail = snake.tail[:snake.length]
  38. }
  39. // reverse it back to the original order, replace the tail in `snake`
  40. snake.tail = ReverseSlice(snake.tail)
  41. for i, j := range snake.tail {
  42. // The Tail end
  43. if i == 0 {
  44. left := getDirection(j, snake.tail[i+1])
  45. right := getDirection(j, snake.tail[i+1])
  46. tail = append(tail, getLineType(left, right))
  47. // The Bit behind the head
  48. } else if i == len(snake.tail)-1 {
  49. left := getDirection(j, snake.tail[i-1])
  50. right := getDirection(j, snake.head)
  51. tail = append(tail, getLineType(left, right))
  52. // The body of the snake
  53. } else {
  54. left := getDirection(j, snake.tail[i-1])
  55. right := getDirection(j, snake.tail[i+1])
  56. tail = append(tail, getLineType(left, right))
  57. }
  58. }
  59. // Draw the body
  60. for i, segment := range snake.tail {
  61. screen.SetContent(segment.x, segment.y, tail[i], nil, style)
  62. }
  63. // Draw the head, make sure it is on top of everything
  64. screen.SetContent(snake.head.x, snake.head.y, '0', nil, style)
  65. }
  66. func snakeDirection(press int, snake *Snake) {
  67. if press == Left {
  68. snake.head.x--
  69. snake.tail = append(snake.tail, Position{x: snake.head.x + 1, y: snake.head.y})
  70. snake.direction = press
  71. } else if press == Right {
  72. snake.head.x++
  73. snake.tail = append(snake.tail, Position{x: snake.head.x - 1, y: snake.head.y})
  74. snake.direction = press
  75. } else if press == Up {
  76. snake.head.y--
  77. snake.tail = append(snake.tail, Position{x: snake.head.x, y: snake.head.y + 1})
  78. snake.direction = press
  79. } else if press == Down {
  80. snake.head.y++
  81. snake.tail = append(snake.tail, Position{x: snake.head.x, y: snake.head.y - 1})
  82. snake.direction = press
  83. }
  84. }
  85. // Check if a pos hits the tail
  86. func hitsTail(snake *Snake, x int, y int) bool {
  87. var hit bool = false
  88. for _, segment := range snake.tail {
  89. if segment.x == x && segment.y == y {
  90. hit = true
  91. }
  92. }
  93. return hit
  94. }
  95. func ReverseSlice[T comparable](s []T) []T {
  96. var r []T
  97. for i := len(s) - 1; i >= 0; i-- {
  98. r = append(r, s[i])
  99. }
  100. return r
  101. }
  102. func validateDirection(snake *Snake, direction int) bool {
  103. if snake.direction == direction {
  104. return true
  105. } else if snake.direction == Left && direction == Right {
  106. return false
  107. } else if snake.direction == Right && direction == Left {
  108. return false
  109. } else if snake.direction == Up && direction == Down {
  110. return false
  111. } else if snake.direction == Down && direction == Up {
  112. return false
  113. } else {
  114. return true
  115. }
  116. }
  117. func getDirection(from Position, to Position) int {
  118. var direction int
  119. if from.x-to.x == 1 {
  120. direction = Left
  121. } else if from.x-to.x == -1 {
  122. direction = Right
  123. } else if from.y-to.y == 1 {
  124. direction = Up
  125. } else if from.y-to.y == -1 {
  126. direction = Down
  127. }
  128. return direction
  129. }
  130. func getLineType(from int, to int) rune {
  131. var lineType rune
  132. if (from == Left && to == Down) || (from == Down && to == Left) {
  133. lineType = '┐'
  134. } else if (from == Up && to == Right) || (from == Right && to == Up) {
  135. lineType = '└'
  136. } else if (from == Left && to == Right) || (from == Right && to == Left) {
  137. lineType = '─'
  138. } else if (from == Left && to == Up) || (from == Up && to == Left) {
  139. lineType = '┘'
  140. } else if (from == Right && to == Down) || (from == Down && to == Right) {
  141. lineType = '┌'
  142. } else if (from == Up && to == Down) || (from == Down && to == Up) {
  143. lineType = '│'
  144. }
  145. return lineType
  146. }