目录
1.游戏介绍与思路
1.1介绍:
1.2游戏区思路
1.2.1围墙
1.2.2游戏区域
1.2.3蛇头与蛇身
1.3游戏逻辑思路
2.正式实现贪吃蛇
2.1在开始前我们先包头文件和宏定义
2.2创建游戏区并且初始化
2.3初始化蛇头与蛇身
2.4打印与覆盖蛇
2.5实现蛇的移动
2.6蛇移动
2.7食物的随机生成
2.8判断游戏是否结束
3.整体游戏逻辑
4.完整代码
1.游戏介绍与思路
1.1介绍:
小键盘上下左右来控制方向,开始蛇的长度为3,吃到食物蛇身+1,碰到墙游戏结束
1.2游戏区思路
1.2.1围墙
围墙很简单,我们只要确定长和宽即可
#define ROW 22
#define COL 42
1.2.2游戏区域
利用一个二维数组face来存放游戏区内各方块的内容
如果(x,y)处是空的,我们就把数组的face[x][y]=BLANK;
如果(x,y)处是墙,我们就把数组的face[x][y]=WALL;
如果(x,y)处是食物,我们就把数组的face[x][y]=FOOD;
为了代码的可读性,我们使用宏定义
#define BlANK 0
#define WALL 1
#define FOOD 2
#define HEAD 3
#define BODY 4
1.2.3蛇头与蛇身
我们利用结构体来构造蛇头与蛇身
(1)蛇头的结构体
需要存放蛇头的横纵坐标,以及蛇的总长度
struct snakehead
{int x;//蛇头横坐标int y;//蛇头纵坐标int len;//蛇的总长度
}snake;
(2)蛇身结构体
存放每个蛇身的横纵坐标,需要开辟多个
struct snakebody
{int x;//蛇身横坐标int y;//蛇身纵坐标
}body[ROW*COL];
1.3游戏逻辑思路
接收键盘字符来判断需要进行的操作
#define UP 72
#define DOWN 80
#define LEFT 75
#define RIGHT 77
#define SPACE 32
#define ESC 27
整体:初始化棋盘——初始化蛇头与蛇身——打印蛇——进行游戏
游戏:蛇移动(通过接收键盘)——打印蛇——判断触碰的内容(墙=游戏结束,食物=长度加 一,空=继续游戏)
2.正式实现贪吃蛇
2.1在开始前我们先包头文件和宏定义
#pragma once#include <stdio.h>
#include <windows.h>
#include <conio.h>
#include <stdlib.h>
#include <time.h>#define ROW 22
#define COL 42#define BlANK 0
#define WALL 1
#define FOOD 2
#define HEAD 3
#define BODY 4#define UP 72
#define DOWN 80
#define LEFT 75
#define RIGHT 77
#define SPACE 32
#define ESC 27
接下来我们先实现这次的重点——实现光标跳转函数
光标跳转可以让我们实现在任意位置的打印,这个非常有用
void CursorJump(int x, int y)//传入需要跳转的位置
{COORD pos;//存放横纵坐标的一个结构体pos.X = x;//赋值pos.Y = y;//赋值HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);//接收屏幕句柄SetConsoleCursorPosition(handle, pos);//将光标放置到pos处
}
这里的COORD不需要你自己定义,直接使用就可以了。这个结构体内部包含一个横坐标,一个纵坐标
调用函数,光标跳转到指定地点,我们就可以实现任意位置的打印。
为了游戏的美观我们需要隐藏光标
void HideCursor()
{CONSOLE_CURSOR_INFO curInfo;curInfo.dwSize = 1;curInfo.bVisible = FALSE;HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);SetConsoleCursorInfo(handle, &curInfo);
}
2.2创建游戏区并且初始化
int face[ROW][COL];
先创建一个长*宽大小的二维数组,用来存放游戏区每个格子的情况
初始化游戏区
void InitInterface()
{for (int i = 0; i < ROW; i++)//需要打印ROW行{for (int j = 0; j < COL; j++){if (j == 0 || j == COL - 1)//第一列或者最后一列{face[i][j] = WALL; //标记该位置为墙CursorJump(2 * j, i);//光标跳转printf("■");}else if (i == 0 || i == ROW - 1)//第一行和最后一行{face[i][j] = WALL; //标记该位置为墙printf("■");}else{face[i][j] = BlANK; //标记该位置为空}}}
}
初始化后我们就得到了游戏区,并且将游戏区的内容存放到数组中
2.3初始化蛇头与蛇身
void Initsnake()
{snake.len = 2;//蛇的初始长度为2snake.x = COL / 2;//蛇头初始位置snake.y = ROW / 2;//蛇头初始位置//第一个蛇身body[0].x = COL / 2-1;body[0].y = ROW / 2;//第二个蛇身body[1].x = COL / 2-2;body[1].y = ROW / 2;face[snake.y][snake.x] = HEAD;//标记该位置为头face[body[0].y][body[0].x] = BODY;//标记该位置为身子face[body[1].y][body[1].x] = BODY;//标记该位置为身子
}
2.4打印与覆盖蛇
这里实现蛇移动的方法是利用空格覆盖来实现蛇的移动
void DrawSnake(int flag)//利用flag来决定是打印还是覆盖
{if (flag == 1)//打印蛇{CursorJump(2 * snake.x, snake.y);//光标跳转到蛇头位置printf("■");//打印蛇头for (int i = 0; i < snake.len; i++)//利用循环打印蛇身{CursorJump(2 * body[i].x, body[i].y);//光标跳转到蛇身的位置printf("□");//打印蛇身}}else//覆盖蛇{if (body[snake.len - 1].x != 0)//蛇身不为空{CursorJump(2 * body[snake.len-1 ].x, body[snake.len-1 ].y);printf(" ");//空格覆盖}}
}
2.5实现蛇的移动
思路:将原来的蛇覆盖后打印新蛇
void MoveSneke(int x, int y)
{DrawSnake(0);//先覆盖之前的蛇face[body[snake.len - 1].y][body[snake.len - 1].x] = BlANK;//将覆盖后的标记为空for (int i = snake.len - 1; i > 0; i--){body[i].x = body[i - 1].x;//将后一个身子的坐标放到前一个身子body[i].y = body[i - 1].y;}body[0].x = snake.x;body[0].y = snake.y;snake.x = snake.x + x;snake.y = snake.y + y;DrawSnake(1);//打印蛇
}
画图更容易理解





2.6蛇移动
void run(int x, int y)
{int t = 0;while (1){if (t == 0){t = 6000;//蛇移动的速度}while (--t){if (kbhit() != 0)//检测是否有键盘输入,有就返回非0break;}if (t == 0){judgeFunc(x, y);//判断游戏是否结束MoveSneke(x, y);//移动蛇}else{break;}}
}
2.7食物的随机生成
void RandFood()
{int i, j;do{i = rand() % ROW;//随机生成坐标j = rand() % COL;} while (face[i][j] != BlANK);//判断此坐标是否为空,不为空就重新生成face[i][j] = FOOD;//在为空的地方标记食物CursorJump(2 * j, i);//跳转打印食物printf("●");
}
2.8判断游戏是否结束
void judgeFunc(int x, int y)
{if (face[snake.y + y][snake.x + x] == FOOD)//如果这个地方是食物{snake.len++;//蛇身长度+1RandFood();//重新随机生成食物}else if (face[snake.y + y][snake.x + x] == WALL)//如果位置是墙{Sleep(1000);//给玩家反应时间system("cls");//清屏CursorJump(2 * (COL / 3), ROW / 2 + 3);printf("game over,agin? y/n");char n;scanf("%c", &n);if (n == 'y'){system("cls");main();}else{exit(0);}}
}
3.整体游戏逻辑
void game2()
{int n = RIGHT;//默认向右移动int tmp = 0;goto first;while (1){n = getch();//接收玩家键盘输入switch (n){case UP:case DOWN:if (tmp != LEFT && tmp != RIGHT)//玩家按上下,但是上一次不是左右{n = tmp;//方向改为上或下}break;case LEFT:case RIGHT:if (tmp != UP && tmp != DOWN){n = tmp;}case SPACE:case ESC:case 'r':case 'R':break;default:n = tmp;break;}first:switch (n){case UP:run(0, -1);tmp = UP;break;case DOWN:run(0, 1);tmp = DOWN;break;case LEFT:run(-1, 0);tmp = LEFT;break;case RIGHT:run(1, 0);tmp = RIGHT;break;case SPACE:system("pause>nul");break;case ESC:system("cls");CursorJump(COL - 8, ROW / 2);printf("game over");CursorJump(COL - 8, ROW / 2);exit(0);case 'r':case 'R':system("cls");main();}}
}
4.完整代码
#include <stdio.h>
#include <windows.h>
#include <conio.h>
#include <stdlib.h>
#include <time.h>#define ROW 22
#define COL 42#define BlANK 0
#define WALL 1
#define FOOD 2
#define HEAD 3
#define BODY 4#define UP 72
#define DOWN 80
#define LEFT 75
#define RIGHT 77
#define SPACE 32
#define ESC 27int max, grade;
struct snakehead
{int x;int y;int len;
}snake;struct snakebody
{int x;int y;
}body[ROW*COL];int face[ROW][COL];void HideCursor();//隐藏光标
void CursorJump(int x, int y);
void InitInterface();
void Initsnake();
void DrawSnake(int flag);
void MoveSneke(int x, int y);
void run(int x, int y);
void judgeFunc(int x, int y);
void RandFood();void HideCursor()
{CONSOLE_CURSOR_INFO curInfo;curInfo.dwSize = 1;curInfo.bVisible = FALSE;HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);SetConsoleCursorInfo(handle, &curInfo);
}
void CursorJump(int x, int y)
{COORD pos;pos.X = x;pos.Y = y;HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);SetConsoleCursorPosition(handle, pos);
}
void InitInterface()
{//color(6);for (int i = 0; i < ROW; i++){for (int j = 0; j < COL; j++){if (j == 0 || j == COL - 1){face[i][j] = WALL; //标记该位置为墙CursorJump(2 * j, i);printf("■");}else if (i == 0 || i == ROW - 1){face[i][j] = WALL; //标记该位置为墙printf("■");}else{face[i][j] = BlANK; //标记该位置为空}}}
}void Initsnake()
{snake.len = 2;snake.x = COL / 2;snake.y = ROW / 2;body[0].x = COL / 2-1;body[0].y = ROW / 2;body[1].x = COL / 2-2;body[1].y = ROW / 2;face[snake.y][snake.x] = HEAD;face[body[0].y][body[0].x] = BODY;face[body[1].y][body[1].x] = BODY;
}void DrawSnake(int flag)
{//system("cls");//InitInterface();if (flag == 1){CursorJump(2 * snake.x, snake.y);printf("■");for (int i = 0; i < snake.len; i++){CursorJump(2 * body[i].x, body[i].y);printf("□");}}else{if (body[snake.len - 1].x != 0){CursorJump(2 * body[snake.len-1 ].x, body[snake.len-1 ].y);printf(" ");}}
}void MoveSneke(int x, int y)
{DrawSnake(0);face[body[snake.len - 1].y][body[snake.len - 1].x] = BlANK;for (int i = snake.len - 1; i > 0; i--){body[i].x = body[i - 1].x;body[i].y = body[i - 1].y;}body[0].x = snake.x;body[0].y = snake.y;snake.x = snake.x + x;snake.y = snake.y + y;DrawSnake(1);
}void run(int x, int y)
{int t = 0;while (1){if (t == 0){t = 6000;}while (--t){if (kbhit() != 0)break;}if (t == 0){judgeFunc(x, y);MoveSneke(x, y);}else{break;}}
}
void judgeFunc(int x, int y)
{if (face[snake.y + y][snake.x + x] == FOOD){snake.len++;grade += 10;RandFood();}else if (face[snake.y + y][snake.x + x] == WALL){Sleep(1000);system("cls");CursorJump(2 * (COL / 3), ROW / 2 + 3);printf("game over,agin? y/n");char n;scanf("%c", &n);if (n == 'y'){system("cls");main();}else{exit(0);}}
}
void RandFood()
{int i, j;do{i = rand() % ROW;j = rand() % COL;} while (face[i][j] != BlANK);face[i][j] = FOOD;CursorJump(2 * j, i);printf("●");
}void game()
{//printf("贪吃蛇\n");//创建游戏区域HideCursor();InitInterface();Initsnake();DrawSnake(1);RandFood();game2();}int main()
{game();return 0;
}
void game2()
{int n = RIGHT;int tmp = 0;goto first;while (1){n = getch();switch (n){case UP:case DOWN:if (tmp != LEFT && tmp != RIGHT){n = tmp;}break;case LEFT:case RIGHT:if (tmp != UP && tmp != DOWN){n = tmp;}case SPACE:case ESC:case 'r':case 'R':break;default:n = tmp;break;}first:switch (n){case UP:run(0, -1);tmp = UP;break;case DOWN:run(0, 1);tmp = DOWN;break;case LEFT:run(-1, 0);tmp = LEFT;break;case RIGHT:run(1, 0);tmp = RIGHT;break;case SPACE:system("pause>nul");break;case ESC:system("cls");CursorJump(COL - 8, ROW / 2);printf("game over");CursorJump(COL - 8, ROW / 2);exit(0);case 'r':case 'R':system("cls");main();}}
}














![C语言实现贪吃蛇[内附详细步骤]](https://img-blog.csdnimg.cn/cd8a415638344a99bd95d3d801c643c7.png)




