c语言贪吃蛇
整体逻辑
- 界面绘制
- 定义结构体以及结构体的初始化
2.1 一节变三节 - 蛇的移动
3.1 监控键盘
3.2 蛇的移动 - 食物
4.1 定义
4.2 初始化
4.3 食物的绘制 - 食物的再生与身体增长、分数
- 死亡与结束
- 优化
7.1 getch()函数会返回两个数值,过滤第一个,留下第二个真实键值
界面绘制与主函数
#include<graphics.h> //图形界面库
#include<stdio.h>
#include<stdlib.h>
int main()
{//界面绘制initgraph(WIN_WIDTH, WIN_HEIGTH);//初始化窗口setbkcolor(RGB(207, 214, 229));//设置背景颜色cleardevice();//刷新窗口//初始化GemeInit();while (1) {//绘制GameDraw();//移动GameMove();BeginBatchDraw();//双缓存机制,减少闪烁//控制键盘KeyControl;FlushBatchDraw();//刷新双缓冲区EatFood();Sleep(100);
}}
定义和初始化
-
蛇
//定义蛇 struct Snake {int num; //蛇身长int dir; //方向int score; //分数int size; //蛇的宽和高 定位int speed;//蛇速度//坐标struct Pos coor[MAX_SNAKE]; }snake; // 定位 struct Pos {int x;int y; };
-
食物
//定义食物 struct Food {int x;int y;bool flag;//判断食物是否存在 }food;
-
初始化
//初始化 void GemeInit() {snake.num = 3;snake.dir = RIGHT;snake.score = 0;snake.size = 15;snake.speed = 10;//三节蛇身的初始化snake.coor[0].x = 200; //修改初始位置,避免蛇身重叠snake.coor[0].y = 200;snake.coor[1].x = 185;snake.coor[1].y = 200;snake.coor[2].x = 170;snake.coor[2].y = 200;//食物的初始化food.x = rand() % (WIN_WIDTH / 10) * 10;food.y = rand() % (WIN_HEIGTH / 10) * 10;food.flag = true; }
根据坐标绘制图形
-
绘制蛇身、食物、分数
void GameDraw() {cleardevice();//清屏//三节蛇身for (int i = 0; i < snake.num; i++){//蛇的填充色setfillcolor(BLACK);//画矩形fillrectangle(snake.coor[i].x, snake.coor[i].y, snake.coor[i].x + snake.size, snake.coor[i].y + snake.size);}//食物,复用蛇身setfillcolor(BLACK);fillrectangle(food.x, food.y, food.x + snake.size, food.y + snake.size);//分数char temp[20] = "";sprintf(temp, "分数%d", snake.score);outtextxy(10, 10, temp); }
蛇的移动
-
监控键盘
void KeyControl() {//只有按键按下时才处理if (_kbhit()) {char key = _getch();//接收getch()函数的第一个返回值char key2 = _getch();//接收getch()函数的第二个返回值,即真实键值if (key == -32) {switch (key2) {case 72:if (snake.dir != DOWN) {snake.dir = UP;printf("↑\n");}break;case 75:if (snake.dir != RIGHT) {snake.dir = LEFT;printf("←\n");}break;case 77:if (snake.dir != LEFT) {snake.dir = RIGHT;printf("→\n");}break;case 80:if (snake.dir != UP) {snake.dir = DOWN;printf("↓\n");}break;}}} }
-
蛇的移动
void GameMove() {//从蛇尾开始覆盖,a,b,c三节考虑。for (int i = snake.num - 1; i > 0; i--) {snake.coor[i].x = snake.coor[i - 1].x;snake.coor[i].y = snake.coor[i - 1].y;}switch (snake.dir) {case UP:snake.coor[0].y -= snake.speed;break;case DOWN:snake.coor[0].y += snake.speed;break;case LEFT:snake.coor[0].x -= snake.speed;break;case RIGHT:snake.coor[0].x += snake.speed;break;} }
吃食物
-
消失与再生
//吃食物 void EatFood() {if (food.flag && snake.coor[0].x == food.x && snake.coor[0].y == food.y) {food.flag = false;snake.num++;snake.score += 10;}CreateFood(); }//生成食物 void CreateFood() {if (!food.flag) {food.x = rand() % (WIN_WIDTH / 10) * 10;food.y = rand() % (WIN_HEIGTH / 10) * 10;food.flag = true;} }
完整代码
/*
1. 界面绘制
2. 定义结构体以及结构体的初始化2.1 一节变三节,绘制蛇身
3. 蛇的移动3.1 监控键盘3.2 蛇的移动
4. 绘制食物4.1 定义4.2 初始化4.3 食物的绘制
5. 食物的再生与身体增长、分数
6. 死亡与结束
7. 优化7.1 getch()函数会返回两个数值,过滤第一个,留下第二个真实键值
*/#include<graphics.h> //图形界面库
#include<stdio.h>
#include <conio.h> //键盘监控
#include<stdlib.h>#define MAX_SNAKE 500
#define WIN_WIDTH 640
#define WIN_HEIGTH 480// 定位
struct Pos
{int x;int y;
};// 蛇的结构体
struct Snake {int num; //蛇身长int dir; //方向int score; //分数int size; //蛇的宽和高 定位int speed;//蛇速度//坐标struct Pos coor[MAX_SNAKE];
}snake;struct Food {int x;int y;bool flag;//判断食物是否存在
}food;//枚举类型定义方向
enum DIR {UP,DOWN,LEFT,RIGHT
};//初始化
void GemeInit() {snake.num = 3;snake.dir = RIGHT;snake.score = 0;snake.size = 15;snake.speed = 10;//三节蛇身snake.coor[0].x = 200; //修改初始位置,避免蛇身重叠snake.coor[0].y = 200;snake.coor[1].x = 185;snake.coor[1].y = 200;snake.coor[2].x = 170;snake.coor[2].y = 200;//食物food.x = rand() % (WIN_WIDTH / 10) * 10;food.y = rand() % (WIN_HEIGTH / 10) * 10;food.flag = true;}// 绘制三节蛇身、食物、分数
void GameDraw() {cleardevice();//for (int i = 0; i < snake.num; i++){//蛇的填充色setfillcolor(BLACK);//画矩形fillrectangle(snake.coor[i].x, snake.coor[i].y, snake.coor[i].x + snake.size, snake.coor[i].y + snake.size);}//食物的填充色setfillcolor(BLACK);//画矩形fillrectangle(food.x, food.y, food.x + snake.size, food.y + snake.size);char temp[20] = "";sprintf(temp, "分数%d", snake.score);outtextxy(10, 10, temp);
}//蛇的移动
void GameMove() {//从蛇尾开始覆盖,a,b,c三节考虑。for (int i = snake.num - 1; i > 0; i--) {snake.coor[i].x = snake.coor[i - 1].x;snake.coor[i].y = snake.coor[i - 1].y;}switch (snake.dir) {case UP:snake.coor[0].y -= snake.speed;break;case DOWN:snake.coor[0].y += snake.speed;break;case LEFT:snake.coor[0].x -= snake.speed;break;case RIGHT:snake.coor[0].x += snake.speed;break;}
}//监控键盘
void KeyControl() {//只有按键按下时才处理if (_kbhit()) {char key = _getch();//接收getch()函数的第一个返回值char key2 = _getch();//接收getch()函数的第二个返回值,即真实键值if (key == -32) {switch (key2) {case 72:if (snake.dir != DOWN) {snake.dir = UP;printf("↑\n");}break;case 75:if (snake.dir != RIGHT) {snake.dir = LEFT;printf("←\n");}break;case 77:if (snake.dir != LEFT) {snake.dir = RIGHT;printf("→\n");}break;case 80:if (snake.dir != UP) {snake.dir = DOWN;printf("↓\n");}break;}}}
}//生成食物
void CreateFood() {if (!food.flag) {food.x = rand() % (WIN_WIDTH / 10) * 10;food.y = rand() % (WIN_HEIGTH / 10) * 10;food.flag = true;}
}//吃食物
void EatFood() {if (food.flag && snake.coor[0].x == food.x && snake.coor[0].y == food.y) {food.flag = false;snake.num++;snake.score += 10;}CreateFood();
}int main()
{//界面绘制initgraph(WIN_WIDTH, WIN_HEIGTH);//初始化窗口setbkcolor(RGB(207, 214, 229));//设置背景颜色cleardevice();//刷新窗口GemeInit();while (1) {//绘制GameDraw();//移动GameMove();BeginBatchDraw();//双缓存机制,减少闪烁//控制键盘KeyControl;FlushBatchDraw();//刷新双缓冲区EatFood();Sleep(100);}
}