Advertisement
Guest User

Snake

a guest
Apr 21st, 2019
138
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 9.39 KB | None | 0 0
  1. #include <Snake.h>
  2. #include <Adafruit_NeoPixel.h>
  3.  
  4. // ===============================
  5. // ========== Constants ==========
  6. // ===============================
  7.  
  8. #define IO_PIN      10
  9. #define NUM_PIXEL   100
  10. #define BRIGHTNESS  255
  11. #define TIME_DELAY  200
  12.  
  13. #define MATRIX_SIZE   10
  14. #define MATRIX_EMPTY  0
  15. #define MATRIX_APPLE  1
  16. #define MATRIX_SNAKE  2
  17.  
  18. #define DIRECTION_OBEN    0
  19. #define DIRECTION_RECHTS  1
  20. #define DIRECTION_UNTEN   2
  21. #define DIRECTION_LINKS   3
  22. #define DIRECTION_ERROR   4
  23.  
  24. #define RED   0x00FF0000
  25. #define GREEN 0x0000FF00
  26. #define BLUE  0x000000FF
  27.  
  28. // =========================================
  29. // ========== Method deklarations ==========
  30. // =========================================
  31.  
  32. void printNumber(const char* name, long value);
  33. void printNumberln(const char* name, long value);
  34.  
  35. // =============================
  36. // ========== Structs ==========
  37. // =============================
  38.  
  39. struct Step {
  40.   uint8_t direction;
  41.   float distance;
  42. };
  43.  
  44. struct PathNode {
  45.   PathNode* parent = nullptr;
  46.   uint8_t length = 0;
  47.   uint8_t x: 4, y: 4;
  48. };
  49.  
  50. struct CoordinateArray {
  51.   CoordinateArray(Coordinate* coords, uint8_t length) {
  52.     this->coords = coords;
  53.     this->length = length;
  54.   }
  55.  
  56.   Coordinate* coords;
  57.   uint8_t length;
  58. };
  59.  
  60.  
  61.  
  62. Snake snake;
  63. Coordinate apple;
  64. Step steps[4];
  65. Coordinate directions[4];
  66. uint8_t directionArray[4];
  67.  
  68. long periodEnd;
  69.  
  70. Adafruit_NeoPixel strip = Adafruit_NeoPixel(NUM_PIXEL, IO_PIN, NEO_GRBW + NEO_KHZ800);
  71.  
  72. // ====================================
  73. // ========== Main-Functions ==========
  74. // ====================================
  75.  
  76. void setup() {
  77.   randomSeed(analogRead(0));
  78.   Serial.begin(9600);
  79.   while (!Serial) {
  80.     ;
  81.   }
  82.  
  83.   initializeDirections();
  84.   initializeLedStrip();
  85.  
  86.   snake = Snake();
  87.  
  88.   createNewApple();
  89.   apple.x = apple.y = 9;
  90.   //ledTest();
  91.  
  92.   periodEnd = millis() + TIME_DELAY;
  93.   renderToScreen();
  94.   randomizeDirections();
  95. }
  96.  
  97.  
  98.  
  99. void loop() {
  100.   periodEnd = millis() + TIME_DELAY;
  101.  
  102.   Coordinate nextCoord = runDijkstra(snake[0]); //max 31millis
  103.  
  104.   if (nextCoord.y < snake[0].y) {
  105.     moveSnake(DIRECTION_OBEN);
  106.   } else if (nextCoord.y > snake[0].y) {
  107.     moveSnake(DIRECTION_UNTEN);
  108.   } else if (nextCoord.x > snake[0].x) {
  109.     moveSnake(DIRECTION_RECHTS);
  110.   } else if (nextCoord.x < snake[0].x) {
  111.     moveSnake(DIRECTION_LINKS);
  112.   }
  113.  
  114.   if (snakeAteApple()) {
  115.     createNewApple();
  116.     randomizeDirections();
  117.   }
  118.  
  119.   while (periodEnd > millis()) {
  120.     ; // Wait
  121.   }
  122.  
  123.   renderToScreen();
  124. }
  125.  
  126. /** Randomize directions */
  127. void randomizeDirections(){
  128.   uint8_t newNumber;
  129.  
  130.   for (uint8_t i = 0; i < 4; i++){
  131.     directionArray[i] = 4;
  132.   }
  133.  
  134.   for (uint8_t i = 0; i < 4; i++){
  135.     do {
  136.       newNumber = random(4);
  137.     } while (directionAlreadyInUse(newNumber));
  138.  
  139.     directionArray[i] = newNumber;
  140.   }
  141. }
  142.  
  143. bool directionAlreadyInUse(uint8_t number){
  144.   for (uint8_t i = 0; i < 4; i++){
  145.     if (directionArray[i] == number){
  146.       return true;
  147.     }
  148.   }
  149.  
  150.   return false;
  151. }
  152.  
  153. /**
  154.    Tests, if the snake ate the apple
  155. */
  156. bool snakeAteApple() {
  157.   if ((snake[0].x == apple.x) && (snake[0].y == apple.y)) {
  158.     return true;
  159.   } else {
  160.     return false;
  161.   }
  162. }
  163.  
  164. /**
  165.     Resets the game
  166. */
  167. void restart() {
  168.   snake.reset();
  169.   createNewApple();
  170. }
  171.  
  172. /**
  173.    Moves the Snake to the new position
  174. */
  175. void moveSnake(uint8_t direction) {
  176.   switch (direction) {
  177.     case DIRECTION_OBEN: snake.moveUp(); break;
  178.     case DIRECTION_RECHTS: snake.moveRight(); break;
  179.     case DIRECTION_UNTEN: snake.moveDown(); break;
  180.     case DIRECTION_LINKS: snake.moveLeft(); break;
  181.   }
  182. }
  183.  
  184. // ==============================
  185. // ========== RENDERER ==========
  186. // ==============================
  187.  
  188. /**
  189.    Renders the led strip
  190. */
  191. void renderToScreen() {
  192.   clearLedStrip();
  193.   renderApple();
  194.   renderSnake();
  195.   strip.show();
  196. }
  197.  
  198. /**
  199.    Renders the apple to the led strip
  200. */
  201. void renderApple() {
  202.   uint8_t pos = calcLedPos(apple);
  203.   strip.setPixelColor(pos, RED);
  204. }
  205.  
  206. /**
  207.    Rendes the snake to the led strip
  208. */
  209. void renderSnake() {
  210.   uint8_t pos;
  211.   uint32_t snakeSegmentColor = strip.Color(128, 255, 0);
  212.  
  213.   pos = calcLedPos(snake[0]);
  214.   strip.setPixelColor(pos, strip.Color(255, 255, 0));
  215.  
  216.   for (uint8_t i = 1; i < SNAKE_LENGTH; i++) {
  217.     pos = calcLedPos(snake[i]);
  218.     strip.setPixelColor(pos, snakeSegmentColor);
  219.     snakeSegmentColor -= 0x200000;
  220.   }
  221. }
  222.  
  223. /**
  224.    Calculates the position of a coordinate on the led strip
  225. */
  226. uint8_t calcLedPos(Coordinate coord) {
  227.   uint8_t pos = coord.y * MATRIX_SIZE;
  228.  
  229.   if ((coord.y % 2) == 0) {
  230.     return pos + coord.x;
  231.   } else {
  232.     return pos + MATRIX_SIZE - coord.x - 1;
  233.   }
  234. }
  235.  
  236. /**
  237.    Creates a new apple in the matrix
  238. */
  239. void createNewApple() {
  240.   int8_t x, y;
  241.  
  242.   do {
  243.     x = random(MATRIX_SIZE);
  244.     y = random(MATRIX_SIZE);
  245.   } while (snake.coordIsTaken(x, y));
  246.  
  247.   apple.x = x;
  248.   apple.y = y;
  249. }
  250.  
  251.  
  252. // ===========================
  253. // ========== INITS ==========
  254. // ===========================
  255.  
  256. /**
  257.    Initializes the directions-array
  258. */
  259. void initializeDirections() {
  260.   directions[DIRECTION_OBEN] = Coordinate(0, -1);
  261.   directions[DIRECTION_RECHTS] = Coordinate(1, 0);
  262.   directions[DIRECTION_UNTEN] =  Coordinate(0, 1);
  263.   directions[DIRECTION_LINKS] = Coordinate(-1, 0);
  264. }
  265.  
  266. /**
  267.    Initializes the led strip
  268. */
  269. void initializeLedStrip() {
  270.   strip.begin(); // This initializes the NeoPixel library.
  271.   strip.setBrightness(BRIGHTNESS); // set brightness
  272.   strip.show(); // Initialize all pixels to 'off'
  273. }
  274.  
  275. /**
  276.    Tests all leds by letting them blink in all 3 colors
  277. */
  278. void ledTest() {
  279.   uint8_t timeDelay = 20;
  280.  
  281.   for (uint8_t i = 0; i < NUM_PIXEL; i++) {
  282.     clearLedStrip();
  283.     strip.setPixelColor(i, RED);
  284.     strip.show();
  285.     delay(timeDelay);
  286.   }
  287.  
  288.   for (uint8_t i = 0; i < NUM_PIXEL; i++) {
  289.     clearLedStrip();
  290.     strip.setPixelColor(i, GREEN);
  291.     strip.show();
  292.     delay(timeDelay);
  293.   }
  294.  
  295.   for (uint8_t i = 0; i < NUM_PIXEL; i++) {
  296.     clearLedStrip();
  297.     strip.setPixelColor(i, BLUE);
  298.     strip.show();
  299.     delay(timeDelay);
  300.   }
  301. }
  302.  
  303. void clearLedStrip() {
  304.   for (uint8_t i = 0; i < NUM_PIXEL; i++) {
  305.     strip.setPixelColor(i, 0);
  306.   }
  307. }
  308.  
  309. // ==============================
  310. // ========== DIJKSTRA ==========
  311. // ==============================ยด
  312.  
  313. #define OPEN_LIST_MAX 30
  314. #define ALL_LIST_MAX 100
  315.  
  316. // ArrayList - OpenList
  317. PathNode* openList[OPEN_LIST_MAX];
  318. uint8_t openList_pos;
  319.  
  320. // ArrayList - All
  321. PathNode* allList[ALL_LIST_MAX];
  322. uint8_t allList_pos;
  323.  
  324.  
  325.  
  326. uint8_t calcPos(uint8_t x, uint8_t y, uint8_t x_length) {
  327.   return y * x_length + x + 1;
  328. }
  329.  
  330. bool nodeAlreadyExists(uint8_t x, uint8_t y) {
  331.   for (uint8_t i = 0; i < allList_pos; i++) {
  332.     if ((allList[i]->x == x) && (allList[i]->y == y)) {
  333.       return true;
  334.     }
  335.   }
  336.  
  337.   return false;
  338. }
  339.  
  340. bool isWithinMatrix(PathNode* nextNode, Coordinate coord) {
  341.   if (!((nextNode->x + coord.x >= 0) && (nextNode->x + coord.x < MATRIX_SIZE))) {
  342.     return false;
  343.   }
  344.  
  345.  
  346.   if (!((nextNode->y + coord.y >= 0) && (nextNode->y + coord.y < MATRIX_SIZE))) {
  347.     return false;
  348.   }
  349.  
  350.   return true;
  351. }
  352.  
  353. void testDirection(uint8_t nextDirection, PathNode* nextNode) {
  354.   Coordinate coord = directions[nextDirection];
  355.  
  356.   if (isWithinMatrix(nextNode, coord) && (!snake.coordIsTaken(nextNode->x + coord.x, nextNode->y + coord.y)) && (!nodeAlreadyExists(nextNode->x + coord.x, nextNode->y + coord.y))) {
  357.     PathNode* newNode = new PathNode;
  358.     newNode->parent = nextNode;
  359.     newNode->length = nextNode->length + 1;
  360.     newNode->x = nextNode->x + coord.x;
  361.     newNode->y = nextNode->y + coord.y;
  362.     openList[openList_pos++] = newNode;
  363.     allList[allList_pos++] = newNode;
  364.   }
  365. }
  366.  
  367. Coordinate runDijkstra(Coordinate start) {
  368.   openList_pos = 0;
  369.   allList_pos = 0;
  370.  
  371.   uint8_t nextNodeIndex = 0;
  372.   PathNode* nextNode = nullptr;
  373.   PathNode* originNode = nullptr;
  374.  
  375.   // Init
  376.   originNode = nextNode = new PathNode;
  377.   allList[allList_pos++] = nextNode;
  378.  
  379.   nextNode->length = 0;
  380.   nextNode->x = start.x;
  381.   nextNode->y = start.y;
  382.  
  383.   // Origin-Element abarbeiten
  384.   openList[openList_pos++] = nextNode;
  385.  
  386.   uint8_t bestLength;
  387.   uint8_t matrixFieldValue;
  388.   while (true) {
  389.     // Node mit kleinster Laenge suchen
  390.     bestLength = 255;
  391.     for (uint8_t i = 0; i < openList_pos; i++) {
  392.       //printNode(openList[i]); // TODO
  393.       if (openList[i]->length < bestLength) {
  394.         nextNode = openList[i];
  395.         bestLength = nextNode->length;
  396.         nextNodeIndex = i;
  397.       }
  398.     }
  399.  
  400.     // Wenn diese Node Ziel ist, wird sie zurueck gegeben
  401.     if ((nextNode->x == apple.x) && (nextNode->y == apple.y)) {
  402.       uint8_t length = nextNode->length - 1;
  403.  
  404.       for (uint8_t i = 0; i < length; i++) {
  405.         nextNode = nextNode->parent;
  406.       }
  407.  
  408.       Coordinate coord(nextNode->x, nextNode->y);
  409.  
  410.       for (uint8_t i = 0; i < allList_pos; i++) {
  411.         delete allList[i];
  412.       }
  413.  
  414.       return coord;
  415.     }
  416.  
  417.     // Directions absuchen
  418.     for (uint8_t i = 0; i < 4; i++){
  419.       testDirection(directionArray[i], nextNode);
  420.     }
  421.  
  422.     // NextNode aus der Liste loeschen
  423.     for (uint8_t i = nextNodeIndex; i < OPEN_LIST_MAX - 1; i++) {
  424.       openList[i] = openList[i + 1];
  425.     }
  426.     openList_pos--;
  427.   }
  428. }
  429.  
  430. void printNumber(const char* name, long value) {
  431.   Serial.print(name );
  432.   Serial.print(value, DEC);
  433. }
  434.  
  435. void printNumberln(const char* name, long value) {
  436.   Serial.print(name );
  437.   Serial.println(value, DEC);
  438. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement