不费话,直接上代码。VC++ 6.0可以完美运行,VS2015等版本需要做点修改,请按提示将“scanf”这些函数改成“_scanf”这样的形式即可。
不闪屏的原理部分请参考这篇文章
代码只有两百多行,很多地方都加上了注释,有疑问可以留言
#include "stdio.h"
#include "stdlib.h"
#include <Windows.h>
#include <time.h>
#include <conio.h>
#define LENGTH 15
int i;
HANDLE hOutput, hOutBuf;
HANDLE *houtpoint;
COORD coord = { 0,0 };
DWORD bytes = 0;
unsigned char data[LENGTH + 2][LENGTH + 2];
bool showcircle = false;
char direction = 'd';
int headx = 2, heady = 0;
int foodx = 0, foody = 0;
bool running = true;
char level[LENGTH];
int gamelevel = 1;
int eatcount = 0;
struct SnakeBody
{
int x[LENGTH*LENGTH];
int y[LENGTH*LENGTH];
}snake;
int snakelength = 3;
void show()
{
showcircle = !showcircle;
if (showcircle)
{
houtpoint = &hOutput;
}
else
{
houtpoint = &hOutBuf;
}
coord.X = 50;
coord.Y = 3;
sprintf(level, "level:%2d", gamelevel);
WriteConsoleOutputCharacterA(*houtpoint, level, strlen(level), coord, &bytes);
for (i = 0; i < LENGTH + 2; i++)
{
coord.X = 44;
coord.Y = i + 5;
WriteConsoleOutputCharacterA(*houtpoint, (char*)data[i], (LENGTH + 2), coord, &bytes);
}
SetConsoleActiveScreenBuffer(*houtpoint);
Sleep(200 / gamelevel);
}
void showover()
{
showcircle = !showcircle;
if (showcircle)
{
houtpoint = &hOutput;
}
else
{
houtpoint = &hOutBuf;
}
memset(data, 255, (LENGTH + 2)*(LENGTH + 2));
for (i = 0; i < LENGTH + 2; i++)
{
coord.X = 44;
coord.Y = i + 5;
WriteConsoleOutputCharacterA(*houtpoint, (char*)data[i], (LENGTH + 2), coord, &bytes);
}
coord.X = 44 + LENGTH / 2 - 3;
coord.Y = 5;
WriteConsoleOutputCharacterA(*houtpoint, "GAME OVER", 9, coord, &bytes);
SetConsoleActiveScreenBuffer(*houtpoint);
}
void draw()
{
memset(data, 255, (LENGTH + 2)*(LENGTH + 2));
for (i = 0; i < (LENGTH + 2); i++)
{
data[0][i] = 205;
data[i][0] = 186;
data[LENGTH + 1][i] = 205;
data[i][LENGTH + 1] = 186;
}
data[0][0] = 201;
data[LENGTH + 1][0] = 200;
data[0][(LENGTH + 2) - 1] = 187;
data[LENGTH + 1][(LENGTH + 2) - 1] = 188;
for (i = 0; i < snakelength; i++)
{
data[snake.y[i] + 1][(snake.x[i] + 1)] = 233;
}
data[foody + 1][(foodx + 1)] = 236;
}
void generatefood()
{
bool dogenerate = true;
while (dogenerate)
{
srand((unsigned)time(NULL));
foodx = rand() % LENGTH;
foody = rand() % LENGTH;
dogenerate = false;
for (i = 0; i < snakelength; i++)
{
if (snake.y[i] == foody && foodx == snake.x[i])
{
dogenerate = true;
}
}
}
}
bool control()
{
char getkeych;
if (kbhit())
{
char key = _getch();
switch (key)
{
case 'd':
case 's':
case 'a':
case 'w':direction = key; break;
}
}
switch (direction)
{
case 'd':headx++; break;
case 's':heady++; break;
case 'a':headx--; break;
case 'w':heady--; break;
}
if (headx < 0)
{
headx = LENGTH - 1;
}
else if (headx > LENGTH - 1)
{
headx = 0;
}
if (heady < 0)
{
heady = LENGTH - 1;
}
else if (heady > LENGTH - 1)
{
heady = 0;
}
for (i = 0; i < snakelength; i++)
{
if (snake.x[i] == headx && snake.y[i] == heady)
{
return false;
}
}
if (foodx == headx && foody == heady)
{
snakelength++;
snake.x[snakelength - 1] = headx;
snake.y[snakelength - 1] = heady;
generatefood();
eatcount++;
gamelevel = eatcount / 10 + 1;
}
for (i = 0; i < snakelength - 1; i++)
{
snake.x[i] = snake.x[i + 1];
snake.y[i] = snake.y[i + 1];
}
snake.x[snakelength - 1] = headx;
snake.y[snakelength - 1] = heady;
return true;
}
void main()
{
SetConsoleOutputCP(437);
hOutBuf = CreateConsoleScreenBuffer(
GENERIC_WRITE,
FILE_SHARE_WRITE,
NULL,
CONSOLE_TEXTMODE_BUFFER,
NULL
);
hOutput = CreateConsoleScreenBuffer(
GENERIC_WRITE,
FILE_SHARE_WRITE,
NULL,
CONSOLE_TEXTMODE_BUFFER,
NULL
);
CONSOLE_CURSOR_INFO cci;
cci.bVisible = 0;
cci.dwSize = 1;
SetConsoleCursorInfo(hOutput, &cci);
SetConsoleCursorInfo(hOutBuf, &cci);
snake.x[2] = 2; snake.y[2] = 0;
snake.x[1] = 1; snake.y[1] = 0;
snake.x[0] = 0; snake.y[0] = 0;
generatefood();
while (running)
{
if (!control())
{
showover();
break;
}
draw();
show();
}
scanf("%d", &i);
}