Mini game: The first mini game I wrote in my life - Snake (C language)

        The editor opened a column about games, mainly using the easyx graphics library.


Table of contents for series of articles:     

       Chapter 1: The first mini-game written in life - Snake (C language)


        I have released the code of this game on gitee. If you don’t mind it, you can go to this website to view and copy it: https://gitee.com/rising-sun-1 .

       Today, we will use the easyx graphics library and C language to write code. First, we need to analyze the general idea of ​​this mini game, and then write the code.


Table of contents

analysis of idea:

window:

Greedy Snake:

food:

Other functions:

Code writing:

Preparation before writing code:

Beginning preparation:

Creation of Snake: 

Creation of food:

Game ending conditions:

Game initialization:

Inside the main function:


analysis of idea:

window:

       First, create a pixel window and use the initgraph function to create it (the basic usage of this function can be viewed on this website: https://docs.easyx.cn/zh-cn/intro ).

       After creating it, start thinking about the basic elements of the game: snakes and food . The following is an analysis of greedy snakes and food:

Greedy Snake:

       For a greedy snake, several grids are needed, so how are these grids connected? Because arrays require data of the same type to be stored together, but storing the snake's body in a two-dimensional space requires coordinates, so using arrays is relatively troublesome. We can use structures to represent the snake's nodes. Because the snake wants to move, we can move the head node and then delete the tail node so that the snake can move. The snake needs to change its direction when moving. How to change its direction? The coordinates can be considered, for example, if you move down, the vertical coordinate will be increased by one, etc.

food:

       Food needs to be randomly distributed, so we need to select random numbers and use the rand function (use cplusplus.com to view the function). In order to make the random numbers more random, we need to use the time function (need to call the header file #include <time.h>). 

Other functions:

       Other functions include snake eating food, lengthening the snake's body, conditions for the end of the game, re-initialization after the game is over, and discussion while writing the code.

The general idea is as above, let’s write the code below:

Code writing:

Preparation before writing code:

        First of all, you need to download the easyx graphics library ( https://easyx.cn/ ). After downloading, follow the picture to create a project in vs, select the console application, and enter to write code.

Beginning preparation:

       First, write header files and macros to shield the unsafeness of the scanf function.

(The reason why the scanf_s function is not used is because the scanf_s function is VS and is not compatible with other compilers, resulting in the non-portability of the function.)

       Next, create a main function, create a window of 800 pixels high and 600 pixels wide according to the analysis idea, and then use the line function to draw the table. The approximate code is as follows:

void printline()   //进行表格的绘画
{
	int x = 0;
	for (x = 0; x <= 800; x += NODE_WIDTH)
	{
		line(x, 0, x, 600);   //line函数是画出直线的函数
	}
	int y = 0;
	for (y = 0; y < 600; y += NODE_WIDTH)
	{
		line(0, y, 800, y);
	}
}
int main()
{
    //创建窗口
	initgraph(800, 600);
	setbkcolor(RGB(164, 225, 202)); //创建一个像素窗口
	cleardevice();
	getchar();
	closegraph();
	return 0;
}

Creation of Snake: 

      Then create the snake and use the structure to create a node.

typedef struct {   //贪吃蛇的结点
	int x;
	int y;
}node;

       Define the initial position of the snake:

node snack[100] = { {5, 7}, {4, 7}, {3, 7}, {2, 7}, {1, 7} };

       Because the snake's body is composed of multiple rectangles (cubes), it needs to be constructed using a loop . The length of the snake is known to be constructed using a for loop.

       There are three loops in C language, namely: for, while, and do while. They have some differences that make them applicable to different scenarios. If the number of loops is known, use a for loop. If the number of loops is unknown, use a while loop. If you want to loop once, use a do while loop.

void printsnack(node* snack, int n)  //进行蛇主题的绘画
{
	int left, right, bottom, top;
	int i = 0;
	for (i = 0; i < n; i++)
	{
		left = snack[i].x * NODE_WIDTH;
		top = snack[i].y * NODE_WIDTH;
		right = (snack[i].x + 1) * NODE_WIDTH;
		bottom = (snack[i].y + 1) * NODE_WIDTH;
		solidrectangle(left, top, right, bottom); 
	}
}

       After creating the snake, move the snake behind it. How to make the snake move? Use coordinates to make the snake move. For example, passing the value of the previous node to the value of the next node and looping it will make the snake move one step to the right. Using the head node to move the snake also uses the head node. The point controls the direction, for example, if it moves upward, the ordinate of the head node is reduced by one. The code is as follows:

node snackmove(node* snack, int length, int direction) //蛇移动的函数
{
	node newfinsh = snack[length - 1];  //将蛇结点的最后一个结点保存下来
	for (int i = length - 1; i > 0; i--)
	{
		snack[i] = snack[i - 1];   //将前一个蛇结点移动到后一个蛇结点,进行蛇的移动
	}
	node head;  //定义一个头结点并利用头结点进行方向的移动
	head = snack[0];
	if (direction == eUp)
	{
		head.y--;
	}
	else if (direction == eDown)
	{
		head.y++;
	}
	else if (direction == eLeft)
	{
		head.x--;
	}
	else if (direction == eRight)
	{
		head.x++;
	}
	snack[0] = head;
	return newfinsh;
}

       Here's how to perform keyboard interaction , that is, typing 'w' on the keyboard will cause the snake to move upward. First, use the _kbhit function to check whether there is data in the input buffer area, and use the getch() function to obtain the input data from the buffer area and make corresponding data. It should be noted here that the snake cannot move in the opposite direction to the direction it is moving, so conditions need to be added.

void changedirection(enum direction* pD)   //中间有键盘交互的代码
{ 
	if (_kbhit() != 0)//检查输入缓存区中是否有数据
	{
		char c = _getch();//从缓存区中获取输入数据并做相应的数据
		switch (c)
		{
		case 'w':
			if(*pD != eDown) //要注意蛇不能向正在移动的反方向进行移动
			*pD = eUp;
			break;
		case 's':
			if(*pD != eUp)
			*pD = eDown;
			break;
		case 'a':
			if(*pD != eRight)
			*pD = eLeft;
			break;
		case 'd':
			if(*pD != eLeft)
			*pD = eRight;
			break;
		}
	}
}

Creation of food:

       The creation of food needs to be randomly distributed , so random numbers are used to randomize the location of the food. The random value needs to be within the created window and cannot exceed the window. Food cannot be created on the snake's body. The code is as follows:

node creatfood(node* snack, int length)  //创建食物
{
	node food;
	while (1)
	{
		food.x = rand() % (800 / NODE_WIDTH); //利用随机数进行食物位置的随机
		food.y = rand() % (600 / NODE_WIDTH);
		int i = 0;
		for (i = 0; i < length; i++) //利用for循环一一遍历,防止食物生成在蛇身上
		{
			if (food.x == snack[i].x && food.y == snack[i].y)
			{
				break;
			}
		}
		if (i < length) //如果i小于蛇的长度,则需要继续遍历,知道i大于蛇的长度
		{
			continue;
		}
		else
			break;
	}
	return food;
}

       It is relatively easy to print out food on the form, which is also drawn using the solidrectangle function. However, in order to distinguish the color of the food and the snake, we can use the setfillcolor function to fill it with different colors.

Game ending conditions:

       The condition is that the snake cannot touch the wall and the snake cannot touch the body of the snake. This can be done by using if judgment. Please note that the return type of this function is bool type.

bool isgameover(node* snack, int length)//游戏结束的条件
{
	if (snack[0].x < 0 || snack[0].x>800 / NODE_WIDTH)//当蛇碰到墙壁,游戏结束
		return true;
	if (snack[0].y < 0 || snack[0].y>600 / NODE_WIDTH)
		return true;
	for (int i = 1; i < length; i++)   //当蛇碰到蛇身游戏结束
	{
		if (snack[0].x == snack[i].x && snack[0].y == snack[i].y)
			return true;
	}
	return false;
}

Game initialization:

        It is the state of letting the game progress and restarting the game.

Inside the main function:

        Use the Sleep function to adjust the speed of the snake's movement. If the snake eats food, the snake will grow longer.

while (1)
	{
		cleardevice();
		printline();
		printsnack(snack, length);
		printfood(food);
		Sleep(500);
		changedirection(&d);
		node newlist = snackmove(snack, length, d);
		if (snack[0].x == food.x && snack[0].y == food.y)
		{
			if(length < 100)
			{
				snack[length] = newlist;
				length++;
			}
			food = creatfood(snack, length);
		}
		if (isgameover(snack, length) == true)
		{
			reset(snack, &length, &d);
			food = creatfood(snack, length);
		}
	}

          Thank you everyone for watching. If there are any mistakes, I hope you can criticize and correct them. This is a newbie who has just embarked on his programming journey.

Guess you like

Origin blog.csdn.net/2301_77868664/article/details/131151819