# C language (circular list) to achieve the basic function of snake

2020-11-09 12:58:25

## The general idea

The coordinates of a snake are stored in a circular list , And then use it gotoxy（） function （ You can position the cursor at the specified position ）, At this point, according to the coordinates of the snake output “@”, More output can produce a snake . Move the snake by traversing the circular list , Insert elements to the circular list , It produces a snake lengthening effect . The following is the function of each function

1. Snake map function map（）
2. The movement of the snake move（）,up（）,left（） Such as function
3. Produce food food（） And eating food eat_food()
4. The lengthening effect that snakes produce when they eat food snake_link() function
5. Judge the death of the snake , They are hitting the wall hit_wall() And suicide suicide()

## 1. Snake map function map（）

The game map uses areas that should be closed , Take an array a, Initialize the array to 0, Assign the edge of the game wall to 1, When array is 0, Output " ", The array is 1, Output “#”, Generate a map .
The code is as follows ：

``````void map()   // Create a map of snakes
{

int a = {

0};
int i,j;
for(i = 0; i < 50; i++)
{

a[i] = 1;
a[i] =1;
}
for(i = 0; i < 25; i++)
{

a[i] = 1;
a[i] =1;
}
for(i = 0; i < 25; i++)
for(j = 0; j < 50; j++)
{

if(j%50 == 0)
printf("\n");
if(a[i][j] == 0)
{

printf(" ");
}
else
{

printf("#");
}
}
}
``````

## 2. The movement of the snake move（）,up（）,left（） Such as function

move() Function is used to change the snake's top, bottom, left and right switch Function to solve （ In the following code ch Is a global variable ）
The code is as follows

``````void move(struct snake *p)   // The snake's moving function
{

while(1)
{

ch = getch();
switch(ch)
{

case 'W':p = up(p);break;
case 'A':p = left(p);break;
case 'D':p = right(p);break;
case 'S':p = down(p);break;
}
}
}

``````

What makes the snake move is that we mainly change the coordinates of the snake , At this point, once the snake head moves, we use gotoxy（） Function to output “@”, And then output at the tail of the snake “ ”, The effect of the snake's movement can be produced by cycling , The snake's top, bottom, left, right, and left only need to move in one direction to a single coordinate x or y Make changes , Then save the changed coordinates into the loop list . Moving functions mainly include up（）,left（） etc. , Because it's almost the same , It's only for up（） Function
The code is as follows

``````struct snake *up(struct snake *p) // Move up
{

int x;
int y;
x = p->pre->x;                 // Assign snake head coordinates to x,y
y = p->pre->y;
while(p)                      // Traversal of a circular list , That is, the traversal of snakes
{

Sleep(SNAKE_SPEED);        // The speed at which the snake moves
y--;                       // If you move up, you just subtract the ordinate , You can achieve the effect of the snake moving up
gotoxy(p->x,p->y);         // To the tail of the snake , Output “ ” The snake tail disappears
printf(" ");
gotoxy(x, y);              // Position to snakehead output ,"@", Combined with the disappearance of the snake tail above, the snake head is printed again , Produces the effect of Snake Movement
printf("@");
suicide(p,x,y);            // Judge whether the head of the snake hit the body of the snake
p = p->next;               // Change the coordinates of the snake head to the next
p->pre->x = x;             // At this point, change the head of the previous snake into the tail of the snake , Through continuous traversal to produce the effect of continuous movement
p->pre->y = y;
food();                    // Produce food
eat_food(p,x,y);           // Judge whether you have food
hit_wall(y);               // Judge if you hit the wall
if(kbhit()) break;        // Determine whether there is a key input , If yes, change the direction of the snake's movement
}

return p;
}

``````

## 3. Produce food food（） And eating food eat_food()

Food and eating food , The random number is used to produce food , Producing a food x,y Coordinates are stored in global variables food_xy In an array , The use of gotoxy（food_xy,food_xy） Randomly produce food
The code is as follows

``````void food()                       // Produce food
{

int i;
if(!flag)                     // according to flag To determine whether there is food on the map
{

srand( (unsigned)time( NULL ) );
for( i = 0; i < 2; i++ )  // Yes food_(x,y) To assign random values to
{

food_xy[i] = rand()%24+2;
while(food_xy == 1 || food_xy == 25) // these two items. while To prevent food
food_xy = rand()%24+2;             // The coordinates of the map overlap the edge of the map
while(food_xy >= 49 || food_xy == 1)
food_xy =rand()%24+2;
}
gotoxy(food_xy,food_xy);  // Print food
printf("*");
flag = 1;
}
}
``````

Eat food eat_food(), Then we just need to determine whether the snake head overlaps the coordinates of the food , If it overlaps, it means the snake has eaten food
The code is as follows

``````void eat_food(struct snake *p,int x, int y)           // Snakes eat food , That is, mainly for the snake head x,y Coordinates and
{

//food_xy To match and compare , If they are the same, they will adjust
if(x == food_xy && y == food_xy)            //snake_link Function
{

flag = 0;                                     // Indicates that the food was eaten , Ready to regenerate food
printSnake(p);
gotoxy(8,0);
score = score + 1;                            // score
printf("%d",score);
}
}

``````

# 4. The lengthening effect that snakes produce when they eat food snake_link() function

Snake's lengthening , When the snake gets the food , Now we change the coordinates of the food into the head of the snake , And then print the snake again , That is, you can have the effect of turning a snake into , The essence is to insert the elements of the circular linked list . In this way, the coordinates of food are inserted into the circular list , To achieve the effect of becoming a snake
The code is as follows

``````struct snake *snake_link(struct snake *p)      // The connection of the snake
{

struct snake *q;
q = (struct snake *)malloc(sizeof(struct snake)); // That is, it mainly realizes the insertion elements of the circular linked list , Again
q->x = food_xy;                                // Print snake , You can eat the food and the snake grows longer
q->y = food_xy;
q->pre = p->pre;
p->pre->next = q;
p->pre = q;
q->next = p;
return p;
}

``````

## 5. Judge the death of the snake , They are hitting the wall hit_wall() And suicide suicide()

Against the wall , Then we only need to determine the single coordinates of the snake head x Axis or y Whether the axis is equal to the coordinates of the wall , If it's equal, it means the snake hit the wall
The code is as follows

``````void hit_wall(int n)       // Judge if the snake hit the wall , That's a single coordinate for the snake x perhaps y Judge , If it's equal to the value of the wall , The end of the game
{

if(ch == 'W'|| ch == 'S' )
if(n == 1 || n == 25)              // The coordinates of the wall
{

gotoxy(0,26);
printf(" Game over ！");
exit(0);
}
if(ch == 'A'|| ch == 'D' )
if(n == 0 || n == 49)
{

gotoxy(0,26);
printf(" Game over ！");
exit(0);
}
}
``````

commit suicide suicide() Whether the head of the snake has hit the body of the snake , The way to do this is to take out the coordinates of the snake head , Compared with the coordinates of the snake, if it's equal , It means that the head of the snake hit the body of the snake , It's essentially a circular list of values to match , Traverse
The code is as follows

``````void suicide(struct snake *p, int x, int y) // commit suicide , That is, when you hit yourself, the game ends
{

struct snake *q;                         // Pass in the coordinates of the snake head , Then compare it with its own body coordinates. If it is equal, it means , The head of the snake hit the body of the snake
q = p;
while(q != p->next)                      // That is, the traversal matching of the circular linked list
{

if(p->x == x && p->y == y)
{

gotoxy(0,26);
printf(" Game over ！");
exit(0);
}
else
p = p->next;
}
}

``````

So far, the basic functions of snakes have been discussed , Here's the whole code .

All codes are as follows

``````#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <conio.h>
#include <time.h>
#define SNAKE_SPEED 200 // The speed at which the snake moves
int score = 0;         // Scores
int flag = 0;          // Used to determine if there is food on the map ,0 For there is no food
int food_xy;         // Positioning food
char ch;               // Used to determine the direction of the snake's movement
struct snake   // The snake that defines a circular list
{

int x;
int y;
struct snake *next;
struct snake *pre;
};

void HideCursor()// Hide the cursor when the snake moves , Hide cursor function
{

CONSOLE_CURSOR_INFO cursor;
cursor.bVisible = FALSE;
cursor.dwSize = sizeof(cursor);
HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleCursorInfo(handle, &cursor);
}

void gotoxy(int x, int y)   // Positioning cursor function , To move the snake , And the emergence of food （ delivery x,y You can position the cursor to x,y）
{

HideCursor();
COORD coord = {

x,y};
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord);
}

void map()   // Create a map of snakes
{

int a = {

0};
int i,j;
for(i = 0; i < 50; i++)
{

a[i] = 1;
a[i] =1;
}
for(i = 0; i < 25; i++)
{

a[i] = 1;
a[i] =1;
}
for(i = 0; i < 25; i++)
for(j = 0; j < 50; j++)
{

if(j%50 == 0)
printf("\n");
if(a[i][j] == 0)
{

printf(" ");
}
else
{

printf("#");
}
}
}

struct snake *createSnake()   // Initialize the snake , Build a snake , The essence is a circular list
{

int i;
p = q = (struct snake *)malloc(sizeof(struct snake));
for( i = 0; i < 5; i++)
{

p->x = 25 - i;
p->y = 13;
q->next = p;
q = p;
p = (struct snake *)malloc(sizeof(struct snake));
}

}

void printSnake(struct snake *p)   // Print snake , utilize gotoxy（） To print snakes , The coordinates can be visualized as a snake by traversing the circular list once
{

struct snake *q;
q = p;
while(q != p->next)             // Loop list traversal
{

gotoxy(p->x,p->y);          // According to the coordinates and positioning cursor function to type @, Realize the output snake
printf("@");
p = p->next;
}
gotoxy(p->x,p->y);
printf("@");
gotoxy(0,0);
printf(" Your score ：");          // Initialization score
}

void food()                       // Produce food
{

int i;
if(!flag)                     // according to flag To determine whether there is food on the map
{

srand( (unsigned)time( NULL ) );
for( i = 0; i < 2; i++ )  // Yes food_(x,y) To assign random values to
{

food_xy[i] = rand()%24+2;
while(food_xy == 1 || food_xy == 25) // these two items. while To prevent the coordinates of the food from overlapping the edges of the map
food_xy = rand()%24+2;
while(food_xy >= 49 || food_xy == 1)
food_xy =rand()%24+2;
}
gotoxy(food_xy,food_xy);  // Print food
printf("*");
flag = 1;
}
}

struct snake *snake_link(struct snake *p)      // The connection of the snake
{

struct snake *q;
q = (struct snake *)malloc(sizeof(struct snake)); // That is, it mainly realizes the insertion elements of the circular linked list , Then print the snake , You can eat the food and the snake grows longer
q->x = food_xy;
q->y = food_xy;
q->pre = p->pre;
p->pre->next = q;
p->pre = q;
q->next = p;
return p;
}

void eat_food(struct snake *p,int x, int y)           // Snakes eat food , That is, mainly for the snake head x,y Coordinates and food_xy To match and compare , If the same is called snake_link Function
{

if(x == food_xy && y == food_xy)
{

flag = 0;
printSnake(p);
gotoxy(8,0);
score = score + 1;
printf("%d",score);
}
}

void hit_wall(int n)       // Judge if the snake hit the wall , That's a single coordinate for the snake x perhaps y Judge , If it's equal to the value of the wall , The end of the game
{

if(ch == 'W'|| ch == 'S' )
if(n == 1 || n == 25)
{

gotoxy(0,26);
printf(" Game over ！");
exit(0);
}
if(ch == 'A'|| ch == 'D' )
if(n == 0 || n == 49)
{

gotoxy(0,26);
printf(" Game over ！");
exit(0);
}
}

void suicide(struct snake *p, int x, int y) // commit suicide , That is, when you hit yourself, the game ends
{

struct snake *q;                         // Pass in the coordinates of the snake head , Then compare it with its own body coordinates. If it is equal, it means , The head of the snake hit the body of the snake
q = p;
while(q != p->next)                      // That is, the traversal matching of the circular linked list
{

if(p->x == x && p->y == y)
{

gotoxy(0,26);
printf(" Game over ！");
exit(0);
}

else
p = p->next;
}
}

struct snake *up(struct snake *p) // Move up
{

int x;
int y;
x = p->pre->x;                 // Assign snake head coordinates to x,y
y = p->pre->y;
while(p)                      // Traversal of a circular list , That is, the traversal of snakes
{

Sleep(SNAKE_SPEED);        // The speed at which the snake moves
y--;                       // If you move up, you just subtract the ordinate , You can achieve the effect of the snake moving up
gotoxy(p->x,p->y);         // To the tail of the snake , Output “ ” The snake tail disappears
printf(" ");
gotoxy(x, y);              // Position to snakehead output ,"@", Combined with the disappearance of the snake tail above, the snake head is printed again , Produces the effect of Snake Movement
printf("@");
suicide(p,x,y);            // Judge whether the head of the snake hit the body of the snake
p = p->next;               // Change the coordinates of the snake head to the next
p->pre->x = x;             // At this point, change the head of the previous snake into the tail of the snake , Through continuous traversal to produce the effect of continuous movement
p->pre->y = y;
food();                    // Produce food
eat_food(p,x,y);           // Judge whether you have food
hit_wall(y);               // Judge if you hit the wall
if(kbhit()) break;        // Determine whether there is a key input , If yes, change the direction of the snake's movement
}

return p;

}

struct snake *left(struct snake *p) // Move to the left
{

int x;
int y;
x = p->pre->x;
y = p->pre->y;
while(p)
{

Sleep(SNAKE_SPEED);
x--;
gotoxy(p->x,p->y);
printf(" ");
gotoxy(x, y);
printf("@");
suicide(p,x,y);
p = p->next;
p->pre->x = x;
p->pre->y = y;
food();
eat_food(p,x,y);
hit_wall(x);
if(kbhit()) break;
}
return p;
}

struct snake *down(struct snake *p)  // Move down the
{

int x;
int y;
x = p->pre->x;
y = p->pre->y;
while(p)
{

Sleep(SNAKE_SPEED);
y++;
gotoxy(p->x,p->y);
printf(" ");
gotoxy(x, y);
printf("@");
suicide(p,x,y);
p = p->next;
p->pre->x = x;
p->pre->y = y;
food();
eat_food(p,x,y);
hit_wall(y);
if(kbhit()) break;
}
return p;
}

struct snake *right(struct snake *p)   // To the right
{

int x;
int y;
x = p->pre->x;
y = p->pre->y;
while(p)
{

Sleep(SNAKE_SPEED);
x++;
gotoxy(p->x,p->y);
printf(" ");
gotoxy(x, y);
printf("@");
suicide(p,x,y);
p = p->next;
p->pre->x = x;
p->pre->y = y;
food();
eat_food(p,x,y);
hit_wall(x);
if(kbhit()) break;
}
return p;

}
void move(struct snake *p)   // The snake's moving function
{

while(1)
{

ch = getch();
switch(ch)
{

case 'W':p = up(p);break;
case 'A':p = left(p);break;
case 'D':p = right(p);break;
case 'S':p = down(p);break;
}
}
}
int main()
{

struct snake *p;
map();      // Generating maps
p = createSnake(); //  Initialize snake
printSnake(p);   //  Print snake
move(p);        // Move the snake

return 0;
}

``````