控制键:↑↓←→

//里面定义了五种类型、一些宏和通用工具函数。类型例如size_t、wchar_t、div_t、ldiv_t和lldiv_t;宏例如EXIT_FAILURE、EXIT_SUCCESS、RAND_MAX和MB_CUR_MAX等等;
//常用的函数如malloc()、calloc()、realloc()、free()、system()、atoi()、atol()、rand()、srand()、exit()等等。
//具体的内容你自己可以打开编译器的include目录里面的头文件看看。
ifndef__cplusplus
//一般用于将C++代码以标准C形式输出(即以C的形式被调用),这是因为C++虽然常被认为是C的超集,但是C++的编译器还是与C的编译器不同的。C中调用C++中的代码这样定义会是安全的。
typedefcharbool;
//使用typedef声明的名称将占用与其他标识符相同的命名空间(不包括语句标签)。因此,它们不能使用与前一个声明的名称相同的标识符(除了在类类型声明中.
definetrue1
//正确为1
if
//即可以设置不同的条件,在编译时编译不同的代码,预编译指令中的表达式与C语言本身的表达式基本一至如逻辑运算、算术运算、位运算等均可以在预编译指令中使用。
//之所以能够实现条件编译是因为预编译指令是在编译之前进行处理的,通过预编译进行宏替换、条件选择代码段,然后生成最后的待编译代码,最后进行编译。
//将光标移动到控制台的(x,y)坐标点处
voidgotoxy(intx,inty)
{
COORDcoord;
=x;
=y;
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE),coord);
}
defineMAPWIDTH78//宽度
#defineMAPHEIGHT24//高度
//食物的坐标
struct{
intx;
inty;
}food;
//蛇的相关属性
struct{
intspeed;//蛇移动的速度
intlen;//蛇的长度
intx[SNAKESIZE];//组成蛇身的每一个小方块中x的坐标
inty[SNAKESIZE];//组成蛇身的每一个小方块中y的坐标
}snake;
//绘制游戏边框
voiddrawMap();
//随机生成食物
voidcreateFood();
//按键操作
voidkeyDown();
//蛇的状态
boolsnakeStatus();
//从控制台移动光标
voidgotoxy(intx,inty);
intkey=72;//表示蛇移动的方向,72为按下“↑”所代表的数字
//用来判断蛇是否吃掉了食物,这一步很重要,涉及到是否会有蛇身移动的效果以及蛇身增长的效果
intchangeFlag=0;
intsorce=0;//记录玩家的得分
inti;
voiddrawMap()
{
//打印上下边框
for(i=0;i=MAPWIDTH;i+=2)//i+=2是因为横向占用的是两个位置
{
//将光标移动依次到(i,0)处打印上边框
gotoxy(i,0);
printf("■");
//将光标移动依次到(i,MAPHEIGHT)处打印下边框
gotoxy(i,MAPHEIGHT);
printf("■");
}
//打印左右边框
for(i=1;iMAPHEIGHT;i++)
{
//将光标移动依次到(0,i)处打印左边框
gotoxy(0,i);
printf("■");
//将光标移动依次到(MAPWIDTH,i)处打印左边框
gotoxy(MAPWIDTH,i);
printf("■");
}
//随机生成初试食物
while(1)
{
srand((unsignedint)time(NULL));
=rand()%(MAPWIDTH-4)+2;
=rand()%(MAPHEIGHT-2)+1;
//生成的食物横坐标的奇偶必须和初试时蛇头所在坐标的奇偶一致,因为一个字符占两个字节位置,若不一致
//会导致吃食物的时候只吃到一半
if(%2==0)
break;
}
//将光标移到食物的坐标处打印食物
gotoxy(,);
printf("*");
//初始化蛇的属性
=3;
=200;
//在屏幕中间生成蛇头
[0]=MAPWIDTH/2+1;//x坐标为偶数
[0]=MAPHEIGHT/2;
//打印蛇头
gotoxy([0],[0]);
printf("■");
//生成初试的蛇身
for(i=1;;i++)
{
//蛇身的打印,纵坐标不变,横坐标为上一节蛇身的坐标值+2
[i]=[i-1]+2;
[i]=[i-1];
gotoxy([i],[i]);
printf("■");
}
//打印完蛇身后将光标移到屏幕最上方,避免光标在蛇身处一直闪烁
gotoxy(MAPWIDTH-2,0);
return;
}
voidkeyDown()
{
intpre_key=key;//记录前一个按键的方向
if(_kbhit())//如果用户按下了键盘中的某个键
{
fflush(stdin);//清空缓冲区的字符
//getch()读取方向键的时候,会返回两次,第一次调用返回0或者224,第二次调用返回的才是实际值
key=_getch();//第一次调用返回的不是实际值
key=_getch();//第二次调用返回实际值
}
/*
*蛇移动时候先擦去蛇尾的一节
*changeFlag为0表明此时没有吃到食物,因此每走一步就要擦除掉蛇尾,以此营造一个移动的效果
*为1表明吃到了食物,就不需要擦除蛇尾,以此营造一个蛇身增长的效果
*/
if(changeFlag==0)
{
gotoxy([],[]);
printf("");//在蛇尾处输出空格即擦去蛇尾
}
//将蛇的每一节依次向前移动一节(蛇头除外)
for(i=;i0;i--)
{
[i]=[i-1];
[i]=[i-1];
}
//蛇当前移动的方向不能和前一次的方向相反,比如蛇往左走的时候不能直接按右键往右走
//如果当前移动方向和前一次方向相反的话,把当前移动的方向改为前一次的方向
if(pre_key==72key==80)
key=72;
if(pre_key==80key==72)
key=80;
if(pre_key==75key==77)
key=75;
if(pre_key==77key==75)
key=77;
/**
*控制台按键所代表的数字
*“↑”:72
*“↓”:80
*“←”:75
*“→”:77
*/
//判断蛇头应该往哪个方向移动
switch(key)
{
case75:
[0]-=2;//往左
break;
case77:
[0]+=2;//往右
break;
case72:
[0]--;//往上
break;
case80:
[0]++;//往下
break;
}
//打印出蛇头
gotoxy([0],[0]);
printf("■");
gotoxy(MAPWIDTH-2,0);
//由于目前没有吃到食物,changFlag值为0
changeFlag=0;
return;
}
voidcreateFood()
{
if([0]==[0]==)//蛇头碰到食物
{
//蛇头碰到食物即为要吃掉这个食物了,因此需要再次生成一个食物
while(1)
{
intflag=1;
srand((unsignedint)time(NULL));
=rand()%(MAPWIDTH-4)+2;
=rand()%(MAPHEIGHT-2)+1;
//随机生成的食物不能在蛇的身体上
for(i=0;;i++)
{
if([i]==[i]==)
{
flag=0;
break;
}
}
//随机生成的食物不能横坐标为奇数,也不能在蛇身,否则重新生成
if(%2==0)
break;
}
//绘制食物
gotoxy(,);
printf("*");
++;//吃到食物,蛇身长度加1
sorce+=10;//每个食物得10分
=5;//随着吃的食物越来越多,速度会越来越快
changeFlag=1;//很重要,因为吃到了食物,就不用再擦除蛇尾的那一节,以此来造成蛇身体增长的效果
}
return;
}
boolsnakeStatus()
{
//蛇头碰到上下边界,游戏结束
if([0]==0||[0]==MAPHEIGHT)
returnfalse;
//蛇头碰到左右边界,游戏结束
if([0]==0||[0]==MAPWIDTH)
returnfalse;
//蛇头碰到蛇身,游戏结束
for(i=1;;i++)
{
if([i]==[0][i]==[0])
returnfalse;
}
returntrue;
}
intmain()
{
drawMap();
while(1)
{
keyDown();
if(!snakeStatus())
break;
createFood();
Sleep();
}
gotoxy(MAPWIDTH/2,MAPHEIGHT/2);
printf("GameOver!\n");
gotoxy(MAPWIDTH/2,MAPHEIGHT/2+1);
printf("本次游戏得分为:%d\n",sorce);
Sleep(500);
return0;
}