How to use the two-way linked list to achieve a simple C language version of the Snake game (as shown in the figure below).

Among them, yellow box represents greedy snake, red ★ represents food!

The use of two-way linked list to achieve this game, there are the following points need to do key analysis.

1) As we know, the standard composition of each node in the two-way linked list is a data field and two pointer fields, but for the realization of Snake game, because the position of each node is changing with the snake’s movement, so the nodes in the linked list also need to be positioned at any time.

In a two-dimensional picture, to define the position of a node, at least the row number and the column number are required.

From this, we can get the composition of each node in the bidirectional linked list of the snake:

Typedef struct SnakeNode {int x, y; Struct SnakeNode *pre; struct SnakeNode *pre; Struct SnakeNode *next; struct SnakeNode *next; // Pointer to the next Node}Node, *pNode;

2) The movement of the snake is essentially the relocation of each node in the linked list.

In other words, unless the snake eats the food, no matter how it moves, it will not affect the whole structure of the two-way linked list (the number of nodes). The only thing that will be affected is the location data (x, y) of each node.

Therefore, we can try to design a functional function to realize the movement of the snake. The realization idea used in this section is divided into two steps:

▶ Starting from the tail of the snake (the tail node of the bidirectional linked list), move forward traversal, during the process, change the (x, y) of the current node to the (x, y) of the precursor node in turn, thus realizing the forward movement of the whole snake body (all nodes except the first node);

▶ Receive the movement command input by the user, and move the Snake left, right, up or down according to the user’s instructions. The (x, y) in the first node shall be calculated by X-1, X +1, Y-1 and Y +1 respectively.

The move() function implements the snake’s move as shown below:

Bool Move(pNode pHead, char key) {bool game_over = false; bool game_over = false; pNode pt = pTail; while (pt ! = pHead) {// Pt-> x = Pt-> pre->x; pt->y = pt->pre->y; pt = pt->pre; } switch (key) { case'd': { pHead->x += 1; if (pHead->x >= ROW) game_over = true; break; } case'a': { pHead->x -= 1; if (pHead->x < 0) game_over = true; break; } case's': { pHead->y += 1; if (pHead->y >= COL) game_over = true; break; } case'w': { pHead->y -= 1; if (pHead->y < 0) game_over = true;; break; } } if (SnakeDeath(pHead)) game_over = true; return game_over; }

Note that the snakeDeath () function is also called in this code. This function is used to determine if the snake is moving into a wall or itself. If it is, the game is over.

3) When the snake eats the food, the snake needs to add a section, which is the essence of a two-way linked list to add a node. But the only difficulty in implementing this is: how do you initialize (x, y) for this node?

This design of the Snake game, for this problem, provides the simplest solution, is not to initialize the new nodes X and Y.

We should know that the snake moves all the time, and in the above move() function, the position of each node of the snake will be corrected all the time. Therefore, when a new node is added to the two-way linked list, the position of the new node will be corrected by itself as long as the snake moves one step.

In other words, the realization of the snake eating food is just adding a new node to the two-way linked list. The following is the code to achieve this function:

Typedef struct Food {int x; // create a structure that represents Food; int y; }Food, *pFood; PNode EatFood(pNode pHead, pFood pFood) {pNode p_add = NULL, pt = NULL; if (pFood->x == pHead->x&&pFood->y == pHead->y) { p_add = (pNode)malloc(sizeof(Node)); score++; pTail->next = p_add; p_add->pre = pTail; p_add->next = NULL; pTail = p_add; Do {*pFood = CreateFood(); } while (FoodInSnake(pHead, pFood)); } return pHead; }

Among them, the Food structure is used to represent Food, which only contains (x, y) that can locate the location of Food.

In addition, in this code, foodeInSnake () function is also called. Since the position of the food is random, it is very likely to overlap with the snake, so the function of this function is: if overlap, the food will be regenerated.

The implementation of the foodinSnake () function is simple and won’t be repeated here:

Bool FoodInSnake(pNode pHead, pFood pFood) {pNode pt = NULL; for (pt = pHead; pt ! = NULL; pt = pt->next) { if (pFood->x == pt->x&&pFood->y == pt->y) return true; } return false; }

4) Snake game interface display, the simplest production method is: Snake every move, clear the screen and regenerate once.

The problem with this implementation is that if Snake moves too fast, the entire interface will be rendered with the cursor, and the screen will flash a lot. Therefore, when rendering the interface, it is necessary to hide the cursor. This is done using the < Windows.h > header file. The code is as follows:

// Hide the cursor void GoToXy (int x, int y) {Handle Handle = getStdHandle (STD_OUTPUT_HANDLE); COORD pos; pos.X = x; pos.Y = y; SetConsoleCursorPosition(handle, pos); } void HideCursor() { CONSOLE_CURSOR_INFO cursor_info = { 1, 0 }; SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &cursor_info); }

Also, in order to render the entire interface with color, we need to introduce the < Windows.h > header file and use the following function:

void color(int m) {
 
    HANDLE consolehend;
 
    consolehend = GetStdHandle(STD_OUTPUT_HANDLE);
 
    SetConsoleTextAttribute(consolehend, m);
 
}

5) It is important to note that the heap space occupied by the bidirectional linked list must be released manually after this:

Void exitGame (pNode *pHead) {pNode p_delete = NULL, p_head = NULL; while (*pHead ! = NULL) { p_head = (*pHead)->next; if (p_head ! = NULL) p_head->pre = NULL; p_delete = *pHead; free(p_delete); p_delete = NULL; *pHead = p_head; }}

After solving the above problems, the use of two-way linked list to achieve the snake game, basically there is no difficulty. Families can try to do it independently according to the implementation ideas provided in this section.