项目基本分析
1.项目目标:
通过参考文献《贪吃蛇游戏用户开发与使用》文献和参考网上代码,编写一个能够在Visual C++ 6.0环境下运行的贪吃蛇游戏程序。
2.项目功能:
包括以下几个方面:蛇的生命周期、分数统计、是否死亡。
- 蛇的运动范围是在边框内,这里我想用坐标来限制,周期的话就是蛇的长度;
- 分数统计就直接定义一个数来储存,然后但蛇吃到食物的时候就更新分数;
- 死亡情况的话,有两种:一是碰到边框,二是碰到自己
一.整体设计
-
函数分快
-
主函数
int main()
{
//打印初始化界面
printf_JM();
printf_snake();
printf_foot();
while(1)
{
YX(); //运行
if (!died())
break; //如果死了就跳出while(1)循环
creatfood(); //判断是否是否被吃,然后产生食物
control_xy(82,5);
printf("sorce:%d\n",sorce);
Sleep(snake.speed);//变速
}
control_xy(30, 26);
printf("Game Over!\n");
control_xy(40, 26);
printf("本次游戏得分为:%d\n", sorce);
Sleep(500);
return 0;
}
一.详细流程
1.整体流程
2.各模块流程
- 用结构体定义属性
- 初始化界面
- 移动蛇
- 判断食物是否产生
- 死亡情况
四.公用结构体说明
1.coord函数的用法:
来自<Windows.h>里的一个函数
作用:表示文字在控制台的坐标,俗称坐标结构
//将光标移到控制台的(x,y)位置
void control_xy(int x, int y)
{
COORD coord;
coord.X = x;
coord.Y = y;
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord);
}
2.定义食物、蛇的属性
//食物的坐标
struct
{
int x; //前边已经有过光标在控制台的定义的函数,所以这里的坐标只需要用x和y来就好
int y;
}food;//蛇的属性
struct
{
int speed;//蛇的速度
int len;//蛇的长度
int x[snakesize];//蛇的每一节的坐标
int y[snakesize];//
}snake;
3.申明全局变量宏定义
#define snakesize 100 //蛇的最长长度
#define width 78 //主边框宽度
#define total 108 //总宽
#define height 24 //主边框高度
#define width1 30 //显示分数的边框宽度int i;
int sorce; //来记录学生的分数
int PD; //来判断食物是不是被蛇吃掉了
int key=72; /*来存键值,一开始默认方向向上
上:72
下:80
左:75
右:77
*/
五.各函数模块
1.界面的初始化
//打印原始游戏界面
void printf_JM()
{
//打印上下边框
for (i = 0; i <= total; i += 2)//i+=2是因为横向占用的是两个位置
{
control_xy(i, 0);
printf("■");
control_xy(i, height);
printf("■");
}
//打印左右边框
for (i = 1; i < height; i++)
{
control_xy(0, i);//第一条
printf("■");
control_xy(width, i);//第二条
printf("■");
control_xy(total, i);//第三条
printf("■");
}
//在第二个边框输出分数和规则
//control_xy(82,5);
//printf("sorce:%d",sorce);
control_xy(82,8);
printf("【游戏规则】");
control_xy(82,10);
printf("键盘上的方向键控制蛇运动");
control_xy(82,12);
printf("吃到一个食物得10分");
control_xy(82,14);
printf("当蛇碰到边框或蛇身则死亡\n");
}
//打印蛇身
void printf_snake()
{
//初始化蛇的属性
snake.len = 3;
snake.speed = 200;
//在屏幕中间生成蛇头
snake.x[0] = width / 2 + 1;//x坐标为偶数
snake.y[0] = height / 2;
//打印蛇头
control_xy(snake.x[0], snake.y[0]);
printf("■");
//生成初试的蛇身
for (i = 1; i < snake.len; i++)
{
//蛇身的打印,纵坐标不变,横坐标为上一节蛇身的坐标值+2
snake.x[i] = snake.x[i - 1] + 2;
snake.y[i] = snake.y[i - 1];
control_xy(snake.x[i], snake.y[i]);
printf("■");
}
control_xy(width / 2, 10);
return;
}
//随机生成食物
void printf_foot()
{
// printf_JM();
//printf_snake();
while (1)
{
srand((unsigned int)time(NULL)); //利用srand函数随机产生坐标
food.x = rand() % (width - 4) + 2;
food.y = rand() % (height - 2) + 1;
if (food.x % 2 == 0)
break;
}
//将光标移到食物的坐标处打印食物
control_xy(food.x,food.y);
printf("■");
//打印完食物后将光标移到屏幕最下方,避免光标在蛇身处一直闪烁
control_xy(width - 2, 27);
return;
}
2.开始运行,通过方向键移动蛇身
void YX()
{
int pre_key = key;//用来存放前一个键值,因为蛇移动的值不能和原来的相反,所以要根据这个去判断
if (_kbhit())
{
fflush(stdin);//清空缓冲区的字符
key = _getch();//返回0或者224
key = _getch();//返回实际值
}
//如果食物没有被次,这蛇尾消除
if (PD == 0)
{
control_xy(snake.x[snake.len - 1], snake.y[snake.len - 1]);
printf(" ");//在蛇尾处输出空格即擦去蛇尾
}
for (i = snake.len - 1; i > 0; i--)
{
snake.x[i] = snake.x[i - 1];
snake.y[i] = snake.y[i - 1];
}
//蛇当前移动的方向不能和前一次的方向相反,比如蛇往左走的时候不能直接按右键往右走
//如果当前移动方向和前一次方向相反的话,把当前移动的方向改为前一次的方向
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:
snake.x[0] -= 2;//往左
break;
case 77:
snake.x[0] += 2;//往右
break;
case 72:
snake.y[0]--;//往上
break;
case 80:
snake.y[0]++;//往下
break;
}
control_xy(snake.x[0], snake.y[0]); //打印出蛇头
printf("■");
control_xy(width - 2, 0);
PD = 0;//由于目前没有吃到食物,PD值为0
return;
}
5.是否重生成食物
void creatfood()
{
if (snake.x[0] == food.x && snake.y[0] == food.y)//蛇头碰到食物
{
//蛇头碰到食物即为要吃掉这个食物了,因此需要再次生成一个食物
while (1)
{
int flag = 1;
srand((unsigned int)time(NULL));
food.x = rand() % (width - 4) + 2;
food.y = rand() % (height - 2) + 1;
//随机生成的食物不能在蛇的身体上
for (i = 0; i < snake.len; i++)
{
if (snake.x[i] == food.x && snake.y[i] == food.y)
{
flag = 0;
break;
}
}
if (flag && food.x % 2 == 0)
break;
}
//绘制食物
control_xy(food.x, food.y);
printf("■");
snake.len++;//吃到食物,蛇身长度加1
sorce += 10;//每个食物得10分
snake.speed -= 5;变速
PD = 1;
}
return;
}
6.蛇死亡情况
//蛇死亡情况
bool died()
{
if (snake.y[0] == 0 || snake.y[0] == height)//上下边界
return 0;
if (snake.x[0] == 0 || snake.x[0] == width)//左右边界
return 0;
for (i = 1; i < snake.len; i++)//自己碰自己
{
if (snake.x[i] == snake.x[0] && snake.y[i] == snake.y[0])
return 0;
}
return 1;
}