600字范文,内容丰富有趣,生活中的好帮手!
600字范文 > 【C语言】贪吃蛇小游戏代码详解

【C语言】贪吃蛇小游戏代码详解

时间:2020-02-28 13:50:41

相关推荐

【C语言】贪吃蛇小游戏代码详解

贪吃蛇的规则大家应该都知道,简单来说就是吃到食物则蛇身增长,蛇可以在游戏区域内随意移动。游戏结束条件就是蛇撞到边界或者撞到自己色蛇身。

首先,实现一个函数,这个函数的作用是将光标移动到我们所期望的位置

/** 控制光标所在的位置*/void gotoxy(int x, int y){COORD coord;coord.X = x;coord.Y = y;SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord);}

构建结构体对象

设计这个游戏,最重要的两个对象就是蛇和食物,因此用两个结构体来代表这两个对象。食物只关注其坐标位置,蛇的话,成员包括坐标数组,长度和分数。

// 定义游戏区域的边界宽度#define WIDTH 100#define HIGH 20// 定义蛇的最大长度#define MAX_LENGHT 100// 定义游戏初始速度#define SPEED 500// 定义游戏中的两个对象:食物和蛇struct{int x;int y;}food;struct{int len;int x_buf[MAX_LENGHT];int y_buf[MAX_LENGHT];int score;}snake;// 要用到的全局变量int food_flag = 0;int key = 72;

初始化游戏边界和小蛇

这个没什么难度,就是循环打印,直接放代码。

/* * 绘制游戏区域边界*/void DrawMap(void){int x, y;for (x = 0; x < WIDTH + 4; x += 2){y = 0;gotoxy(x, y);printf("■");y = HIGH + 2;gotoxy(x, y);printf("■");}for (y = 1; y < HIGH + 2; y++){x = 0;gotoxy(x, y);printf("■");x = WIDTH + 2;gotoxy(x, y);printf("■");}// 将光标移出游戏区域gotoxy(0, HIGH + 5);}

注意最后一行使用gotoxy函数移动函数很重要,不然光标会在游戏区域内持续闪烁,在退出游戏时,甚至会出现显示问题。(为了避免遗漏,我基本在每个涉及到光标移动的函数最后都加了这句话)

/** 初始化小蛇*/void CreateSnake(void){int orgin_x, orgin_y;orgin_x = WIDTH / 2 + 2;orgin_y = HIGH / 2 + 1;snake.len = 3;snake.x_buf[0] = orgin_x;snake.y_buf[0] = orgin_y;snake.x_buf[1] = orgin_x;snake.y_buf[1] = ++orgin_y;snake.x_buf[2] = orgin_x;snake.y_buf[2] = ++orgin_y;snake.score = -1;int i;for (i = 0; i < snake.len; i++){gotoxy(snake.x_buf[i], snake.y_buf[i]);printf("■");}gotoxy(0, HIGH + 5);}

生成食物

我使用一个标志位food_flag来代表区域内是否存在食物(初始时刻,以及蛇吃到食物时,food_flag为0)。当food_flag为0时就执行生成食物的操作。由于要保证游戏的随机性,用随机数来生成食物坐标。

/** 当游戏区域内不存在食物时,随机创造一个食物*/void CreateFood(void){if (food_flag == 0){int flag = 0,i;do{srand((unsigned int)time(NULL));food.x = (rand() % (WIDTH/2))*2 + 2;food.y = rand() % HIGH + 1;// 判断生成的食物是否和蛇身重合for (i = 0; i < snake.len; i++){if (snake.x_buf[i] == food.x && snake.y_buf[i] == food.y){flag = 1;break;}}} while (flag);gotoxy(food.x, food.y);printf("★");// 吃到食物,则分数加1snake.score++;food_flag = 1;}gotoxy(0, HIGH + 5);}

实现的方法都大同小异,但是我强调的点是随机生成坐标的实现。由于字符"■"是占两位,所以横坐标必须为2的倍数。其他的帖子里一般是用以下方法

food.x = rand() % WIDTH + 2;food.y = rand() % HIGH + 1;

然后通过while循环来判断x是否适合要求,不符合就重新生成。但这种做法会出现一种问题,游戏进行过程中会出现卡顿的效果。主要原因就是奇偶数出现概率各占50%,因此有大概率出现多次的循环操作。

我的方法如下,这样的好处是可以保证生成的横坐标一定是偶数。避免了大量的循环操作。

food.x = (rand() % (WIDTH/2))*2 + 2;food.y = rand() % HIGH + 1;

移动小蛇

首先要对snake对象中坐标缓存区内的坐标进行后移,以便装入新的坐标。在此要分两种情况,一是小蛇没吃到食物,则抹去最后一节,在头部加入新坐标;二是小蛇吃到食物,则不删去最后一节。

void SnakeMove(int x, int y){// 判断是否吃到食物,吃到长度加1if (!food_flag)snake.len++;// 没吃到则抹去最后一节else{gotoxy(snake.x_buf[snake.len - 1], snake.y_buf[snake.len - 1]);printf(" ");}int i;for (i = snake.len - 1; i > 0; i--){snake.x_buf[i] = snake.x_buf[i - 1];snake.y_buf[i] = snake.y_buf[i - 1];}snake.x_buf[0] = x;snake.y_buf[0] = y;gotoxy(snake.x_buf[0], snake.y_buf[0]);printf("■");gotoxy(0, HIGH + 5);}

随后根据用户按键,改变小蛇前进方向。这块部分代码也是我移植过来的,有详细的注释,就不在这赘述了。

void move(){int pre_key = key, x, y;if (_kbhit())//如果用户按下了键盘中的某个键{fflush(stdin);//清空缓冲区的字符//getch()读取方向键的时候,会返回两次,第一次调用返回0或者224,第二次调用返回的才是实际值key = _getch();//第一次调用返回的不是实际值key = _getch();//第二次调用返回实际值}// 小蛇移动方向不能和上一次的方向相反if (pre_key == 72 && key == 80)key = 72;if (pre_key == 80 && key == 72)key = 80;if (pre_key == 75 && key == 77)key = 75;if (pre_key == 77 && key == 75)key = 77;switch (key){case 75:x = snake.x_buf[0] - 2;//往左y = snake.y_buf[0];break;case 77:x = snake.x_buf[0] + 2;//往右y = snake.y_buf[0];break;case 72:x = snake.x_buf[0];y = snake.y_buf[0] - 1;//往上break;case 80:x = snake.x_buf[0];y = snake.y_buf[0] + 1;//往下break;}if (x == food.x&&y == food.y)food_flag = 0;SnakeMove(x, y);}

检查游戏进程

主要是包括两个方面,(1)失败:小蛇撞墙或者撞到自己的身体;(2)成功:小蛇长度达到最大长度。

void check(void){int i;// 失败条件if (snake.x_buf[0] == 0 | snake.x_buf[0] == WIDTH + 4 | snake.y_buf[0] == 0 | snake.y_buf[0] == HIGH + 2){printf("Game Over!\n");exit(0);}for (i = 1; i < snake.len; i++){if (snake.x_buf[0] == snake.x_buf[i] && snake.y_buf[0] == snake.y_buf[i]){printf("Game Over!\n");exit(0);}}// 胜利条件if (snake.len == MAX_LENGHT){printf("Your are win!\n");exit(0);}// 打印得分gotoxy(0, HIGH + 6);printf("Your score: %d", snake.score);}

主函数

#include <stdio.h>#include <stdlib.h>#include <Windows.h>#include <time.h>#include <conio.h>int main(void){DrawMap();CreateSnake();while (1){CreateFood();move();// 用于控制游戏的速度Sleep(SPEED - 2 * snake.len);check();}}

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。