操作说明:通过键盘上的左键和右键控制“蛇头”向左或者向右移动,基本玩法和游戏规则与贪吃蛇是一致的。(想象自己是“蛇头”,面向前面进行左右操作)
#include <cstdlib>
#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
char *screen = new char[nScreenWidth * nScreenHeight];
for (int i = 0; i != nScreenWidth * nScreenHeight; i++)
screen[i] = ' ';
HANDLE hConsole = CreateConsoleScreenBuffer(GENERIC_READ | GENERIC_WRITE, 0, NULL, CONSOLE_TEXTMODE_BUFFER, NULL);
SetConsoleActiveScreenBuffer(hConsole);
DWORD dwBytesWritten = 0;
while (1)
{
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)
{
// Timing & Input
//this_thread::sleep_for(200ms);
//Get Input
auto t1 = chrono::system_clock::now();
while ((chrono::system_clock::now() - t1) < ((nSnakeDirection % 2 == 1) ? 120ms : 200ms))
{
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;
}
bKeyLeftOld = bKeyLeft;
bKeyRightOld = bKeyRight;
}
//Game Logic
//Updata Snake position
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;
}
//Collison Dection
//For broder
if (snake.front().x < 0 || snake.front().x > nScreenWidth)
bDead = true;
if (snake.front().y < 3 || snake.front().y >= nScreenHeight)
bDead = true;
//For Food
if (snake.front().x == nFoodX && snake.front().y == nFoodY)
{
nScore++;
while (screen[nFoodY * nScreenWidth + nFoodX] != ' ')
{ //generate a "food" within the border
nFoodX = rand() % nScreenWidth;
nFoodY = (rand() % (nScreenHeight - 3)) + 3;
}
for (int i = 0; i != 5; i++)
{
snake.push_back({snake.back().x, snake.back().y});
}
}
//For 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 pff Snake's tail
snake.pop_back();
//Display to player
//Clear Screen
for (int i = 0; i != nScreenWidth * nScreenHeight; i++)
screen[i] = ' ';
//Draw Stats & Border
for (int i = 0; i != nScreenWidth; i++)
{
screen[i] = '=';
screen[2 * nScreenWidth + i] = L'=';
}
wsprintf(&screen[nScreenWidth + 5], " Game name:Snake Author:Hechun Jiang YOUR SCORES:%d ", nScore);
//Draw Snake Body
for (auto s : snake)
screen[s.y * nScreenWidth + s.x] = bDead ? '+' : 'O';
//Draw Snake Head
screen[snake.front().y * nScreenWidth + snake.front().x] = bDead ? 'X' : '@';
//Draw Food
screen[nFoodY * nScreenWidth + nFoodX] = '%';
if (bDead)
wsprintf(&screen[15 * nScreenWidth + 40], " if you want to try again, please press 'SPACE' ");
//Display Frame
WriteConsoleOutputCharacter(hConsole, screen, nScreenHeight * nScreenWidth, {0, 0}, &dwBytesWritten);
}
//check 'space'
while ((0x8000 & GetAsyncKeyState((unsigned char)('\x20'))) == 0)
;
}
return 0;
}