You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

162 lines
3.9 KiB

  1. #include "Snake.h"
  2. Snake::Snake(uint32_t headY, uint32_t headX)
  3. :direction_{LEFT}
  4. {
  5. snake_.push_back(Point{headY, headX, '>'});
  6. for (uint32_t i = 1; i <= SNAKE_DEFAULT_SIZE; i++) {
  7. snake_.push_back(Point{headY, headX + i, SNAKE_BODY_CHAR});
  8. }
  9. }
  10. bool Snake::isBitten() const {
  11. const Point& head = snake_.front();
  12. // use manual iterator loop instead of
  13. // range-based for as we need to skip head
  14. for (auto it = std::next(snake_.begin()); it != snake_.end(); it++) {
  15. if (it->getX() == head.getX() && it->getY() == head.getY()) {
  16. return true;
  17. }
  18. }
  19. return false;
  20. }
  21. bool Snake::hasBitSnack(uint32_t snackY, uint32_t snackX) const {
  22. return snake_.front().getY() == snackY && snake_.front().getX() == snackX;
  23. }
  24. bool Snake::hasCrashedWall() const {
  25. const Point& head = snake_.front();
  26. return (head.getY() < GAME_TOP_WALL_Y) ||
  27. (head.getY() > GAME_BOTTOM_WALL_Y) ||
  28. (head.getX() < GAME_LEFT_WALL_X) ||
  29. (head.getX() > GAME_RIGHT_WALL_X);
  30. }
  31. uint32_t Snake::getSize() const {
  32. return snake_.size();
  33. }
  34. void Snake::incSize(){
  35. const auto tail = std::prev(snake_.end());
  36. const uint32_t tailX = tail->getX();
  37. const uint32_t tailY = tail->getY();
  38. const auto prev = std::prev(tail);
  39. const uint32_t prevX = prev->getX();
  40. const uint32_t prevY = prev->getY();
  41. if (prevY == tailY){
  42. // if the two last parts are on the same 'height' (horizontal tail direction)
  43. if (prevX < tailX) {
  44. // if the tail continues to the left:
  45. // add one part to the right of the tail
  46. snake_.push_back(Point{tailY, tailX + 1, SNAKE_BODY_CHAR});
  47. }
  48. else {
  49. // if the tail continues to the right:
  50. // add one part to the left of the tail
  51. snake_.push_back(Point{tailY, tailX - 1, SNAKE_BODY_CHAR});
  52. }
  53. }
  54. else {
  55. // if the two last parts are on the same 'width' (vertical tail direction)
  56. if (prevY < tailY) {
  57. // if the tail continues to the upper side:
  58. // add one part facing down
  59. snake_.push_back(Point{tailY + 1, tailX, SNAKE_BODY_CHAR});
  60. }
  61. else {
  62. // if the tail continues to the lower side:
  63. // add one part facing up
  64. snake_.push_back(Point{tailY - 1, tailX, SNAKE_BODY_CHAR});
  65. }
  66. }
  67. }
  68. void Snake::updateHead(){
  69. switch (direction_) {
  70. case UP:
  71. snake_.front().moveUp();
  72. break;
  73. case DOWN:
  74. snake_.front().moveDown();
  75. break;
  76. case LEFT:
  77. snake_.front().moveLeft();
  78. break;
  79. case RIGHT:
  80. snake_.front().moveRight();
  81. break;
  82. }
  83. }
  84. void Snake::printSnake() const {
  85. //We print each element of the snake-list
  86. for (const Point& part : snake_){
  87. part.print();
  88. }
  89. Graphics::get().refreshScreen();
  90. }
  91. void Snake::move() {
  92. auto head = snake_.begin();
  93. auto second = std::next(snake_.begin());
  94. // clear the tail - overwrites with ' '
  95. snake_.back().clear();
  96. // update all nodes by iterating from the back
  97. // and copying the previous nodes values in
  98. // until the second-to-first one
  99. auto iter = std::prev(snake_.end());
  100. while (iter != second) {
  101. auto prev = std::prev(iter);
  102. *iter = *prev;
  103. iter = prev;
  104. }
  105. // update the previous to head node
  106. // by copying from head and setting
  107. // the image to be body instead of head
  108. *second = *head;
  109. iter->setImg(SNAKE_BODY_CHAR);
  110. updateHead();
  111. printSnake();
  112. }
  113. void Snake::moveUp(){
  114. snake_.front().setImg('v');
  115. direction_ = UP;
  116. move();
  117. }
  118. void Snake::moveDown(){
  119. snake_.front().setImg('^');
  120. direction_ = DOWN;
  121. move();
  122. }
  123. void Snake::moveLeft(){
  124. snake_.front().setImg('>');
  125. direction_ = LEFT;
  126. move();
  127. }
  128. void Snake::moveRight(){
  129. snake_.front().setImg('<');
  130. direction_ = RIGHT;
  131. move();
  132. }