Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // Snake.cpp : This file contains the 'main' function. Program execution begins and ends there.
- //
- #include <iostream>
- #include <conio.h>
- #include <windows.h>
- #include <queue>
- #include <time.h>
- using namespace std;
- bool gameOver;
- const int width = 50;
- HANDLE hScr;
- const int height = 20;
- const int startx = width / 2 + 1;
- const int starty = height / 2 + 1;
- enum eDirecton { STOP = 0, LEFT, RIGHT, UP, DOWN };
- int currentx = startx;
- int currenty = starty;
- queue<eDirecton> Tail;
- int fruitX, fruitY, score;
- int tailX, tailY;
- const char WALL = '#';
- const char FRUIT = 'X';
- const char SNAKE = (char)219;
- const char HEADLEFT = '<';
- const char HEADRIGHT = '>';
- const char HEADUP = '^';
- const char HEADDOWN = 'v';
- eDirecton dir;
- // Create a coordinate for positioning the cursor in the console
- COORD GetPos(int x, int y)
- {
- COORD Pos = { x, y };
- return Pos;
- }
- // Returns the character at the specified coordiate. This allows us to check what the snake ran into
- int GetCharAt(HANDLE h, COORD Pos)
- {
- const int BUFFSIZE = 1;
- char buf[BUFFSIZE + 1] = "";
- DWORD numb_read;
- ReadConsoleOutputCharacter(hScr, (LPTSTR) buf, (DWORD) BUFFSIZE, Pos, (LPDWORD) &numb_read);
- return buf[0];
- }
- // Resets the game
- void NewGame()
- {
- // Not moving
- dir = STOP;
- //Reset the tail queue (FIFI collection)
- queue <eDirecton> ResetQ;
- swap(Tail, ResetQ);
- score = 0;
- //Reset the current position
- currentx = startx;
- currenty = starty;
- // Set the tail coordinates to the same location (since it's size is 1)
- tailX = currentx;
- tailY = currenty;
- // clear the screen
- system("cls");
- // set the random seed
- srand(time(NULL));
- //Draw the walls
- for (int i = 0; i <= width + 2; i++)
- cout << WALL;
- for (int i = 1; i < height + 1; ++i)
- {
- SetConsoleCursorPosition(hScr, GetPos(0, i));
- cout << WALL;
- SetConsoleCursorPosition(hScr, GetPos(width + 2, i));
- cout << WALL;
- }
- SetConsoleCursorPosition(hScr, GetPos(0, height + 1));
- for (int i = 0; i <= width + 2; i++)
- cout << WALL;
- // Draw the star position of the snake
- SetConsoleCursorPosition(hScr, GetPos(currentx, currenty));
- cout << SNAKE;
- // Draw the first fruit
- do
- {
- fruitX = rand() % width + 1;
- fruitY = rand() % height + 1;
- SetConsoleCursorPosition(hScr, GetPos(fruitX, fruitY));
- } while (GetCharAt(hScr, GetPos(fruitX, fruitY)) != ' ');
- cout << FRUIT;
- SetConsoleCursorPosition(hScr, GetPos(0, height + 4));
- cout << "Score: " << score << " ";
- }
- bool UpdatePosition(eDirecton dir)
- {
- char cHEAD;
- if (dir == STOP)
- return true;
- if (Tail.size() > 0)
- {
- SetConsoleCursorPosition(hScr, GetPos(currentx, currenty));
- cout << SNAKE;
- }
- // Push the current direction to our Tail queue (FIFO collection);
- Tail.push(dir);
- // Based on the direction, change the coordinates
- switch (dir)
- {
- case LEFT:
- --currentx;
- cHEAD = HEADLEFT;
- break;
- case RIGHT:
- ++currentx;
- cHEAD = HEADRIGHT;
- break;
- case UP:
- --currenty;
- cHEAD = HEADUP;
- break;
- case DOWN:
- ++currenty;
- cHEAD = HEADDOWN;
- break;
- }
- // Check the character at the new coordiantes so we can see if we hit the wall, tail, fruit or an empty space
- int c = GetCharAt(hScr, GetPos(currentx, currenty));
- // We hit the fruit!
- if (c == (int)FRUIT)
- {
- score += 10;
- do
- {
- fruitX = rand() % width + 1;
- fruitY = rand() % height + 1;
- SetConsoleCursorPosition(hScr, GetPos(fruitX, fruitY));
- } while(GetCharAt(hScr, GetPos(fruitX, fruitY)) != ' ');
- cout << FRUIT;
- SetConsoleCursorPosition(hScr, GetPos(0, height + 4));
- cout << "Score: " << score << " ";
- }
- else if (c != ' ') // if it is not a space, we hit the wall or the tail. We lost!!!
- {
- return false;
- }
- else // This must be a empty space. The tail doesn't grow, so we remove the end of the tail
- {
- // Set the position to the last character in the tail and set it to blank;
- SetConsoleCursorPosition(hScr, GetPos(tailX, tailY));
- cout << ' ';
- // 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
- switch (Tail.front())
- {
- case LEFT:
- tailX--;
- break;
- case RIGHT:
- tailX++;
- break;
- case UP:
- tailY--;
- break;
- case DOWN:
- tailY++;
- break;
- }
- Tail.pop(); // Remove the last item for the tail
- }
- // Now add the head character
- SetConsoleCursorPosition(hScr, GetPos(currentx, currenty));
- cout << cHEAD;
- return true;
- }
- void Input()
- {
- if (_kbhit())
- {
- char C = _getch();
- if (C == -32) // Extended key pressed
- {
- C = _getch();
- switch (C)
- {
- case 'H': // Up Arrow key pressed
- dir = UP;
- break;
- case 'P': // Down Arrow key pressed
- dir = DOWN;
- break;
- case 'M': // Right Arrow key pressed
- dir = RIGHT;
- break;
- case 'K': // Left Arrow key pressed
- dir = LEFT;
- break;
- }
- }
- else if (C == 'x' || C == 'X')
- gameOver = true;
- }
- }
- int main()
- {
- hScr = GetStdHandle(STD_OUTPUT_HANDLE);
- // remove the flickering cursor
- CONSOLE_CURSOR_INFO info;
- info.dwSize = 100;
- info.bVisible = FALSE;
- SetConsoleCursorInfo(hScr, &info);
- // Start a new game
- NewGame();
- gameOver = false;
- while (!gameOver)
- {
- Input();
- // Update the position
- if (!UpdatePosition(dir))
- {
- // If UpdatePosition returns false, the game is over
- HANDLE h = GetStdHandle(STD_OUTPUT_HANDLE);
- SetConsoleCursorPosition(h, GetPos(0, height + 6));
- cout << "GAME OVER!!! Play Again? (Y/N)";
- char x = NULL;
- while (x != 'Y' && x != 'N')
- x = toupper(_getch());
- if (x == 'Y')
- {
- NewGame();
- continue;
- }
- return 0;
- }
- Sleep(100);
- }
- CloseHandle(hScr);
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment