Added Snake Game
This commit is contained in:
parent
cb2401e72c
commit
3c2d01859a
180
OneLoneCoder_Snake.cpp
Normal file
180
OneLoneCoder_Snake.cpp
Normal file
@ -0,0 +1,180 @@
|
||||
/*
|
||||
OneLoneCoder.com - Command Line Snake
|
||||
"Give me a break, I'm on holiday..." - @Javidx9
|
||||
|
||||
Disclaimer
|
||||
~~~~~~~~~~
|
||||
I don't care what you use this for. It's intended to be educational, and perhaps
|
||||
to the oddly minded - a little bit of fun. Please hack this, change it and use it
|
||||
in any way you see fit. BUT, you acknowledge that I am not responsible for anything
|
||||
bad that happens as a result of your actions. However, if good stuff happens, I
|
||||
would appreciate a shout out, or at least give the blog some publicity for me.
|
||||
Cheers!
|
||||
|
||||
Background
|
||||
~~~~~~~~~~
|
||||
Classic Snake! Controls are Arrow keys Left & Right, eat food, grow larger, avoid self!
|
||||
|
||||
|
||||
Author
|
||||
~~~~~~
|
||||
Twitter: @javidx9
|
||||
Blog: www.onelonecoder.com
|
||||
|
||||
Video:
|
||||
~~~~~~
|
||||
https://youtu.be/e8lYLYlrGLg
|
||||
|
||||
Last Updated: 24/06/2017
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include <list>
|
||||
#include <thread>
|
||||
using namespace std;
|
||||
|
||||
#include <Windows.h>
|
||||
|
||||
int nScreenWidth = 120;
|
||||
int nScreenHeight = 30;
|
||||
|
||||
struct sSnakeSegment
|
||||
{
|
||||
int x;
|
||||
int y;
|
||||
};
|
||||
|
||||
int main()
|
||||
{
|
||||
// Create Screen Buffer
|
||||
wchar_t *screen = new wchar_t[nScreenWidth*nScreenHeight];
|
||||
for (int i = 0; i < nScreenWidth*nScreenHeight; i++) screen[i] = L' ';
|
||||
HANDLE hConsole = CreateConsoleScreenBuffer(GENERIC_READ | GENERIC_WRITE, 0, NULL, CONSOLE_TEXTMODE_BUFFER, NULL);
|
||||
SetConsoleActiveScreenBuffer(hConsole);
|
||||
DWORD dwBytesWritten = 0;
|
||||
|
||||
while(1)
|
||||
{
|
||||
// Reset to known state
|
||||
list<sSnakeSegment> snake = { {60,15},{61,15},{62,15},{63,15},{64,15},{65,15},{66,15},{67,15},{68,15},{69,15} };
|
||||
int nFoodX = 30;
|
||||
int nFoodY = 15;
|
||||
int nScore = 0;
|
||||
int nSnakeDirection = 3;
|
||||
bool bDead = false;
|
||||
bool bKeyLeft = false, bKeyRight = false, bKeyLeftOld = false, bKeyRightOld = false;
|
||||
|
||||
while (!bDead)
|
||||
{
|
||||
// Frame Timing, compensate for aspect ratio of command line
|
||||
auto t1 = chrono::system_clock::now();
|
||||
while ((chrono::system_clock::now() - t1) < ((nSnakeDirection % 2 == 1) ? 120ms : 200ms))
|
||||
{
|
||||
// Get Input,
|
||||
bKeyRight = (0x8000 & GetAsyncKeyState((unsigned char)('\x27'))) != 0;
|
||||
bKeyLeft = (0x8000 & GetAsyncKeyState((unsigned char)('\x25'))) != 0;
|
||||
|
||||
if (bKeyRight && !bKeyRightOld)
|
||||
{
|
||||
nSnakeDirection++;
|
||||
if (nSnakeDirection == 4) nSnakeDirection = 0;
|
||||
}
|
||||
|
||||
if (bKeyLeft && !bKeyLeftOld)
|
||||
{
|
||||
nSnakeDirection--;
|
||||
if (nSnakeDirection == -1) nSnakeDirection = 3;
|
||||
}
|
||||
|
||||
bKeyRightOld = bKeyRight;
|
||||
bKeyLeftOld = bKeyLeft;
|
||||
}
|
||||
|
||||
// ==== Logic
|
||||
|
||||
// Update Snake Position, place a new head at the front of the list in
|
||||
// the right direction
|
||||
switch (nSnakeDirection)
|
||||
{
|
||||
case 0: // UP
|
||||
snake.push_front({ snake.front().x, snake.front().y - 1 });
|
||||
break;
|
||||
case 1: // RIGHT
|
||||
snake.push_front({ snake.front().x + 1, snake.front().y });
|
||||
break;
|
||||
case 2: // DOWN
|
||||
snake.push_front({ snake.front().x, snake.front().y + 1 });
|
||||
break;
|
||||
case 3: // LEFT
|
||||
snake.push_front({ snake.front().x - 1, snake.front().y });
|
||||
break;
|
||||
}
|
||||
|
||||
// Collision Detect Snake V Food
|
||||
if (snake.front().x == nFoodX && snake.front().y == nFoodY)
|
||||
{
|
||||
nScore++;
|
||||
while (screen[nFoodY * nScreenWidth + nFoodX] != L' ')
|
||||
{
|
||||
nFoodX = rand() % nScreenWidth;
|
||||
nFoodY = (rand() % (nScreenHeight-3))+3;
|
||||
}
|
||||
|
||||
for (int i = 0; i < 5; i++)
|
||||
snake.push_back({ snake.back().x, snake.back().y });
|
||||
}
|
||||
|
||||
// Collision Detect Snake V World
|
||||
if (snake.front().x < 0 || snake.front().x >= nScreenWidth)
|
||||
bDead = true;
|
||||
if (snake.front().y < 3 || snake.front().y >= nScreenHeight)
|
||||
bDead = true;
|
||||
|
||||
// Collision Detect Snake V Snake
|
||||
for (list<sSnakeSegment>::iterator i = snake.begin(); i != snake.end(); i++)
|
||||
if (i != snake.begin() && i->x == snake.front().x && i->y == snake.front().y)
|
||||
bDead = true;
|
||||
|
||||
// Chop off Snakes tail :-/
|
||||
snake.pop_back();
|
||||
|
||||
// ==== Presentation
|
||||
|
||||
// Clear Screen
|
||||
for (int i = 0; i < nScreenWidth*nScreenHeight; i++) screen[i] = L' ';
|
||||
|
||||
// Draw Stats & Border
|
||||
for (int i = 0; i < nScreenWidth; i++)
|
||||
{
|
||||
screen[i] = L'=';
|
||||
screen[2 * nScreenWidth + i] = L'=';
|
||||
}
|
||||
wsprintf(&screen[nScreenWidth + 5], L"www.OneLoneCoder.com - S N A K E ! ! SCORE: %d", nScore);
|
||||
|
||||
|
||||
// Draw Snake Body
|
||||
for (auto s : snake)
|
||||
screen[s.y * nScreenWidth + s.x] = bDead ? L'+' : L'O';
|
||||
|
||||
// Draw Snake Head
|
||||
screen[snake.front().y * nScreenWidth + snake.front().x] = bDead ? L'X' : L'@';
|
||||
|
||||
// Draw Food
|
||||
screen[nFoodY * nScreenWidth + nFoodX] = L'%';
|
||||
|
||||
if (bDead)
|
||||
wsprintf(&screen[15 * nScreenWidth + 40], L" PRESS 'SPACE' TO PLAY AGAIN ");
|
||||
|
||||
// Display Frame
|
||||
WriteConsoleOutputCharacter(hConsole, screen, nScreenWidth * nScreenHeight, { 0,0 }, &dwBytesWritten);
|
||||
}
|
||||
|
||||
// Wait for space
|
||||
while ((0x8000 & GetAsyncKeyState((unsigned char)('\x20'))) == 0);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user