当前位置:网站首页>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
 Insert picture description here

The main idea

Roughly prepare

  1. First, use a two-dimensional array arr To store the layout on the screen , use 0 To represent the blank space , The area where snakes can move ,
  2. Other foods 、 And the outermost walls are represented by numbers less than zero
  3. 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
  4. 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 ;
  5. 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 ,
     Insert picture description here

Randomly produce food

  1. So now we start to randomly produce food , Use a function produceFood Specially designed to randomly produce food
  2. Randomly generate a vertical coordinate vertical The level of levelv = rand() % ROW; l = rand() % COL Judge arr[v][l] Whether it is a blank area , If it doesn't regenerate , Until a blank area is generated

Choice of direction

  1. 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

  1. 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
  2. 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
  3. 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
  4. 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);
}

原网站

版权声明
本文为[Ah Fei]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/173/202206221014083560.html