当前位置:网站首页>One of the C language practical projects is greedy snake
One of the C language practical projects is greedy snake
2022-07-03 01:39:00 【Someone -jojo】
friends , After me c Knowledge of the first ten chapters of language , Everyone should have started , I personally think that learning c The best way to use language is to make wheels , Writing projects is the best way to improve , We can connect the knowledge we have learned .
Today we write a practical project, snake : Core will use Array and gotoxy(); function
Let's look at the finished product first :
This is a somewhat crude snake program , Although simple, finding and solving problems when writing is the most valuable asset .
Let's first look at what this program has :
1. Map
2. The snake
3. food
According to these three, we will divide the greedy snake program into modules :
1. Map module
2. Randomly generate food modules
3. Initialize snake module
4. Greedy snake mobile module
5. Game status module
6. Coordinate control module
Analysis complete , We began to get to the point :
One Map module
The code is as follows
void createMap() {
for (int i = 0 + MOVE_CENTER; i < MAP_WIDTH + MOVE_CENTER; i += 2) {// Up and down
gotoxy(i, 0);// change x,y unchanged -> Top edge
printf(MAP_MODE);
gotoxy(i, MAP_HEIGHT - 1);// change x,y unchanged -> The bottom side
printf(MAP_MODE);
}
for (int i = 0; i < MAP_HEIGHT; i++) {// Left and right
gotoxy(0 + MOVE_CENTER, i);// change y,x unchanged -> The leftmost side
printf(MAP_MODE);
gotoxy(MAP_WIDTH + MOVE_CENTER, i);// change y,x unchanged -> The rightmost side
printf(MAP_MODE);
}
// Change the cursor position , Make it not affect the beauty
gotoxy(96, 0);
// Initialize snake
initSnake();
}
First, we know the first knowledge point by writing a map :gotoxy(int x, int y); function :
gotoxy(int x, int y) yes #include<windows.h> A function declared in , The function is to move the cursor to the specified position . In Contemporary Visual C++ or GCC You can customize this function in .
I drew a picture , So that you can understand :
The upper left corner is the origin (0,0),x Increase to the right ,y Up and down .
How did you draw this box map ?:
First, we draw the upper and lower boxes :
for (int i = 0 + MOVE_CENTER; i < MAP_WIDTH + MOVE_CENTER; i += 2) { // Up and down
gotoxy(i, 0);// change x,y unchanged -> Top edge
printf(MAP_MODE);
gotoxy(i, MAP_HEIGHT - 1);// change x,y unchanged -> The bottom side
printf(MAP_MODE);
}
utilize for Cycle output our MAP_MODE Square box , Then assign a value to the coordinate function and print circularly
You may be a little confused , Why i+=2 instead of i++, because ■, This thing , Occupy two cursor widths ;
Here we define the macro :
#defineMAP_MODE"■"// Map module
#defineMAP_WIDTH 80// Map length
#defineMAP_HEIGHT 30// Map width
#defineMOVE_CENTER 12// Move the map
Why use macros to define ? For the convenience of our next revision , There is no need to take and modify the module separately , Modify the macro definition directly .
We set the length of the map as 80, Width is 30;
To move the position is to move the map to the right , Can be more beautiful
Be careful :■, This thing , Occupy two cursor widths ;
well , Similarly, we began to draw the left and right sides :
for (int i = 0; i < MAP_HEIGHT; i++) { // Left and right
gotoxy(0 + MOVE_CENTER, i);// change y,x unchanged -> The leftmost side
printf(MAP_MODE);
gotoxy(MAP_WIDTH + MOVE_CENTER, i);// change y,x unchanged -> The rightmost side
printf(MAP_MODE);
}
Finally, we move the cursor outside the map , So as not to affect reading :
// Change the cursor position , Make it not affect the beauty
gotoxy(96, 0);
Then initialize the snake , Let's write first , I'll talk about initializing the snake module later :
// Initialize snake
initSnake();
}
Two Coordinate module
Because we used this in the map module gotoxy(); function , It belongs to the coordinate module , So let's talk about this module :
void gotoxy(int x, int y) {// System auxiliary function
COORD pos = { x, y };
HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleCursorPosition(hOut, pos);
}
gotoxy(), According to the coordinates assigned by you , Move the cursor to the corresponding place .
You just have to remember , Use gotoxy(); Function you have to define it like this , And bring the header #include<windows.h>// In order to use gotoxy( Cursor movement function )
The coordinate function to be used next time , Direct application ;
3、 ... and Randomly generate food modules
The code is as follows :
void createFood() {
// Random food
srand(time(NULL));// Random seeds
int isCreate = 1;// Indicates whether food can be created
food.x = rand() % (MAP_WIDTH - 4 + 2) + MOVE_CENTER;
food.y = rand() % (MAP_HEIGHT - 1 + 1);
if (food.x % 2 == 0) {// Satisfy x Coordinates are even
// The coordinates of food cannot be on the snake
for (int i = 0; i < snake.currentLen; i++) {
if (snake.x[i] == food.x && snake.y[i] == food.y) {
isCreate = 0;
}
if (isCreate) {
gotoxy(food.x, food.y);
printf(MAP_MODE);
flag = 0;
// Change the cursor position , Make it not affect the beauty
gotoxy(96, 0);
}
}
}
}
Let's analyze the food first , Food is also a box , He has x And y coordinate .
Analysis complete , Let's create the structure :
structFood { // Food structure
int x;
int y;
}food;
Okay , We have food , Now we're going to randomly generate it in our map , That is to say, his range of activities :
How random ?
srand(time(NULL));// Random seeds
meanwhile time() The function should bring the header file #include<time.h>// Random seeds to appear food , Because it is the use of system time .
The purpose of this order is Use system time , Returns a random number .
meanwhile , We need to make food in the place we want :
No more outside the map , It cannot be produced on the body of a snake .
Let's simply define a int isCreate = 1;// Indicates whether food can be created
The following code represents : The food x Coordinates and y Where coordinates can be generated :
food.x = rand() % (MAP_WIDTH - 4 + 2) + MOVE_CENTER;
food.y = rand() % (MAP_HEIGHT - 1 + 1);
If you don't understand rand function , Please click the link below to understand , We won't go into details :
https://blog.csdn.net/cmm0401/article/details/54599083
After understanding, you may want to ask , Why is food x The coordinates are at 4 To the width of the map , because ■, This thing , Occupy two cursor widths , Take a 2;
Write another for loop , Prevent food from forming on snakes :
if (food.x % 2 == 0) { // Satisfy x Coordinates are even because ■, This thing , Occupy two cursor widths , Take a 2;
// The coordinates of food cannot be on the snake
for (int i = 0; i < snake.currentLen; i++) {
if (snake.x[i] == food.x && snake.y[i] == food.y) {
isCreate = 0;
}
snake Structure we will talk about later ,snake.currentLen Is the length of the snake :
Then we write something that can produce food if loop ;
if (isCreate) {
gotoxy(food.x, food.y);
printf(MAP_MODE);
flag = 0;
// Change the cursor position , Make it not affect the beauty
gotoxy(96, 0);
}
flag Is the global variable I defined :int flag = 1;// Need to produce food
Four Initialize snake module
The code is as follows :
void initSnake() {
snake.currentLen = INITLEN;
snake.x[0] = MAP_WIDTH / 2 + MOVE_CENTER;
snake.y[0] = MAP_HEIGHT / 2;
gotoxy(snake.x[0], snake.y[0]);
printf(SNAKE_HEAD);
// Print out the snake with a cycle , The snake's body is connected to the back of the snake's head
for (int i = 1; i < snake.currentLen; i++) {
snake.x[i] = snake.x[i - 1] + 2;
snake.y[i] = snake.y[i - 1];
gotoxy(snake.x[i], snake.y[i]);
printf(SNAKE_BODY);
}
First, we write about the structure of snake. We need to know what it is made of :
x coordinate ,y coordinate , And the length of the snake , Snakes are definitely not made up of a single coordinate , We use arrays to represent .
Based on this, we begin to define the snake structure :
structSnake { // The structure of a snake
int x[MAXLEN];
int y[MAXLEN];
int currentLen;// The length of the current snake x[0],y[0] -> Snakehead
}snake;
Define macro variables
#defineINITLEN 3// Define the initial length of the snake
#defineMAXLEN 30// Define the maximum length of the snake
#defineSNAKE_HEAD"⊙"// Snakehead
#defineSNAKE_BODY"●"// Snake-body.
without doubt , Snakehead is the first element of the array x[0]y[0];
snake.currentLen = INITLEN; // The snake length is defined as the initial length
snake.x[0] = MAP_WIDTH / 2 + MOVE_CENTER; // Snakehead x The coordinates appear in the center of the map
snake.y[0] = MAP_HEIGHT / 2; //y The coordinates should also be in the center
gotoxy(snake.x[0], snake.y[0]); // Move the cursor to the center of the map
printf(SNAKE_HEAD); // Output snakehead
When the snake head is finished, let's write the snake body :
// Print out the snake with a cycle , The snake's body is connected to the back of the snake's head
for (int i = 1; i < snake.currentLen; i++) {
snake.x[i] = snake.x[i - 1] + 2; // Add 2 Because the box occupies two spaces
snake.y[i] = snake.y[i - 1];
gotoxy(snake.x[i], snake.y[i]);
printf(SNAKE_BODY);
}
// Change the cursor position , Make it not affect the beauty
gotoxy(96, 0);
5、 ... and Snake mobile module
The code is as follows :
void moveSnake() {
if (_kbhit()) {// Monitor keyboard input
fflush(stdin);
direct = _getch();
}
// Erase the last snaketail
gotoxy(snake.x[snake.currentLen - 1], snake.y[snake.currentLen - 1]);
printf(" ");// Print two cursor size spaces
// Start replacing coordinates , Move the snake
for (int i = snake.currentLen - 1; i > 0; i--) {
snake.x[i] = snake.x[i - 1];
snake.y[i] = snake.y[i - 1];
gotoxy(snake.x[i], snake.y[i]);
printf(SNAKE_BODY);
}
switch (direct) {
case 'w':
case 'W':
snake.y[0]--;
break;
case 's':
case 'S':
snake.y[0]++;
break;
case 'a':
case 'A':
snake.x[0] -= 2;
break;
case 'd':
case 'D':
snake.x[0] += 2;
break;
}
// After moving , The position of the new snake head
gotoxy(snake.x[0], snake.y[0]);
printf(SNAKE_HEAD);
// Change the cursor position , Make it not affect the beauty
gotoxy(96, 0);
// Determine whether the coordinates of the snake head are equal to the food
if (snake.x[0] == food.x && snake.y[0] == food.y) {
snake.currentLen++;
flag = 1;
}
}
First , We encounter functions we are not familiar with kbhit() function , Please see the following link to explain , We won't go into details :
After reading it, you will know that he monitors keyboard input , Because we need to use the keyboard to control the movement of the snake .
Don't forget to bring your header when you use it #include<conio.h>// Monitor keyboard input
Let's get to know , How greedy snakes move , Ate a food , Greedy snake grows one space ,, Snake moves. Are all the squares moving , Not snake head and set to move , The snake tail movement is to erase the last space , Do you remember the old version of the pixel game "brave vs. dragon" we played when we were children , It is also made by using this frame by frame change , Then visually, you think the brave are moving .
Return to the right topic :
How to erase our snake tail :
// Erase the last snaketail
gotoxy(snake.x[snake.currentLen - 1], snake.y[snake.currentLen - 1]);
printf(" ");// Print two cursor size spaces
Snake's x Change the coordinates to length -1,y Coordinates also -1. Then turn the box into “ ”, overwrite .
Then we began to move the snake :
/ Start replacing coordinates , Move the snake
for (int i = snake.currentLen - 1; i > 0; i--) {
snake.x[i] = snake.x[i - 1];
snake.y[i] = snake.y[i - 1];
gotoxy(snake.x[i], snake.y[i]);
printf(SNAKE_BODY);
}
Write a for The cycle keeps checking x-1 The coordinates of are assigned to x, The former coordinate is given to the latter , Isn't this just exercise , Then at the coordinates , We export snake bodies .
The head of a snake controls its body , How to control the snake head , This is what we talked about before kbhit() Function , Since the keyboard input is monitored , Then let's input the key to control the coordinates of the snake head .
Macro definition :int direct = 'a';// The default key is a
Why do I need this macro definition , Because it defaults that our snake moves to the left .
switch (direct) {
case'w':
case'W':
snake.y[0]--; // Up
break;
case's':
case'S':
snake.y[0]++; // Down
break;
case'a':
case'A':
snake.x[0] -= 2; // towards the left
break;
case'd':
case'D':
snake.x[0] += 2; // towards the right
break;
}
// After moving , The position of the new snake head
gotoxy(snake.x[0], snake.y[0]);
printf(SNAKE_HEAD);
// Change the cursor position , Make it not affect the beauty
gotoxy(96, 0);
use switch Statement control keys to manipulate snake head coordinates , So we can control the snake to move .
Then the snake eats food to increase its length :
// Determine whether the coordinates of the snake head are equal to the food
if (snake.x[0] == food.x && snake.y[0] == food.y) {
snake.currentLen++;
flag = 1;
}
Well understood. , Be a snake head xy Coordinates and food xy The coordinates coincide , The length of the snake is increased by one .
flag Is our macro definition , We use it to control food production , Because food can't be produced there without you eating it , Eat one and make one .
6、 ... and Game status module
The code is as follows :
int statement() {// Judge the current state of the game
// Judge whether the snake head hit the wall
if (snake.x[0] == 0 + MOVE_CENTER || snake.x[0] == MAP_WIDTH + MOVE_CENTER || snake.y[0] == 0 || snake.y[0] == MAP_HEIGHT - 1) {
return 1;
}
// Snake head eats any part of his body
for (int i = 1; i < snake.currentLen; i++) {
if (snake.x[0] == snake.x[i] && snake.y[0] == snake.y[i]) {
return 1;
}
}
return 0;
}
Greedy snakes can't go on forever , How does the game end ?
Two cases :
One is that the snake hit the wall , Two snakes bit their bodies
First look at the first one :
// Judge whether the snake head hit the wall
if (snake.x[0] == 0 + MOVE_CENTER || snake.x[0] == MAP_WIDTH + MOVE_CENTER || snake.y[0] == 0 || snake.y[0] == MAP_HEIGHT - 1) {
return 1;
}
How to judge whether the snake hit the wall ? use if Sentence when the snake x Coordinates and y When the coordinates coincide with the coordinates of the map border , End the game .
Look at the second one :
for (int i = 1; i < snake.currentLen; i++) {
if (snake.x[0] == snake.x[i] && snake.y[0] == snake.y[i]) {
return 1;
}
}
return 0;
It's simple, isn't it , Write a for loop , Then snake head xy Coordinates and snake body xy Exit the game when the coordinates are equal
.
main function
Six modules are completed , Let's write main function :
int main() {
createMap();
while (1) {
Sleep(300); // Let the food not appear so fast
if (flag) {
createFood();
}
moveSnake();
if (statement()) {
gotoxy(MAP_WIDTH / 2, MAP_HEIGHT / 2);// Enter game over
printf("Game Over!\n");
// Change the cursor position , Make it not affect the beauty
gotoxy(96, 0);
exit(0);
}
}
Conclusion
This greedy snake is simple , But as our beginner's project, it has a certain degree of difficulty , I followed this procedure b A video of the station was knocked out bit by bit , Why write this article , Because I think we should write our own understanding when making wheels , You can't build wheels all day , What is the wheel? I don't know when I ask you , Only by writing your own understanding can you turn knowledge into your own things .
So I wrote down my understanding and development process , I hope it can help readers understand , The author is a senior student who is looking for internship , Limited ability , If you have any suggestions, please don't hesitate to comment .
边栏推荐
- CF1617B Madoka and the Elegant Gift、CF1654C Alice and the Cake、 CF1696C Fishingprince Plays With Arr
- [androd] module dependency replacement of gradle's usage skills
- Summary of interval knowledge
- Kivy tutorial - example of using Matplotlib in Kivy app
- Meituan dynamic thread pool practice ideas, open source
- Mathematical Knowledge: Steps - Nim Games - Game Theory
- LDC Build Shared Library
- STM32 - Application of external interrupt induction lamp
- Vant 实现简单的登录注册模块以及个人用户中心
- How is the mask effect achieved in the LPL ban/pick selection stage?
猜你喜欢
STM32 - switch of relay control lamp
wirehark数据分析与取证A.pacapng
Arduino dy-sv17f automatic voice broadcast
【数据挖掘】任务3:决策树分类
What is tone. Diao's story
串口抓包/截断工具的安装及使用详解
Why is it not recommended to use BeanUtils in production?
[data mining] task 5: k-means/dbscan clustering: double square
Androd gradle's substitution of its use module dependency
传输层 TCP主要特点和TCP连接
随机推荐
Smart management of Green Cities: Digital twin underground integrated pipe gallery platform
C application interface development foundation - form control (4) - selection control
openresty 缓存
MySQL - database query - condition query
Pytest learning notes (12) -allure feature · @allure Step () and allure attach
Test shift right: Elk practice of online quality monitoring
Tp6 fast installation uses mongodb to add, delete, modify and check
[data mining] task 3: decision tree classification
【面试题】1369- 什么时候不能使用箭头函数?
Scheme and practice of cold and hot separation of massive data
[data mining] task 6: DBSCAN clustering
[data mining] task 5: k-means/dbscan clustering: double square
Tâche 6: regroupement DBSCAN
Meituan dynamic thread pool practice ideas, open source
Top ten regular spot trading platforms 2022
Why is it not recommended to use BeanUtils in production?
C语言课程信息管理系统
Do not log in or log in to solve the problem that the Oracle database account is locked.
uniapp组件-uni-notice-bar通告栏
View of MySQL