当前位置:网站首页>Super simple C language Snake does not flash screen double buffer
Super simple C language Snake does not flash screen double buffer
2022-06-22 10:38:00 【Ah Fei】
C Language is a snake
Today, I summarized the greedy snake I wrote before , Post to the blog , I don't even know if I lost it on my computer , If there is anything wrong, please give me some advice (*・ω< ) ヾ(◍°∇°◍)ノ゙
Greedy snake , The snake we saw was moving , In fact, it is constantly printing and displaying information on the screen , And constantly erase , It makes the snake look like it's moving , Here we need to use the statement : system("cls"), But this creates a problem , Printing cannot be completed at once , So it created Flash screen , The solution to the flash screen is Double buffering , I will introduce the double buffer later 
The main idea
Roughly prepare
- First, use a two-dimensional array
arrTo store the layout on the screen , use 0 To represent the blank space , The area where snakes can move , - Other foods 、 And the outermost walls are represented by numbers less than zero
- Our snake body is represented by a number greater than zero , Snake tail 1 Express , From the tail to the head , We can judge how much food the snake eats according to the snake head value
- Others are the direction keys on the keyboard , Head office 、 The total number of columns , We can use macros to define , In this way, the direction keys do not need to be written ASCII It's a yard , It is more obvious to use the identifier directly to know which direction it is , It's not easy to be wrong ;
- And one more 1 That's ok 2 Column to store the coordinate position of the snake head , By default, the snake has a length , So we should arrange the position of the snake in the array by default , Is to change the value of the position of the snake's body coordinates in the array to from the snake's tail 0 Increase the value of snake head in turn ,

Randomly produce food
- So now we start to randomly produce food , Use a function
produceFoodSpecially designed to randomly produce food - Randomly generate a vertical coordinate
verticalThe level oflevelv = rand() % ROW; l = rand() % COLJudgearr[v][l]Whether it is a blank area , If it doesn't regenerate , Until a blank area is generated
Choice of direction
- According to the key , Determine which direction , Just store the corresponding direction , Be careful : If you press in the opposite direction of the snake's movement , We should not deal with , Let the snake continue to move in this direction , Otherwise, there will be snakes eating themselves , Then you should die , This experience is better , Because there are a lot of times when people die like this, and the experience is not good
Snake moves
- So how do we make the snake move , First, we should give the snake a moving direction by default , And one more 1 That's ok 2 Column to store the coordinate position of the snake head , Know the moving direction of the snake head , And the coordinates , Then we know that the snake head will move to the next coordinate point , Then we can know what the next coordinate point is based on our array ( food , wall , Blank space , Snake-body. ), We can judge
- If it is Blank space : First , Let's make all the values greater than zero in the whole array reduce 1, The value of the original Snake tail is 1 Change into 0 , It becomes a blank area , The tail of the snake moves , Then we let Next coordinate point position Change the value of to the value of snakehead Add 1 , The snake head naturally moves to the next position
- If it is food : Change the value of the position of the next coordinate point to the value of the snakehead Add 1, So the snake moved , And it grows longer , Ate a food , Then call A function that produces food , Continue operation
- If it is A wall or a snake : Dead , According to the value of snake head , Figure out how much food you ate , How many points did you get , Show scores , Quit the game
Double buffering
It has been almost a year since I wrote this greedy snake , I also forgot the double buffer (>ω・* )ノφ(>ω<*) , I can only vaguely remember , Let me say I don't know how to say , I'm too fond of vegetables. ┗( ▔, ▔ )┛, But I have double buffering in my code , The specific double buffering can be seen in
http://m.bubuko.com/infodetail-582228.html
https://blog.csdn.net/weixinhum/article/details/72179593
You can go online to learn about , Okay , Look at the code , You are welcome to give advice on the inadequacies ─=≡Σ(((つ•̀ω•́)つ
The code is as follows :
/********************************************* * snake * use 0 Indicates a blank space , Use more than 0 Number of snakes , The number of snakes from tail to head increases in turn , Other ( wall , food ) Is represented by a negative number , * When it comes to food, it turns the value of the food point into the snakehead value +1, The point of food becomes the head of a snake , sign out * Not touching the food , The next point is empty , Just change the value of the next point into the snakehead value +1, * When the whole array is larger than 0 The value of all minus one , The snake tail becomes one naturally 0, It disappeared , In other cases, exit directly *@author zhoufei *@date 2018-06-03 *********************************************/
#include<stdio.h>
#include<windows.h>
#define FOOD -4 // food
#define WALL -9 // wall
#define COL 35
#define ROW 20
#define VK_UP 72 // The second value of the up, down, left and right direction keys , The arrow keys have two values , The first is 224, Namely 72,...
#define VK_DOWN 80
#define VK_LEFT 75
#define VK_RIGHT 77
#define int short // Put all the int Replace the type data with short Type saves space
/* Experience , Constant capitalization , Variables have multiple words underlined , Function multiple word initial lowercase , The remaining initials are capitalized */
// use word Make a special mark , Copy again
void fangXiangChoice(int arr[][COL]); // Enter the direction of
void start(int p[][COL]); // Initialization before starting
void print(int* a); // Output function , Output to the screen
void produceFood(int a[][COL]); // Produce food
void moveSnake(int (*arr)[COL],int * fx); // The movement of the snake
int head_v = 4,head_h = 5;
// The vertical and horizontal coordinates of the snake head , Use more than 0 Number of snakes , The number of snakes from tail to head increases in turn ,
int arr[ROW][COL];
int speed_snake = 5; // The speed at which the snake moves , Execute several cycles once to control
int fang_xiang = VK_RIGHT;// The direction of the snake's movement , Default right
int exitgame = 0;
HANDLE hOutput,hOutBuf; // Console screen buffer handle
HANDLE *houtpoint;
COORD coord = {
1,0};
DWORD bytes = 0;
char data[ROW][COL];
int zhixiang_hOutput = 0; // The pointer points to the two buffers in turn , Achieve double buffering
void main()
{
int k;
start(arr);
produceFood(arr);
puts(" hi ~ Welcome to the world of snake eaters ! Please sit down , It's time to drive ~");
Sleep(2000); // Sleep 2 second
system("cls");
hOutBuf = CreateConsoleScreenBuffer(
GENERIC_WRITE, // Define that the process can write data to the buffer
FILE_SHARE_WRITE, // Define buffer sharable write permissions
NULL,
CONSOLE_TEXTMODE_BUFFER,
NULL
);
hOutput = CreateConsoleScreenBuffer(
GENERIC_WRITE, // Define that the process can write data to the buffer
FILE_SHARE_WRITE, // Define buffer sharable write permissions
NULL,
CONSOLE_TEXTMODE_BUFFER,
NULL
);
SetConsoleTitle(TEXT(" snake "));
SMALL_RECT rc = {
0,0,COL+10,ROW+4}; // Set window size , Width and height
SetConsoleWindowInfo(hOutput,1,&rc);
SetConsoleWindowInfo(hOutBuf,1,&rc);
// Hide the cursor of the two buffers
CONSOLE_CURSOR_INFO cci;
cci.bVisible = 0;
cci.dwSize =1;
SetConsoleCursorInfo(hOutput, &cci);
SetConsoleCursorInfo(hOutBuf, &cci);
while(1)
{
if(kbhit())
{
fangXiangChoice(arr);
moveSnake(arr,&fang_xiang);
print(arr[0]);
}
if(k++ % speed_snake == 0)
{
moveSnake(arr,&fang_xiang);
print(arr[0]);
}Sleep(40);
}
}
void fangXiangChoice(int arr[][COL])
{
int key1,key2;
key1 = getch();
if(key1 == 27)//ESC Build exit
exitgame = 1;
if(key1 == 224)
{
key2 = getch();
switch(key2)
{
case VK_UP: if(fang_xiang != VK_DOWN) fang_xiang = VK_UP; // If you are moving down , The snake can't move up , The following are the same
break;
case VK_DOWN: if(fang_xiang != VK_UP) fang_xiang = VK_DOWN;
break;
case VK_LEFT: if(fang_xiang != VK_RIGHT) fang_xiang = VK_LEFT;
break;
case VK_RIGHT: if(fang_xiang != VK_LEFT) fang_xiang = VK_RIGHT;
}
}
}
void start(int p[][COL])
{
int i,j;
p[head_v][head_h] = 2; // Initialize snakehead , Snake-body.
p[head_v][head_h-1] = 1;
for(i = 0; i < ROW; i++)
{
for(j = 0; j < COL; j++)
{
if(i == 0 || i == ROW-1 || j == 0 || j == COL-1)
p[i][j] = WALL; // Initialize the wall
}
}
}
void produceFood(int a[][COL])
{
int food_v,food_h;
srand(time(NULL));
food_v = rand() % ROW;
food_h = rand() % COL;
while(a[food_v][food_h] != 0)
{
food_v = rand() % ROW;
food_h = rand() % COL;
}
a[food_v][food_h] = FOOD;
}
/** // The vertical and horizontal coordinates of the snake head , Use more than 0 Number of snakes , The number of snakes from tail to head increases in turn , // When it comes to food, it turns the value of the food point into the snakehead value +1, The point of food becomes the head of a snake , sign out // Not touching the food , The next point is empty , Just change the value of the next point into the snakehead value +1, // When the whole array is larger than 0 The value of all minus one , The snake tail becomes one naturally 0, It disappeared , In other cases, exit directly */
void moveSnake(int (*arr)[COL],int * fx) // Move the snake according to the incoming direction
{
int i,j,eat_food = 0; // by 0 No food
int temp = arr[head_v][head_h]; // Record the current snakehead value
if(*fx == VK_UP)
{
if(arr[head_v - 1][head_h] == 0) head_v--;
else if(arr[head_v - 1][head_h] == FOOD)
head_v--,eat_food = 1; // We've got food , The snake doesn't need to lose one
else exitgame = 1; // The only other cases are hitting the wall and eating the snake
}if(*fx == VK_DOWN)
{
if(arr[head_v + 1][head_h] == 0) head_v++;
else if(arr[head_v + 1][head_h] == FOOD)
head_v++,eat_food =1;
else exitgame = 1;
}if(*fx == VK_LEFT)
{
if(arr[head_v][head_h -1] == 0) head_h--;
else if(arr[head_v][head_h -1] == FOOD)
head_h--,eat_food = 1;
else exitgame = 1;
}if(*fx == VK_RIGHT)
{
if(arr[head_v][head_h + 1] == 0) head_h++;
else if(arr[head_v][head_h + 1] == FOOD)
head_h++,eat_food = 1;
else exitgame = 1;
}
/** If the number of food not eaten is greater than zero, it shall be reduced by one */
arr[head_v][head_h] = temp+1;
if(!eat_food)
{
for(i = 0; i < ROW; i++)
{
for(j = 0; j < COL; j++)
{
if(arr[i][j] > 0) arr[i][j] = arr[i][j] - 1;
}
}
}
else
produceFood(arr); // We've got food , Produce a food
}
void print(int* p)
{
int i,j;
char shuo_ming1[] = " Please press the direction key ↑ ↓ ← → Control up, down, left and right ";
char shuo_ming2[] = " Pressing the arrow keys continuously will accelerate , Exit Click ESC key ";
for(i = 0; i < ROW; i++)
{
for(j = 0; j < COL; j++,p++)
{
if(*p == WALL)
data[i][j] = '*'; //printf("■"); // Wall wall
if(*p == 0)
data[i][j] = ' '; //printf(" ");
if(*p > 0) // The snake
{
if(i == head_v && j == head_h) data[i][j] = '0';//printf("⊙");
else data[i][j] = '@'; //printf("●");
}
if(*p == FOOD)
data[i][j] = '@'; //printf("●");
}//printf("\n");
}
// Here is the buffer code
zhixiang_hOutput = !zhixiang_hOutput ;
if(!zhixiang_hOutput)
{
houtpoint = &hOutput;
}
else
{
houtpoint = &hOutBuf;
}
coord.Y = 1;
WriteConsoleOutputCharacterA(*houtpoint,shuo_ming1,strlen(shuo_ming1), coord,&bytes);
coord.Y++; WriteConsoleOutputCharacterA(*houtpoint,shuo_ming2,strlen(shuo_ming2), coord,&bytes);
for(i = 0; i < ROW; i++)
{
coord.Y++ ;
WriteConsoleOutputCharacterA(*houtpoint,(char *)data[i],COL, coord,&bytes);
}
if(exitgame)
{
char score[20];// The score is the food eaten by the snake multiplied by 3
sprintf(score," Your score is :%d",(arr[head_v][head_h]-2)*3);
coord.Y++;
WriteConsoleOutputCharacterA(*houtpoint,score,strlen(score), coord,&bytes);
SetConsoleActiveScreenBuffer(*houtpoint);
getch();exit(0);
}
SetConsoleActiveScreenBuffer(*houtpoint);
}
边栏推荐
- 字节二面:Redis主节点的Key已过期,但从节点依然读到过期数据是为什么?怎么解决?
- php 数据库 mysql提问
- HMS core news industry solution: let technology add humanistic temperature
- 每日一题day5-1636. 按照频率将数组升序排序
- 符合我公司GIS开源解决方案的探讨
- Byte 3: do you know what Eureka is?
- Duxiaoyong, head of virtual teaching and Research Office of database course: Based on the major needs of domestic databases, explore a new mode of course system construction
- 工作中的帕累托定律:关注结果,而不是输出
- TCP异常连接
- Learn to view object models with VisualStudio developer tools
猜你喜欢

Denso China adopts Oracle HCM cloud technology solution to accelerate the digital transformation of human resources

喜讯丨敏捷科技入选《2022年中国数字安全百强报告》

投资交易管理

Tiktok announces data storage on Oracle server!

iNFTnews | 观点:市场降温或是让NFT应用走向台前的机会
![[deep learning] great! The new attention makes the model 2-4 times faster!](/img/03/37584c9f9d6b16e5a5edc87e3eaa6b.png)
[deep learning] great! The new attention makes the model 2-4 times faster!

2022各大厂最新总结的软件测试宝典,看完不怕拿不到offer

Web Configuration of Visual Studio Code

Software project management 8.3 Agile project quality activities

The future of Dao: an organization primitive for building Web3
随机推荐
批量创建/删除文件、文件夹、修改文件名 后缀名
外贸专题:外贸邮件营销模板
超简单的C语言贪吃蛇 不闪屏 双缓冲
每日一题day5-1636. 按照频率将数组升序排序
Niuke.com Huawei question bank (31~40)
Discussion on the open source GIS solution of our company
thinkphp5.0.24反序列化漏洞分析
定金预售的规则思路详解
无线802.1x认证简介及配置方法
今天,SysAK 是如何实现业务抖动监控及诊断?&手把手带你体验Anolis OS|第25-26期
php 数据库 mysql提问
Basic principles of the Internet
Construction details of Danzhou clean animal laboratory
Target detection / segmentation training using pytorch mask RCNN
Tiktok announces data storage on Oracle server!
Pule frog VR typhoon escape experience VR disaster self rescue simulation system VR popular science knowledge equipment
Detailed explanation of rules and ideas for advance sale of deposit
Start from the principle of MVC and knock on an MVC framework to bring you the pleasure of being a great God
网络中connect的作用
学会用VisualStudio开发人员工具查看对象模型