前言

本篇基于Esayx图形库的基础上,在Visual Studio编译器上运行,主要通过构建各个不同功能的函数(面向过程)来实现这款经典的小游戏———贪吃蛇

一 主要函数

//该函数用于绘制出一个网格出来
void paintGrid();

//该函数用于绘制出一个蛇
void paintSnake(node* snake, int n);

//该函数将依次移动蛇节头并根据前进方向设置蛇头
//以此来控制蛇的移动
node snakeMove(node* snake, int length, int direction);

//该函数通过键盘输入的方式来调整蛇移动的方向
void changDirection(enum direction* p);

//该函数用于在画布中创建出一个食物类型
node creatFood(node* snake, int length);

//该函数用于在画布中生成一个食物
void paintFood(node* food);

//该函数用于判断游戏是否结束
bool isGameover(node* snake, int length);

//该函数用于将游戏数据初始化
void reset(node* snake, int* plength, enum direction* pd);

二 对各个函数进行实现

1.定义结构体以及一些枚举变量、常量

//我们创建的画布大小是600*800大小的,将其分成宽为40的小矩形#define NOOD_WIDTH 40 //该枚举类型分别对应四个方向,用键盘上的wsad来表示上下左右enum direction{eUp,eDown,eLeft,eRight};//该结构node用于记录蛇的每一个节点typedef struct{int x;int y;}node;

2.//该函数用于绘制出一个网格出来
void paintGrid();

void paintGrid(){setlinecolor(WHITE);for (int x = 0; x < 800; x += NOOD_WIDTH)//以这个宽度为间距进行画竖线{line(x, 0, x, 600);//画竖线}for (int y = 0; y < 600; y += NOOD_WIDTH)//以这个宽度为间距进行画横线{line(0, y, 800, y);//画横线}}

3.//该函数用于绘制出一个蛇
void paintSnake(node* snake, int n);

void paintSnake(node* snake, int n){int left, top, right, bottom;for (int i = 0; i < n; i++){left = snake[i].x * NOOD_WIDTH;//*(snake + i).xtop = snake[i].y * NOOD_WIDTH;right = (snake[i].x + 1) * NOOD_WIDTH;bottom = (snake[i].y + 1) * NOOD_WIDTH;setlinecolor(BLACK);fillrectangle(left, top, right, bottom);}}

4.//该函数将依次移动蛇节头并根据前进方向设置蛇头
//以此来控制蛇的移动
node snakeMove(node* snake, int length, int direction);

node snakeMove(node* snake, int length, int direction){node tail = snake[length - 1];//用一个循环将数组中的元素从后往前依次进行覆盖for (int i = length - 1; i > 0; i--){snake[i] = snake[i - 1];//将前一个节点覆盖后一个节点}node newhead = snake[0];if (direction == eUp){newhead.y--;//在原蛇头的基础上进行修改}if (direction == eDown){newhead.y++;}if (direction == eLeft){newhead.x--;}if (direction == eRight){newhead.x++;}snake[0] = newhead;//最后在把修改后的蛇头数据赋值给原数组的首元素return tail;}

5. //该函数通过键盘输入的方式来调整蛇移动的方向
void changDirection(enum direction* p);

void changDirection(enum direction* p){if (_kbhit() != 0){char c = _getch();switch (c){case 'a':if(*p != eRight)*p = eLeft;break;case 'd':if (*p != eLeft)*p = eRight;break;case 'w':if (*p != eDown)*p = eUp;break;case's':if (*p != eUp)*p = eDown;break;}}}

6.//该函数用于在画布中创建出一个食物类型
node creatFood(node* snake, int length);

node creatFood(node* snake, int length){//先在画布圈定的范围之内随机生成一个食物点node food;//然后用一个死循环来对食物点进行检验(不能与蛇的身体进行重合)while (1){food.x = rand() % (800 / NOOD_WIDTH);food.y = rand() % (600 / NOOD_WIDTH);int i = 0;for (i = 0; i < length; i++){if (food.x == snake[i].x && food.y == snake[i].y)break;}if (i < length)continue;elsebreak;}return food;}

7.//该函数用于在画布中生成一个食物
void paintFood(node* food);

void paintFood(node* food){int left, top, right, bottom;left = food->x * NOOD_WIDTH;//*(snake + i).xtop = food->y* NOOD_WIDTH;right = (food->x + 1) * NOOD_WIDTH;bottom = (food->y + 1) * NOOD_WIDTH;setfillcolor(YELLOW);solidrectangle(left, top, right, bottom);setfillcolor(WHITE);}

8.//该函数用于判断游戏是否结束
bool isGameover(node* snake, int length);

bool isGameover(node* snake, int length){if (snake[0].x 800 / NOOD_WIDTH){return true;}if (snake[0].y 600 / NOOD_WIDTH){return true;}for (int i = 1; i < length; i++){if (snake[0].x == snake[i].x && snake[0].y == snake[i].y)return true;}return false;}

9.//该函数用于将游戏数据初始化
void reset(node* snake, int* plength, enum direction* pd);

void reset(node* snake, int* plength, enum direction* pd){for (int i = 0; i  0; j--){snake[i].x = j;}snake[i].y = 7;}*plength = 5;*pd = eRight;}

三 主函数部分

int main(){initgraph(800, 600);setbkcolor(RGB(164, 225, 202));cleardevice();node snake[100] = { {5,7},{4,7},{3,7},{2,7},{1,7} };int length = 5;enum direction d = eRight;srand(unsigned int(time(NULL)));//用当前时间作为随机数种子node food = creatFood(snake,length);while (1){cleardevice();paintGrid();paintSnake(snake, length);paintFood(&food);Sleep(500);changDirection(&d);node last_tail = snakeMove(snake, length, d);if (snake[0].x == food.x && snake[0].y == food.y){if (length < 100){snake[length] = last_tail;length++;}food = creatFood(snake, length);}if (isGameover(snake, length) == true){reset(snake, &length, &d);food = creatFood(snake, length);}}getchar();closegraph();return 0;}

四 完整代码

完整代码如下:

#include #include #include #include #define NODE_WIDTH 40// 节点typedef struct {int x;int y;}node;enum direction{eUp,eDown,eLeft,eRight};void paintGrid(){setlinecolor(WHITE);for (int x = 0; x < 800; x += NOOD_WIDTH){line(x, 0, x, 600);//画竖直线段}for (int y = 0; y < 600; y += NOOD_WIDTH){line(0, y, 800, y);//画竖直线段}}void paintSnake(node* snake, int n){int left, top, right, bottom;for (int i = 0; i  0; i--){snake[i] = snake[i - 1];//将前一个节点覆盖后一个节点}node newhead = snake[0];if (direction == eUp){newhead.y--;//在原蛇头的基础上进行修改}if (direction == eDown){newhead.y++;}if (direction == eLeft){newhead.x--;}if (direction == eRight){newhead.x++;}snake[0] = newhead;//最后在把修改后的蛇头数据赋值给原数组的首元素return tail;}void changDirection(enum direction* p){if (_kbhit() != 0){char c = _getch();switch (c){case 'a':if(*p != eRight)*p = eLeft;break;case 'd':if (*p != eLeft)*p = eRight;break;case 'w':if (*p != eDown)*p = eUp;break;case's':if (*p != eUp)*p = eDown;break;}}}node creatFood(node* snake, int length){//先在画布圈定的范围之内随机生成一个食物点node food;//然后用一个死循环来对食物点进行检验(不能与蛇的身体进行重合)while (1){food.x = rand() % (800 / NOOD_WIDTH);food.y = rand() % (600 / NOOD_WIDTH);int i = 0;for (i = 0; i < length; i++){if (food.x == snake[i].x && food.y == snake[i].y)break;}if (i x * NOOD_WIDTH;//*(snake + i).xtop = food->y* NOOD_WIDTH;right = (food->x + 1) * NOOD_WIDTH;bottom = (food->y + 1) * NOOD_WIDTH;setfillcolor(YELLOW);solidrectangle(left, top, right, bottom);setfillcolor(WHITE);}bool isGameover(node* snake, int length){if (snake[0].x 800 / NOOD_WIDTH){return true;}if (snake[0].y 600 / NOOD_WIDTH){return true;}for (int i = 1; i < length; i++){if (snake[0].x == snake[i].x && snake[0].y == snake[i].y)return true;}return false;}void reset(node* snake, int* plength, enum direction* pd){for (int i = 0; i  0; j--){snake[i].x = j;}snake[i].y = 7;}*plength = 5;*pd = eRight;}int main(){initgraph(800, 600);setbkcolor(RGB(164, 225, 202));cleardevice();node snake[100] = { {5,7},{4,7},{3,7},{2,7},{1,7} };int length = 5;enum direction d = eRight;srand(unsigned int(time(NULL)));//用当前时间作为随机数种子node food = creatFood(snake,length);while (1){cleardevice();paintGrid();paintSnake(snake, length);paintFood(&food);Sleep(500);changDirection(&d);node last_tail = snakeMove(snake, length, d);if (snake[0].x == food.x && snake[0].y == food.y){if (length < 100){snake[length] = last_tail;length++;}food = creatFood(snake, length);}if (isGameover(snake, length) == true){reset(snake, &length, &d);food = creatFood(snake, length);}}getchar();closegraph();return 0;}