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.
 
 
 

163 lines
3.9 KiB

#include "Snake.h"
Snake::Snake(uint32_t headY, uint32_t headX)
:direction_{LEFT}
{
snake_.push_back(Point{headY, headX, '>'});
for (uint32_t i = 1; i <= SNAKE_DEFAULT_SIZE; i++) {
snake_.push_back(Point{headY, headX + i, SNAKE_BODY_CHAR});
}
}
bool Snake::isBitten() const {
const Point& head = snake_.front();
// use manual iterator loop instead of
// range-based for as we need to skip head
for (auto it = std::next(snake_.begin()); it != snake_.end(); it++) {
if (it->getX() == head.getX() && it->getY() == head.getY()) {
return true;
}
}
return false;
}
bool Snake::hasBitSnack(uint32_t snackY, uint32_t snackX) const {
return snake_.front().getY() == snackY && snake_.front().getX() == snackX;
}
bool Snake::hasCrashedWall() const {
const Point& head = snake_.front();
return (head.getY() < GAME_TOP_WALL_Y) ||
(head.getY() > GAME_BOTTOM_WALL_Y) ||
(head.getX() < GAME_LEFT_WALL_X) ||
(head.getX() > GAME_RIGHT_WALL_X);
}
uint32_t Snake::getSize() const {
return snake_.size();
}
void Snake::incSize(){
const auto tail = std::prev(snake_.end());
const uint32_t tailX = tail->getX();
const uint32_t tailY = tail->getY();
const auto prev = std::prev(tail);
const uint32_t prevX = prev->getX();
const uint32_t prevY = prev->getY();
if (prevY == tailY){
// if the two last parts are on the same 'height' (horizontal tail direction)
if (prevX < tailX) {
// if the tail continues to the left:
// add one part to the right of the tail
snake_.push_back(Point{tailY, tailX + 1, SNAKE_BODY_CHAR});
}
else {
// if the tail continues to the right:
// add one part to the left of the tail
snake_.push_back(Point{tailY, tailX - 1, SNAKE_BODY_CHAR});
}
}
else {
// if the two last parts are on the same 'width' (vertical tail direction)
if (prevY < tailY) {
// if the tail continues to the upper side:
// add one part facing down
snake_.push_back(Point{tailY + 1, tailX, SNAKE_BODY_CHAR});
}
else {
// if the tail continues to the lower side:
// add one part facing up
snake_.push_back(Point{tailY - 1, tailX, SNAKE_BODY_CHAR});
}
}
}
void Snake::updateHead(){
switch (direction_) {
case UP:
snake_.front().moveUp();
break;
case DOWN:
snake_.front().moveDown();
break;
case LEFT:
snake_.front().moveLeft();
break;
case RIGHT:
snake_.front().moveRight();
break;
}
}
void Snake::printSnake() const {
//We print each element of the snake-list
for (const Point& part : snake_){
part.print();
}
Graphics::get().refreshScreen();
}
void Snake::move() {
auto head = snake_.begin();
auto second = std::next(snake_.begin());
// clear the tail - overwrites with ' '
snake_.back().clear();
// update all nodes by iterating from the back
// and copying the previous nodes values in
// until the second-to-first one
auto iter = std::prev(snake_.end());
while (iter != second) {
auto prev = std::prev(iter);
*iter = *prev;
iter = prev;
}
// update the previous to head node
// by copying from head and setting
// the image to be body instead of head
*second = *head;
iter->setImg(SNAKE_BODY_CHAR);
updateHead();
printSnake();
}
void Snake::moveUp(){
snake_.front().setImg('v');
direction_ = UP;
move();
}
void Snake::moveDown(){
snake_.front().setImg('^');
direction_ = DOWN;
move();
}
void Snake::moveLeft(){
snake_.front().setImg('>');
direction_ = LEFT;
move();
}
void Snake::moveRight(){
snake_.front().setImg('<');
direction_ = RIGHT;
move();
}