C语言实现贪吃蛇代码
#include"stdafx.h"
#include
#include
#include
#include
#include
#define U 1
#define D 2
#define L 3
#define R 4 //蛇的状态 U:上 D:下 L:左 R:右
typedef struct snake //蛇身的一个节点
{
int x; //节点的x坐标
int y; //节点的y坐标
struct snake *next; //蛇身的下一个节点
}snake;
int score=0,add=10; //总得分和每吃一次食物的得分
int highscore=0; //最高分
int status,sleeptime=200; //蛇前进状态,每次运行的时间间隔
snake *head,*food; //蛇头指针,食物指针
snake *q; //遍历蛇时用的指针
int endgamestatus=0; //游戏结束时的状态
HANDLE hOut; //控制台句柄
void gotoxy(int x,int y);
int color(int c);
void printsnake();
void wlcome();
void createmap();
void scoreandtips();
void initsnake();
void createfood();
int biteself();
void cantcrosswall();
void speedup();
void speeddown();
void snakemove();
void keyboardcontrol();
void lostdraw();
void endgame();
void choose();
void file_out();
void file_in();
void explation();
main()
{
system("mode con cols=100 lines=30");
printsnake();
wlcome();
file_out();
keyboardcontrol();
endgame();
}
void gotoxy(int x,int y)//设置光标位置
{COORD c;
c.X=x;
c.Y=y;
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE),c); //定位光标的位置
}
int color(int c)//设置颜色
{
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),c);
return 0;
}
void printsnake()//打印字符蛇
{
gotoxy(2,5);
color(3);
printf("姓名:张小艾");
gotoxy(2,6);
color(3);
printf("学号:1910101099");
gotoxy(35,1);
color(6);
printf("/^/^");
gotoxy(34,2);
printf("|_| o|");
gotoxy(33,2);
color(2);
printf("_");
gotoxy(25,3);
color(12);
printf("/");
gotoxy(31,3);
color(2);
printf("/");
gotoxy(37,3);
color(6);
printf("_/");
gotoxy(41,3);
color(10);
printf(" ");
gotoxy(26,4);
color(12);
printf("____");
gotoxy(32,4);
printf("_________");
gotoxy(31,4);
color(2);
printf("|");
gotoxy(43,4);
color(10);
printf("");
gotoxy(32,5);
color(2);
printf("_______");
gotoxy(44,5);
color(10);
printf("");
gotoxy(39,6);
printf("| | ");
gotoxy(38,7);
printf("/ / ");
gotoxy(37,8);
printf("/ / ");
gotoxy(35,9);
printf("/ / ");
gotoxy(34,10);
printf(" / / ");
gotoxy(33,11);
printf("/ / _----_ ");
gotoxy(32,12);
printf("/ / _-~ ~-_ | |");
gotoxy(31,13);
printf("( ( _-~ _--_ ~-_ _/ |");
gotoxy(32,14);
printf(" ~-____-~ _-~ ~-_ ~-_-~ /");
gotoxy(33,15);
printf("~-_ _-~ ~-_ _-~");
gotoxy(35,16);
printf("~--____-~ ~-___-~");
}
void wlcome()//欢迎界面
{int n;
int i,j=1;
gotoxy(43,18);
color(11);
printf("贪吃蛇大作战");
color(14);
for(i=20;i<=26;i++)
{
for(j=27;j<=74;j++)
{
gotoxy(j,i);
if(i==20||i==26)
{
printf("-");
}
else if(j==27||j==74)
{
printf("|");
}
}
}
color(12);
gotoxy(35,22);
printf("1.开始游戏");
gotoxy(55,22);
printf("2.游戏说明");
gotoxy(35,24);
printf("3.退出游戏");
gotoxy(29,27);
color(3);
printf("请选择1 2 3
");
color(14);
scanf("%d",&n);
switch(n)
{
case 1:
system("cls");//清屏
createmap();
initsnake();
createfood();
keyboardcontrol();
break;
case 2:
explation();
break;
break;
case 3:
exit(0);
break;
}
}
void createmap()//创建地图
{
int i,j;
for(i=0;i<58;i+=2)
{
gotoxy(i,0);
color(5);
printf("□");
gotoxy(i,26);
printf("□");
}
for(i=0;i<26;i++)
{
gotoxy(0,i);
printf("□");
gotoxy(56,i);
printf("□");
}
for(i=2;i<56;i+=2)
{
for(j=1;j<26;j++)
{
gotoxy(i,j);
color(3);
printf("■
");
}
}
}
void scoreandtips()//游戏界面右侧的得分和小提示
{
file_out();
gotoxy(64,4);
color(11);
printf("*最高纪录*: %d",highscore);
gotoxy(64,8);
color(14);
printf("得分: %d ",score);
color(13);
gotoxy(73,11);
printf("小提示");
gotoxy(60,13);
color(6);
printf("+---------------------+");
gotoxy(60,25);
printf("+---------------------+");
color(3);
gotoxy(64,14);
printf("每个食物得分:%d分",add);
gotoxy(64,16);
printf("不能穿墙,不能咬到自己");
gotoxy(64,18);
printf("用↑↓←→分别控制蛇的移动");
gotoxy(64,20);
printf("F1为加速,F2为减速");
gotoxy(64,22);
printf("space: 暂停游戏");
gotoxy(64,24);
printf("ESC:退出游戏");
}
void file_out()//打开文件记录最高分
{
FILE *fp;
fp=fopen("save.txt","a+");
fscanf(fp,"%d",&highscore);
fclose(fp);
}
void initsnake()
{
snake *tail;
int i;
tail=(snake*)malloc(sizeof(snake));
tail->x=24;
tail->y=5;
tail->next=NULL;
for(i=1;i<=4;i++)
{
head=(snake*)malloc(sizeof(snake));
head->next=tail;
head->x=24+2*i;
head->y=5;
tail=head;
}
while(tail!=NULL)
{gotoxy(tail->x,tail->y);
color(14);
printf("★"); //蛇身由★组成
tail=tail->next;
}
}
void createfood()//随机出现食物
{
snake *food_1;
srand((unsigned)time(NULL));
food_1=(snake*)malloc(sizeof(snake));
while((food_1->x%2!=0))
{
food_1->x=rand()%52+2;
}
food_1->y=rand()%24+1;
q=head;
while(q->next==NULL)
{
if(q->x==food_1->x&&q->y==food_1->y)
{
free(food_1);
createfood();
}
q=q->next;
}
gotoxy(food_1->x,food_1->y);
food=food_1;
color(12);
printf("@");
}
int biteself()
{
snake *self; //定义self为蛇身上除蛇头以外的节点
self=head->next;
while(self!=NULL)
{
if(self->x==head->x&&self->y==head->y)
{
return 1;
}
self=self->next;
}
return 0;
}
void cantcrosswall()
{
if(head->x==0||head->x==56||head->y==0||head->y==26)
{
endgamestatus=1;
endgame();
}
}
void speedup()//加速
{
if(sleeptime>=50)
{
sleeptime=sleeptime-10;
add=add+2;
}
}
void speeddown()//减速
{
if(sleeptime<350)
{
sleeptime=sleeptime+30;
add=add-2;
if(sleeptime==350)
{
add=1;
}
}
}
void snakemove()//控制方向
{
snake *nexthead;
cantcrosswall();
nexthead=(snake*)malloc(sizeof(snake));
if(status==U)//上
{
nexthead->x=head->x; //向上前进时,x不变,y-1
nexthead->y=head->y-1;
nexthead->next=head;
head=nexthead;
q=head;
//如果下一个位置上有食物,下一个位置的坐标和食物坐标相同
if(nexthead->x==food->x&&nexthead->y==food->y)
{
while(q!=NULL)
{
gotoxy(q->x,q->y);
color(14);
printf("★");
q=q->next;
}
score=score+add;
speedup();
createfood();
}
else
{
while(q->next->next!=NULL)//如果没有遇见食物
{
gotoxy(q->x,q->y);
color(14);
printf("★");
q=q->next;
}
//经过上面的循环 ,q指向蛇尾,蛇尾的下一步就是蛇走过去的位置
gotoxy(q->next->x,q->next->y);
color(3);
printf("■");//恢复走过的位置
free(q->next);
q->next=NULL;
}
}
if(status==D)
{
nexthead->x=head->x; //向下前进时,x不变,y+1
nexthead->y=head->y+1;
nexthead->next=head;
head=nexthead;
q=head;
//如果下一个位置上有食物,下一个位置的坐标和食物坐标相同
if(nexthead->x==food->x&&nexthead->y==food->y)
{
while(q!=NULL)
{
gotoxy(q->x,q->y);
color(14);
printf("★");
q=q->next;
}
score=score+add;
speedup();
createfood();
}
else
{
while(q->next->next!=NULL)//如果没有遇见食物
{
gotoxy(q->x,q->y);
color(14);
printf("★");
q=q->next;
}
//经过上面的循环 ,q指向蛇尾,蛇尾的下一步就是蛇走过去的位置
gotoxy(q->next->x,q->next->y);
color(3);
printf("■");//恢复走过的位置
free(q->next);
q->next=NULL;
}
}
if(status==L)//左
{
nexthead->x=head->x-2; //向左前进时,x不变,y+1
nexthead->y=head->y;
nexthead->next=head;
head=nexthead;
q=head;
//如果下一个位置上有食物,下一个位置的坐标和食物坐标相同
if(nexthead->x==food->x&&nexthead->y==food->y)
{
while(q!=NULL)
{
gotoxy(q->x,q->y); //食物变成蛇身上的一部分
color(14);
printf("★");
q=q->next;
}
score=score+add;
speedup();
createfood();
}
else
{
while(q->next->next!=NULL)//如果没有遇见食物
{
gotoxy(q->x,q->y);
color(14);
printf("★");
q=q->next;
}
//经过上面的循环 ,q指向蛇尾,蛇尾的下一步就是蛇走过去的位置
gotoxy(q->next->x,q->next->y);
color(3);
printf("■");//恢复走过的位置
free(q->next);
q->next=NULL;
}
}
if(status==R)
{
nexthead->x=head->x+2; //向上前进时,x不变,y-1
nexthead->y=head->y;
nexthead->next=head;
head=nexthead;
q=head;
//如果下一个位置上有食物,下一个位置的坐标和食物坐标相同
if(nexthead->x==food->x&&nexthead->y==food->y)
{
while(q!=NULL)
{
gotoxy(q->x,q->y);
color(14);
printf("★");
q=q->next;
}
score=score+add;
speedup();
createfood();
}
else
{
while(q->next->next!=NULL)//如果没有遇见食物
{
gotoxy(q->x,q->y);
color(14);
printf("★");
q=q->next;
}
//经过上面的循环 ,q指向蛇尾,蛇尾的下一步就是蛇走过去的位置
gotoxy(q->next->x,q->next->y);
color(3);
printf("■");//恢复走过的位置
free(q->next);
q->next=NULL;
}
}
if(biteself()==1)
{
endgamestatus=2;
endgame();
}
}
void keyboardcontrol()
{
status=R;
while(1)
{
scoreandtips();
//GetAsyncKeyState函数用来判断函数调用指定虚拟键的状态
if(GetAsyncKeyState(VK_UP)&&status!=D)
{
status=U;
}
else if(GetAsyncKeyState(VK_DOWN)&&status!=U)
{
status=D;
}
else if(GetAsyncKeyState(VK_LEFT)&&status!=R)
{
status=L;
}
else if(GetAsyncKeyState(VK_RIGHT)&&status!=L)
{
status=R;
}
if(GetAsyncKeyState(VK_SPACE))
{
while(1)
{
//调用sleep函数,令进程停止,直到达到其中设定的参数时间
Sleep(300);
if(GetAsyncKeyState(VK_SPACE))
{
break;
}
}
}
else if(GetAsyncKeyState(VK_ESCAPE))
{
endgamestatus=3;
break;
}
else if(GetAsyncKeyState(VK_F1))
{
speedup();
}
else if(GetAsyncKeyState(VK_F2))
{
if(sleeptime<350)
{
sleeptime=sleeptime+30;
add=add-2;
if(sleeptime==350)
{
add=1;
}
}
}
Sleep(sleeptime);
snakemove();
}
}
void lostdraw()
{
system("cls");
int i,j;
gotoxy(17,5);
color(11);
printf("+------------------------");
gotoxy(35,5);
color(14);
printf("o00o");
gotoxy(39,5);
color(11);
printf("----------");
gotoxy(48,5);
color(14);
printf("---");
gotoxy(51,5);
color(11);
printf("----------");
gotoxy(61,5);
color(14);
printf("o00o");
gotoxy(65,5);
color(11);
printf("-----------------+");
for(i=6;i<=19;i++)
{
gotoxy(17,i);
printf("|");
gotoxy(82,i);
printf("|");
}
gotoxy(17,20);
printf("+----------------------------------");
gotoxy(52,20);
color(11);
printf("-----------------------------+");
}
void endgame()
{
system("cls");
if(endgamestatus==1)
{
lostdraw();
gotoxy(35,9);
color(12);
printf("对不起,您撞到墙了。游戏结束!");
}
else if(endgamestatus==2)
{
lostdraw();
gotoxy(35,9);
color(12);
printf("对不起,您咬到自己了。游戏结束!");
}
else if(endgamestatus==3)
{
lostdraw();
gotoxy(40,9);
color(12);
printf("您结束了游戏。");
}
gotoxy(43,12);
color(13);
printf("您的得分是 %d",score);
if(score>=highscore)
{
color(10);
gotoxy(33,16);
printf("创新纪录啦!你真棒!!!");
file_in();
}
choose();
}
void file_in()//将最高分存储到文件中
{
FILE *fp;
fp=fopen("save.txt","w+");//以读写的方式建立文件
fprintf(fp,"%d",score);
fclose(fp);
}
void choose()
{
int n;
gotoxy(25,23);
color(12);
printf("重玩一局-------1");
gotoxy(52,23);
printf("不玩了,退出-------2");
gotoxy(46,25);
color(11);
printf("选择:");
scanf("%d",&n);
switch(n)
{
case 1:
system("cls");
score=0;
sleeptime=200;
add=10;
printsnake();
wlcome();
break;
case 2:
exit(0);
break;
default:
gotoxy(35,27);
color(12);
printf("您输入有误,请重新输入");
system("pause >nul");//按任意键
endgame();
choose();
break;
}
}
void explation()
{
int i,j=1;
system("cls");
color(13);
gotoxy(44,3);
printf("游戏说明");
color(2);
for(i=6;i<=22;i++)
{
for(j=20;j<=75;j++)
{
gotoxy(j,i);
if(i==6||i==22)printf("=");
else if(j==20||j==75)printf("||");
}
}
color(3);
gotoxy(30,8);
printf("1、不能穿墙,不能咬到自己");
color(3);
gotoxy(30,8);
printf("1、不能穿墙,不能咬到自己");
color(10);
gotoxy(30,11);
printf("2、用↑↓←→分别控制蛇的移动");
color(14);
gotoxy(30,14);
printf("3、F1为加速,F2为减速");
color(11);
gotoxy(30,17);
printf("4、按空格键暂停游戏,再按空格键继续");
color(4);
gotoxy(30,20);
printf("5、ESC:退出游戏,space:暂停游戏");
getch();//按任意键返回主界面
system("cls");
printsnake();
wlcome();
}