Guest User

C++ Snake Game

a guest
Dec 4th, 2019
689
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 5.82 KB | None | 0 0
  1. // Snake.cpp : This file contains the 'main' function. Program execution begins and ends there.
  2. //
  3.  
  4. #include <iostream>
  5. #include <conio.h>
  6. #include <windows.h>
  7. #include <queue>
  8. #include <time.h>
  9.  
  10.  
  11. using namespace std;
  12.  
  13. bool gameOver;
  14. const int width = 50;
  15. HANDLE hScr;
  16. const int height = 20;
  17. const int startx = width / 2 + 1;
  18. const int starty = height / 2 + 1;
  19. enum eDirecton { STOP = 0, LEFT, RIGHT, UP, DOWN };
  20.  
  21. int currentx = startx;
  22. int currenty = starty;
  23.  
  24. queue<eDirecton> Tail;
  25.  
  26. int fruitX, fruitY, score;
  27. int tailX, tailY;
  28.  
  29.  
  30. const char WALL = '#';
  31. const char FRUIT = 'X';
  32. const char SNAKE = (char)219;
  33. const char HEADLEFT = '<';
  34. const char HEADRIGHT = '>';
  35. const char HEADUP = '^';
  36. const char HEADDOWN = 'v';
  37.  
  38.  
  39. eDirecton dir;
  40.  
  41. // Create a coordinate for positioning the cursor in the console
  42. COORD GetPos(int x, int y)
  43. {
  44.     COORD Pos = { x, y };
  45.     return Pos;
  46. }
  47.  
  48.  
  49. // Returns the character at the specified coordiate.  This allows us to check what the snake ran into
  50. int GetCharAt(HANDLE h, COORD Pos)
  51. {
  52.     const int BUFFSIZE = 1;
  53.     char buf[BUFFSIZE + 1] = "";
  54.     DWORD numb_read;
  55.     ReadConsoleOutputCharacter(hScr, (LPTSTR) buf, (DWORD) BUFFSIZE, Pos, (LPDWORD) &numb_read);
  56.  
  57.     return buf[0];
  58.  
  59. }
  60.  
  61. // Resets the game
  62. void NewGame()
  63. {
  64.     // Not moving
  65.     dir = STOP;
  66.  
  67.     //Reset the tail queue (FIFI collection)
  68.     queue <eDirecton> ResetQ;
  69.     swap(Tail, ResetQ);
  70.     score = 0;
  71.    
  72.     //Reset the current position
  73.     currentx = startx;
  74.     currenty = starty;
  75.  
  76.     // Set the tail coordinates to the same location (since it's size is 1)
  77.     tailX = currentx;
  78.     tailY = currenty;
  79.  
  80.     // clear the screen
  81.     system("cls");
  82.  
  83.     // set the random seed
  84.     srand(time(NULL));
  85.  
  86.     //Draw the walls
  87.     for (int i = 0; i <= width + 2; i++)
  88.         cout << WALL;
  89.  
  90.     for (int i = 1; i < height + 1; ++i)
  91.     {
  92.         SetConsoleCursorPosition(hScr, GetPos(0, i));
  93.         cout << WALL;
  94.         SetConsoleCursorPosition(hScr, GetPos(width + 2, i));
  95.         cout << WALL;
  96.     }
  97.  
  98.     SetConsoleCursorPosition(hScr, GetPos(0, height + 1));
  99.     for (int i = 0; i <= width + 2; i++)
  100.         cout << WALL;
  101.  
  102.  
  103.     // Draw the star position of the snake
  104.     SetConsoleCursorPosition(hScr, GetPos(currentx, currenty));
  105.     cout << SNAKE;
  106.  
  107.     // Draw the first fruit
  108.     do
  109.     {
  110.         fruitX = rand() % width + 1;
  111.         fruitY = rand() % height + 1;
  112.         SetConsoleCursorPosition(hScr, GetPos(fruitX, fruitY));
  113.  
  114.  
  115.     } while (GetCharAt(hScr, GetPos(fruitX, fruitY)) != ' ');
  116.     cout << FRUIT;
  117.     SetConsoleCursorPosition(hScr, GetPos(0, height + 4));
  118.     cout << "Score: " << score << "                    ";
  119.  
  120.  
  121.  
  122. }
  123.  
  124. bool UpdatePosition(eDirecton dir)
  125. {
  126.     char cHEAD;
  127.     if (dir == STOP)
  128.         return true;
  129.     if (Tail.size() > 0)
  130.     {
  131.         SetConsoleCursorPosition(hScr, GetPos(currentx, currenty));
  132.         cout << SNAKE;
  133.  
  134.     }
  135.  
  136.     // Push the current direction to our Tail queue (FIFO collection);
  137.     Tail.push(dir);
  138.  
  139.     // Based on the direction, change the coordinates
  140.     switch (dir)
  141.     {
  142.     case LEFT:
  143.         --currentx;
  144.         cHEAD = HEADLEFT;
  145.         break;
  146.     case RIGHT:
  147.         ++currentx;
  148.         cHEAD = HEADRIGHT;
  149.         break;
  150.     case UP:
  151.         --currenty;
  152.         cHEAD = HEADUP;
  153.         break;
  154.     case DOWN:
  155.         ++currenty;
  156.         cHEAD = HEADDOWN;
  157.         break;
  158.     }
  159.  
  160.    
  161.     // Check the character at the new coordiantes so we can see if we hit the wall, tail, fruit or an empty space
  162.     int c = GetCharAt(hScr, GetPos(currentx, currenty));
  163.  
  164.     // We hit the fruit!
  165.     if (c == (int)FRUIT)
  166.     {
  167.         score += 10;
  168.        
  169.         do
  170.         {
  171.             fruitX = rand() % width + 1;
  172.             fruitY = rand() % height + 1;
  173.             SetConsoleCursorPosition(hScr, GetPos(fruitX, fruitY));
  174.         } while(GetCharAt(hScr, GetPos(fruitX, fruitY)) != ' ');
  175.         cout << FRUIT;
  176.         SetConsoleCursorPosition(hScr, GetPos(0, height + 4));
  177.         cout << "Score: " << score << "                    ";
  178.     }
  179.     else if (c != ' ')  // if it is not a space, we hit the wall or the tail.  We lost!!!
  180.     {
  181.         return false;
  182.     }
  183.     else // This must be a empty space.  The tail doesn't grow, so we remove the end of the tail
  184.     {
  185.         // Set the position to the last character in the tail and set it to blank;
  186.         SetConsoleCursorPosition(hScr, GetPos(tailX, tailY));
  187.         cout << ' ';
  188.  
  189.         // Find the direction we were going for the end of the tail.  This allows us to follow the tail and blank the space at the end of it
  190.         switch (Tail.front())
  191.         {
  192.         case LEFT:
  193.             tailX--;
  194.             break;
  195.         case RIGHT:
  196.             tailX++;
  197.             break;
  198.         case UP:
  199.             tailY--;
  200.             break;
  201.         case DOWN:
  202.             tailY++;
  203.             break;
  204.         }
  205.         Tail.pop();  // Remove the last item for the tail
  206.     }
  207.     // Now add the head character
  208.     SetConsoleCursorPosition(hScr, GetPos(currentx, currenty));
  209.     cout << cHEAD;
  210.    
  211.     return true;
  212. }
  213.  
  214.  
  215.  
  216. void Input()
  217. {
  218.     if (_kbhit())
  219.     {
  220.         char C = _getch();
  221.         if (C == -32)  // Extended key pressed
  222.         {
  223.             C = _getch();
  224.             switch (C)
  225.             {
  226.             case 'H':   // Up Arrow key pressed
  227.                 dir = UP;
  228.                 break;
  229.             case 'P':   // Down Arrow key pressed
  230.                 dir = DOWN;
  231.                 break;
  232.             case 'M':   // Right Arrow key pressed
  233.                 dir = RIGHT;
  234.                 break;
  235.             case 'K':   // Left Arrow key pressed
  236.                 dir = LEFT;
  237.                 break;
  238.             }
  239.         }
  240.         else if (C == 'x' || C == 'X')
  241.             gameOver = true;
  242.     }
  243. }
  244.  
  245.  
  246.  
  247. int main()
  248.  
  249. {
  250.    
  251.     hScr = GetStdHandle(STD_OUTPUT_HANDLE);
  252.  
  253.     // remove the flickering cursor
  254.     CONSOLE_CURSOR_INFO info;
  255.     info.dwSize = 100;
  256.     info.bVisible = FALSE;
  257.     SetConsoleCursorInfo(hScr, &info);
  258.  
  259.     // Start a new game
  260.     NewGame();
  261.     gameOver = false;
  262.  
  263.     while (!gameOver)
  264.     {
  265.         Input();
  266.  
  267.         // Update the position
  268.         if (!UpdatePosition(dir))
  269.         {
  270.             // If UpdatePosition returns false, the game is over
  271.             HANDLE h = GetStdHandle(STD_OUTPUT_HANDLE);
  272.             SetConsoleCursorPosition(h, GetPos(0, height + 6));
  273.             cout << "GAME OVER!!!  Play Again? (Y/N)";
  274.             char x = NULL;
  275.             while (x != 'Y' && x != 'N')
  276.                 x = toupper(_getch());
  277.  
  278.             if (x == 'Y')
  279.             {
  280.                 NewGame();
  281.                 continue;
  282.             }
  283.             return 0;
  284.         }
  285.  
  286.         Sleep(100);
  287.  
  288.  
  289.  
  290.     }
  291.  
  292.     CloseHandle(hScr);
  293.  
  294.  
  295.     return 0;
  296.  
  297.  
  298.  
  299. }
Advertisement
Add Comment
Please, Sign In to add comment