不费话,直接上代码。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);
}