本节需用到的知识点:

(1)结构体知识

(1)蛇运动轨迹的判定

怎样检测蛇是否碰到围墙或事物呢,so easy,只要判定蛇头的位置是否与围墙或食物的位置重合,用C语言来表述就是

if(snake_x==food_x&&snake_y==food_y) //蛇头与食物位置重合

if(snake_x==0||snake_x==19||snake_y==0||snake_y==39) //蛇头位置与四周墙体重合

我们可以再单独写一个函数,检测发生碰撞后,再执行相应的语句

void ishit()
{
if(snake_x==food_x&&snake_y==food_y)//判断蛇头位置是否与食物位置相重合
{
//如果随机生成的食物位置与围墙或蛇体或墙体重合,则循环再次随机生成食物位置
while(map[food_x][food_y]!=0)
{
food_x=rand()%19+1; //随机在1-19的位置产生食物
food_y=rand()%39+1; //随机在1-39的位置产生食物
}
map[food_x][food_y]=4; //在地图上显示食物
}
if(snake_x==0||snake_x==19||snake_y==0||snake_y==39)//判断蛇头位置是否与墙的位置重合
{
system("pause"); //暂停程序
exit(0); //退出程序
}
}

但是随后新的问题又诞生了,蛇吃了食物是应该变长了,为解决此问题,我们需要定义一个结构体数组来表示蛇的身体

struct Snake
{
int x; //每节蛇的x坐标
int y; //每节蛇的y坐标
}snake[800];

同时我们再声明一个整型变数,既可以表示得分,又可以表示蛇的长度,蛇每吃一个食物得一分,加长一节

下面咱们讨论一下蛇怎样沿著一定的轨迹运动的问题,假设蛇身总共为6节,分别是snake[0]到snake[5],向前移动的示意图如下:

由此可以看出,先前移动一次,只需要将数组中前一个的值赋给后一个值即可,知道了此规律,我们就可以继续向下编写了,主要部分如下

for(int i=score;i>0;i--)
{
snake[i].x=snake[i-1].x;
snake[i].y=snake[i-1].y;
map[snake[i].x][snake[i].y]=3;
}

因为加入了结构体部分,重新定义了关于蛇的结构体数组,所以程序内整改部分叫多,下面将完成程序写出:

#include <stdio.h>
#include<Windows.h>
#include<conio.h>
struct Snake
{
int x; //每节蛇的x坐标
int y; //每节蛇的y坐标
}snake[800];

int map[20][40]; //二维数组map[][],用来表示游戏地图
//为0时,表示空白,什么都没有
//为1时,表示上下围墙
//为2时,表示左右围墙
//为3时,表示蛇
//为4时,表示食物

int direction=1; //1表示向上,程序开始默认向上
//2表示向下
//3表示向左
//4表示向右
int food_x=15,food_y=6; //食物位置
int score=0; //游戏得分

void clear()
{
HANDLE handle=GetStdHandle(STD_OUTPUT_HANDLE);//获取标准输出设备句柄
COORD coord; //定义游标位置结构体,其中包含x y坐标两个变数
coord.X=0; //x=0屏幕最上方
coord.Y=0; //y=0屏幕最左边
SetConsoleCursorPosition(handle,coord);//将游标位置移至屏幕左上角
}

void show() //显示界面
{
for(int i=0;i<20;i++) //列印地图
{
for(int j=0;j<40;j++)
switch(map[i][j])
{
case 0: printf(" ");break; //0代表空格,什么也不列印
case 1: printf("-");break; //1代表上下围墙
case 2: printf("|");break; //2代表左右围墙
case 3: printf("@");break; //3代表蛇身用@表示
case 4: printf("$");break; //4代表食物用$表示
}
printf("
");
}
printf("游戏得分: %d",score);
}

void init() //初始化地图
{
int i,j;
for(i=0;i<20;i++)
for(j=0;j<40;j++)
map[i][j]=0; //初始化二维数组,全部置为0

for(i=0;i<20;i++)
for(j=0;j<40;j++)
{
if(i==0||i==19)
map[i][j]=1; //赋值上下围墙 ----------
if(j==0||j==39)
map[i][j]=2; //赋值左右围墙|||||||||||
}

snake[0].x=10;
snake[0].y=20;
map[snake[0].x][snake[0].y]=3; //利用变数在地图中间初始化蛇身
map[food_x][food_y]=4; //初始化食物位置,随便定义了一个位置
show();
}

void move() //响应键盘输入,控制蛇的移动
{
map[snake[score].x][snake[score].y]=0;//将最后一节赋值为0

if(kbhit())
{
char c;
c=getch();
switch(c)
{
case w:direction=1; break; //按w键,蛇向上移动
case s:direction=2; break; //按s键,蛇向下移动
case a:direction=3; break; //按a键,蛇向左移动
case d:direction=4; break; //按d键,蛇向右移动
default: break;
}
}

for(int i=score;i>0;i--)
{
snake[i].x=snake[i-1].x;
snake[i].y=snake[i-1].y;
map[snake[i].x][snake[i].y]=3;
}

switch(direction) //根据direction值,改变蛇的坐标
{
case 1:snake[0].x--; break;
case 2:snake[0].x++; break;
case 3:snake[0].y--; break;
case 4:snake[0].y++; break;
default:break;
}

map[snake[0].x][snake[0].y]=3; //更新地图,将蛇的新位置赋值为3
}

void ishit()
{
if(snake[0].x==food_x&&snake[0].y==food_y)//判断蛇头位置是否与食物位置相重合
{
score++; //得分加1
//如果随机生成的食物位置与围墙或蛇体或墙体重合,则循环再次随机生成食物位置
while(map[food_x][food_y]!=0)
{
food_x=rand()%19+1; //随机在1-19的位置产生食物
food_y=rand()%39+1; //随机在1-39的位置产生食物
}
map[food_x][food_y]=4; //在地图上显示食物
}
//判断蛇头位置是否与墙的位置重合
if(snake[0].x==0||snake[0].x==19||snake[0].y==0||snake[0].y==39)
{
system("pause"); //暂停程序
exit(0); //退出程序
}
}

void main()
{
init();
while(1)
{
clear(); //调用自定义的清屏函数
move();
show();
ishit();
Sleep(200); //睡眠函数,使程序暂停0.1秒,防止运行太快
}
}

运行界面如下

不过此游戏界面简陋,给同学们看都拿不出手,下一步咱们要运用easyx库的相关图形函数,加入图片,美化一下界面

推荐阅读:

相关文章