c++双缓存技术实现控制台不闪屏
贪吃蛇为例
实现双缓存技术实现控制台不闪屏,以上次写的贪吃蛇为例子。
链接:简单的贪吃蛇
话不多说,上代码。
#include<iostream>
#include<Windows.h>
#include<conio.h>
using namespace std;
typedef struct Node
{
int Data[2]; //数据域
struct Node *next; //指针域
}Snake;
Snake * NewSnake(){//初始化蛇
Snake *head, *p,*tail;
head = (Snake*)malloc(sizeof(Snake));
p = (Snake*)malloc(sizeof(Snake));
tail = (Snake*)malloc(sizeof(Snake));
if (head == NULL || p == NULL || tail == NULL)
return head;
head->Data[0] = 10;
head->Data[1] = 10;
p->Data[0] = 11;
p->Data[1] = 10;
tail->Data[0] = 12;
tail->Data[1] = 10;
head->next = p;
p->next = tail;
tail->next = NULL;
return head;
}
void PrintSnake(Snake *head,int Map[20][20])
{//载入地图
Snake* p = head;
if (p != NULL){
while (p != NULL)
{
Map[p->Data[0]][p->Data[1]] = 2;
p = p->next;
}
}
}
void Move(Snake * head,bool & GameState, int Map[20][20], int cx, int cy){
//改变方向,刷新数据
Snake *one = head;
Snake *two = (Snake*)malloc(sizeof(Snake));
two->Data[0] = one->Data[0];
two->Data[1] = one->Data[1];
two->next = one->next;
one->Data[0] += cx;
one->Data[1] += cy;
one->next = two;
if (Map[one->Data[0]][one->Data[1]] == 3)
{//如果吃到豆子,则产生新的豆子
Map[one->Data[0]][one->Data[1]] = 2;
while (true)
{
int Dx = rand() % 20;
int Dy = rand() % 20;
if (Map[Dx][Dy] == 0){
Map[Dx][Dy] = 3;
break;
}
}
}
else if (Map[one->Data[0]][one->Data[1]] == 0)
{//什么都没有吃到
Map[one->Data[0]][one->Data[1]] = 2;
Snake *delone, *deltwo;
delone = one;
deltwo = one->next;
while (deltwo->next != NULL){
delone = deltwo;
deltwo = delone->next;
}
Map[deltwo->Data[0]][deltwo->Data[1]] = 0;
free(deltwo);
delone->next = NULL;
}
else{//吃到墙壁或是自己
GameState = false;
}
}
void MapPrint(int Map[20][20]){
//绘制地图
for (int i = 0; i < 20; i++)
{
for (int j = 0; j < 20; j++)
{
if (Map[i][j] == 0){ cout << " "; }
else if (Map[i][j] == 1){ cout << "■"; }
else if (Map[i][j] == 2){ cout << "●"; }
else if (Map[i][j] == 3){ cout << "★"; }
}
cout << endl;
}
}
void main(){
//HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
//CONSOLE_CURSOR_INFO CursorInfo;
//GetConsoleCursorInfo(handle, &CursorInfo);//获取控制台光标信息
//CursorInfo.bVisible = false; //隐藏控制台光标
//SetConsoleCursorInfo(handle, &CursorInfo);
int Map[20][20] = {//地图的初始化
{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
};
bool GameState = true;
char State = 'x';
Snake *MySnake = NewSnake();//实体化蛇
PrintSnake(MySnake,Map);
//载入地图和蛇
MapPrint(Map);
HANDLE hOutput;
COORD coord = { 0, 0 };
hOutput = GetStdHandle(STD_OUTPUT_HANDLE);
//创建新的缓冲区
HANDLE hOutBuf = CreateConsoleScreenBuffer(
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
CONSOLE_TEXTMODE_BUFFER,
NULL
);
//设置新的缓冲区为活动显示缓冲
SetConsoleActiveScreenBuffer(hOutBuf);
//隐藏两个缓冲区的光标
CONSOLE_CURSOR_INFO cci;
cci.bVisible = 0;
cci.dwSize = 1;
SetConsoleCursorInfo(hOutput, &cci);
SetConsoleCursorInfo(hOutBuf, &cci);
//双缓冲处理显示
DWORD bytes = 100;
char data[1600];
while (GameState){
Sleep(200);//刷新时间,单位毫秒
//system("cls");
MapPrint(Map);
char Control;
if (_kbhit()){
Control = _getch();
if ((Control == 'w' && State != 's') || (Control == 's' && State != 'w') || (Control == 'a' && State != 'd') || (Control == 'd' && State != 'a'))
{//判断是否可以操作
State = Control;
}
}
switch (State)
{
case 'w':
Move(MySnake, GameState, Map, -1, 0);
break;
case 'a':
Move(MySnake, GameState, Map, 0, -1);
break;
case 's':
Move(MySnake, GameState, Map, 1, 0);
break;
case 'd':
Move(MySnake, GameState, Map, 0, 1);
break;
default:break;
}
ReadConsoleOutputCharacterA(hOutput, data, 1600, coord, &bytes);
WriteConsoleOutputCharacterA(hOutBuf, data, 1600, coord, &bytes);
system("cls");
}
//1.读取按键
//2.根据下一步修改链表数据并更改地图数据
//3.判断是否结束如果没有查看是否要刷新地图数据,刷新/不刷新
//4.地图刷新
system("cls");
cout << "游戏结束" << endl;
cout<< "按任意键退出" << endl;
ReadConsoleOutputCharacterA(hOutput, data, 1600, coord, &bytes);
WriteConsoleOutputCharacterA(hOutBuf, data, 1600, coord, &bytes);
system("pause");
}
PS:欢迎交流讨论。