贪吃蛇由地图、蛇身、食物组成。它们的图形显示位置由下面这个函数表示:
void draw(char x, char y) \\显示坐标位置,其中左上角为坐标原点
{
COORD pos; \\写这个函数必须配windows.h头文件
HANDLE hOutput;
pos.X = x;
pos.Y = y;
hOutput = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleCursorPosition(hOutput, pos);
}
初始化地图大小为100×25,通过显示光标位置打印图案:
` void Init_map()
{
char i;
for(i=0;i<100;i++)
{
draw(i,0);
printf("#");
draw(i,25);
printf("#");
}
for(i=0;i<25;i++)
{
draw(0,i);
printf("#");
draw(100,i);
printf("#");
}
}
用单链表初始化蛇身,链表中每一个结点都存储了x,y坐标:
struct snack
{
char x;
char y;
struct snack*next;
}*head,*food,*pnew;
void Init_snack()
{
struct snack* ptail;
char i;
ptail=(struct snack*)malloc(sizeof(struct snack));
ptail->x=50; //初始化蛇头在50,25坐标处
ptail->y=15;
ptail->next=NULL;
for(i=1;i<=2;i++) //初始化蛇身长为3
{
head=(struct snack*)malloc(sizeof(struct snack));
head->next=ptail;
head->x=50+i; //初始化蛇为横向
head->y=15;
ptail=head;
}
while(ptail!=NULL) //遍历结点中的坐标,打印蛇身图案
{
draw(ptail->x,ptail->y);
printf("*");
ptail=ptail->next;
}
}
接下来是食物的随机出现,一要在地图内,二不能出现在蛇身的坐标上。刚开始写完后我发现食物的随机出现是有规律的,即每次打开食物出现的地方是固定,后来加了个时间种子才算达到了随机产生。
void rand_food()
{
if(food!=NULL)
{
return;
}
srand(time(0)); //设置时间种子
struct snack*food_tb=(struct snack*)malloc(sizeof(struct snack));
food_tb->x=rand()%99+1; //食物x坐标在1到99 y坐标在1到24
food_tb->y=rand()%24+1;
pnew=head;
while(pnew!=NULL)
{
if(food_tb->x==pnew->x&&food_tb->y==pnew->y) //判断食物是否出现在蛇身上
{
free(food_tb);
rand_food();
break;
}
pnew=pnew->next;
}
food=food_tb;
draw(food->x,food->y);
printf("!");
}
蛇的移动是通过键盘控制的,由一个kbhit()函数判断键盘是否有按下,如果按下则有getch()读取按下的值,这两个函数都包含在conio.h头文件里。然后在调用case语句,以读取到的值作为其字符常量,通常是w=上,a=左,d=右,s=下。
蛇的死亡条件有两个,一个是撞墙,另一个是自食(按着朝运动方向相反的键也算),写一个函数用if大法判断,如果符合就exit(0)。
蛇的运动速度调节用while(i–)实现,每吃到一个舒服i的值就减少。
下面是整个代码:
#include<stdio.h>
#include<time.h>
#include<windows.h>
#include<stdlib.h>
#include<conio.h>
char ch='d'; \\默认移动向右
static int count;
void draw(char x,char y);
struct snack
{
char x;
char y;
struct snack*next;
}*head,*food,*pnew;
void Init_snack()
{
struct snack* ptail;
char i;
ptail=(struct snack*)malloc(sizeof(struct snack));
ptail->x=50;
ptail->y=15;
ptail->next=NULL;
for(i=1;i<=2;i++) //ÉßÉí³¤¶ÈΪ3£»
{
head=(struct snack*)malloc(sizeof(struct snack));
head->next=ptail;
head->x=50+i;
head->y=15;
ptail=head;
}
while(ptail!=NULL)
{
draw(ptail->x,ptail->y);
printf("*");
ptail=ptail->next;
}
}
void Init_map()
{
char i;
for(i=0;i<100;i++)
{
draw(i,0);
printf("#");
draw(i,25);
printf("#");
}
for(i=0;i<25;i++)
{
draw(0,i);
printf("#");
draw(100,i);
printf("#");
}
}
void rand_food()
{
if(food!=NULL)
{
return;
}
srand(time(0));
struct snack*food_tb=(struct snack*)malloc(sizeof(struct snack));
food_tb->x=rand()%99+1;
food_tb->y=rand()%24+1;
pnew=head;
while(pnew!=NULL)
{
if(food_tb->x==pnew->x&&food_tb->y==pnew->y)
{
free(food_tb);
rand_food();
break;
}
pnew=pnew->next;
}
food=food_tb;
draw(food->x,food->y);
printf("!");
}
void draw(char x, char y)
{
COORD pos;
HANDLE hOutput;
pos.X = x;
pos.Y = y;
hOutput = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleCursorPosition(hOutput, pos);
}
void alive()
{
struct snack *self=head->next;
while(self!=NULL)
{
if(self->x==head->x&&self->y==head->y)
{
exit(0);
}
if(head->x==0||head->x==100||head->y==0||head->y==25)
exit(0);
self=self->next;
}
}
void snack_move()
{
if(kbhit())
ch=getch();
struct snack*nextnode=(struct snack*)malloc(sizeof(struct snack));
switch(ch)
{
case 'w':nextnode->x=head->x;
nextnode->y=head->y-1;
break;
case 's':nextnode->x=head->x;
nextnode->y=head->y+1;
break;
case 'a':nextnode->x=head->x-1;
nextnode->y=head->y;
break;
case 'd':nextnode->x=head->x+1;
nextnode->y=head->y;
break;
}
nextnode->next=head; //nextnode指向第一个结点
head=nextnode; //这里head已经增加了一节
pnew=head;
if(nextnode->x==food->x&&nextnode->y==food->y) //吃到食物就增加一个结点
{
while(pnew!=NULL)
{
draw(pnew->x,pnew->y);
printf("*");
pnew=pnew->next;
}
free(food);
food=NULL;
rand_food();
count++;
}
else //否则蛇继续移动
{
while(pnew->next->next!=NULL)
{
draw(pnew->x,pnew->y);
printf("*");
pnew=pnew->next;
}
draw(pnew->next->x,pnew->next->y);
printf(" ");
free(pnew->next);
pnew->next=NULL; //倒数第二个结点地址指向NULL
}
}
void main()
{
Init_map();
Init_snack();
while(1)
{
int i=50000000-count*5000000;
rand_food();
while(i--);
snack_move();
alive();
}
}