赞
踩
实现了贪吃蛇游戏的基本功能,并实现每次得分的记录及排行。
效果如下图
主页
游戏页面
失败页面
排行榜
直接上代码
代码中有基本的注释
注:如果用.c文件运行测试,会出现大量错误。应该用.cpp文件运行。
#include<windows.h> #include<stdio.h> #include<stdlib.h> #include<conio.h> #include<math.h> #include<time.h> typedef struct lei //蛇结点结构体 { int x; int y; struct lei *next; }lei; typedef struct record //记录 { int fraction; //分数 int hour; int min; int sec; int year; int mon; int day; }record; int score,scoreup=2,speed; //得分,单个食物分数,初始速度 int bool_=1; //用于判断是否自动加速 int nfood_1; //记录吃到的食物数,用于自动加速的判断 int nfood_2; //记录吃到的食物数,用于提示信息的显示条件 void Setpox(int x,int y); //设置光标 void Setcolor(unsigned short color); //设置文本颜色 void Homepage(); //主页显示 void Frame(); //边框 void Gamedescription(); //游戏说明 void Rankinglist(); //排行榜显示 void Gamemodule(); //方向控制及游戏运行 void Createmap(); //地图页面输出函数 void Outsnake(lei *p); //输出蛇 void Suspend(lei *q); //空格键暂停 void Inherit(lei *p); //蛇身传递 lei* Createfood(lei *q); //显示随机食物 void Speedhint(int _score); //速度信息提示 void Setspeed_reduce(); //减速 void Setspeed_plus(); //加速 int Collision(lei *q); //失败判定 void Endprompt(); //结束页面 void Destruction(lei *p); //释放蛇结点空间 int Cmpfunc(const void *a, const void *b);//排序方式 void Recordeddata(); //保存成绩 void Setpox(int x=0,int y=0) { COORD pox={x,y}; HANDLE hOut=GetStdHandle(STD_OUTPUT_HANDLE); SetConsoleCursorPosition(hOut,pox); } void Setcolor(unsigned short color) { HANDLE hCon = GetStdHandle(STD_OUTPUT_HANDLE); SetConsoleTextAttribute(hCon,color); } void Recordeddata() //保存成绩 { time_t timep; struct tm *ti; time(&timep); ti=localtime(&timep); //获取系统时间 record *gdata=(record*)malloc(sizeof(record)); gdata->year=ti->tm_year;//年 gdata->mon=ti->tm_mon; //月 gdata->day=ti->tm_mday; //日 gdata->hour=ti->tm_hour;//时 gdata->min=ti->tm_min; //分 gdata->sec=ti->tm_sec; //秒 gdata->fraction=score; FILE *fp=fopen("out.txt","ab"); if(fp==NULL) fp=fopen("out.txt","wb"); fwrite(gdata,sizeof(record),1,fp); fclose(fp); //删除文件指针 free(gdata); } int Cmpfunc(const void *a,const void *b) { return(*(int*)b-*(int*)a);//降序排序 } void Rankinglist() //排行榜显示 { system("cls"); int i=0; record gdata[1000]; FILE *fp=fopen("out.txt","rb"); if(fp==NULL) { Setpox(56,12); printf("暂无记录"); Setpox(); return; } rewind(fp); while(!feof(fp)) //feof检查文件是否结束,遇到结束符,返回非零 { fread(&gdata[i],sizeof(struct record),1,fp); i++; } qsort(gdata, i-1, sizeof(record), Cmpfunc);//按得分排序 Setpox(52,3); Setcolor(12); printf("排行榜"); Setpox(42,5); Setcolor(14); printf("得分\t\t\t时间\n"); Setcolor(15); for(int j=0;j<i-1;j++) //总共有i-1条记录信息 { Setpox(43,7+j*2); printf("%d\t\t",gdata[j].fraction); printf("%d/%02d/%02d ",gdata[j].year+1900,gdata[j].mon+1,gdata[j].day); printf("%02d:%02d:%02d\n",gdata[j].hour,gdata[j].min,gdata[j].sec ); } fclose(fp); //删除文件指针 Setpox(); } void Gamedescription() //游戏说明 { system("cls"); Setpox(55,4); printf("游戏说明"); Setcolor(12); Setpox(34,8); printf("1.由“A”“W”“D”“S”分别控制左、上、右、下的方向"); Setpox(34,10); printf("2.由空格键控制暂停游戏和继续游戏"); Setpox(34,12); printf("3.当蛇首撞墙或咬到蛇身时游戏结束"); Setpox(34,14); printf("4.按Q键可加速,按E键可减速"); Setpox(34,16); printf("5.速度自动增加到一定程度或按减速键后,将不再继续加速"); Setpox(34,18); printf("6.小蛇每吃到一个食物,分数就会增加。初始分数为零"); Setpox(34,20); printf("7.小蛇的初始长度为6,每吃到一个食物长度就会加一"); Setpox(34,22); printf("8.小蛇的初始速度为300MS/格,速度会自动根据得分情况增加"); Setpox(34,24); printf("9.以上按键皆不区分大小写"); } void Setspeed_plus() //加速可以用参数 { if(speed>100) speed-=100; else speed/=2; scoreup*=2; //每个食物的分数翻倍 nfood_1=0; nfood_2=0; } void Setspeed_reduce()//减速 { if(speed>=100) speed+=100; else speed*=2; scoreup/=2; //每个食物的分数减半 bool_=0; } void Speedhint() //速度提示 { Setcolor(11); if(nfood_2<2) //该速度阶段前两个食物才显示内容 { switch(speed) { case 300: Setpox(86,15); printf("朋友,别嫌慢"); Setpox(86,17); printf("这才刚刚开始"); break; case 200: Setpox(86,15); printf("嗨,朋友,现在快一点了"); Setpox(86,17); printf("是原来的1.5倍"); break; case 100: Setpox(83,15); printf("我明白你已经厌倦了这龟速"); Setpox(83,17); printf("所以我把速度变成刚才的两倍了"); break; case 50: Setpox(86,15); printf("自动加速到此为止了"); Setpox(86,17); printf("这是真正的挑战"); break; } } else { if(nfood_2%12==0)//不自动加速(减速或自动加速结束)时做出提示 { Setpox(86,15); printf("如果你想更快!"); Setpox(86,17); printf("可以按Q键!!!"); } else { Setpox(83,15); printf(" "); Setpox(83,17); printf(" "); } } } void Frame(int n) //画边框 { int i; Setpox(17,5); Setcolor(11); printf("⊙--------------------------"); Setcolor(14); printf("oOOo"); Setcolor(11); printf("----------"); Setcolor(14); printf("(_)"); Setcolor(11); printf("----------"); Setcolor(14); printf("oOOo"); Setcolor(11); printf("--------------------------⊙"); for(i = 6;i<=19;i++) //竖边框 { Setpox(17,i); printf("§"); Setpox(102,i); printf("§"); } Setpox(17,20); printf("⊙---------------------------------------"); Setcolor(14); printf("☆☆☆"); Setcolor(11); printf("--------------------------------------⊙"); Setpox(53,23);//56 24 printf("∵ˇˇˇˇˇˇˇ∵"); Setpox(53,26); printf("∴^^^^^^^∴"); if(n==0) //主页面的字符图案 { Setpox(57,2); Setcolor(6); printf("\\\\\\|///"); Setpox(54,3); printf("\\\\"); Setpox(58,3); Setcolor(15); printf(".-.-"); Setpox(65,3); Setcolor(6); printf("//"); Setpox(55,4); Setcolor(14); printf("("); Setpox(58,4); Setcolor(15); printf(".@.@"); Setpox(65,4); Setcolor(14); printf(")");// } else //游戏结束页面的字符图案 { Setpox(57,1); Setcolor(6); printf("∧ ∧"); Setpox(55,2); printf(" / \\ / \\"); Setpox(54,3); printf("( ︹ ˇ ︹ )"); Setpox(54,4); printf("く "); Setcolor(15); printf("⊙ ⊙"); Setcolor(14); printf(" / "); Setpox(55,5); printf("く い /"); Setpox(57,6); printf("く 々 √"); Setpox(60,7); printf("ˇ"); } } void Createmap() //地图页面输出函数 { int i; Setcolor(11); for(i=2;i<27;i++) { Setpox(2,i); printf("◆"); Setcolor(3); for(int j=0;j<29;j++) printf("■"); Setcolor(11); printf("◆"); } Setpox(2,1); for(i=0;i<31;i++)//上边框 { printf("◆"); } Setpox(2,27); for(i=0;i<31;i++)//下边框 { printf("◆"); } Setpox(80,3); printf("方向键:"); Setpox(88,4); printf("左 <———> A"); Setpox(88,5); printf("上 <———> W"); Setpox(88,6); printf("右 <———> D"); Setpox(88,7); printf("下 <———> S"); Setpox(80,9); printf("暂停键: 空格"); Setpox(80,12); printf("得分"); Setpox(80,22); printf("按Q键可加速,按E键可减速"); Setcolor(10); for(i=0;i<30;i++) { Setpox(70,i); printf("§"); } Setpox(82,14); printf("∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞"); Setpox(82,19); printf("∞∞∞∞∞∞∞∞∞∞∞∞∞∞∞"); for(i=15;i<19;i++) { Setpox(81,i); printf("φ"); Setpox(111,i); printf("φ"); } } lei* Createfood(lei *q) //显示随机食物 { lei *p,*k; k=(lei*)malloc(sizeof(lei)); k->next=NULL; zhe: p=q->next; srand((unsigned)time(NULL)); // srand(rand()+(unsigned int)time(NULL)); while((k->x=rand()%57+4)%2!=0) //确保食物显示在格子内 {;} k->y=rand()%24+3; while(p!=NULL) { if((k->x==p->x&&k->y==p->y))//如果新食物与蛇身重合,则重新生成 goto zhe; p=p->next; } Setcolor(12); Setpox(k->x,k->y); printf("●"); return k; } void Inherit(lei *p) //蛇身传递 { lei *r=p->next; //p为第一个结点,即蛇首 if(r->next!=NULL) Inherit(r); r->x=p->x; //把前一个结点的坐标传递给后一个结点 跟随 r->y=p->y; } void Outsnake(lei *p) //输出蛇 { lei *r,*k=p->next; Setcolor(14); while(p->next!=NULL) { r=p->next; p=r; Setpox(r->x,r->y); printf("★"); } if(k->x!=p->x||k->y!=p->y) { Setpox(p->x,p->y); //覆盖尾迹 Setcolor(3); printf("■"); } Setpox(); Sleep(speed); } void Suspend(lei *q) //空格键暂停 { Setpox(); while(1) { if(kbhit()&&getch()==' ')//kbhit函数,非阻塞地响应键盘输入事件 return; } } int Collision(lei *q) //失败判定 { lei *p=q->next,*r=p->next; if(p->x==2||p->x==62||p->y==1||p->y==27)//撞墙 return 1; while(r->next!=NULL) { if(p->x==r->x&&p->y==r->y) //咬到自己 return 1; r=r->next; } return 0; } void Destruction(lei *p) //结束后释放蛇结点空间 { lei *q=p,*r; while(q->next!=NULL) { r=q; q=q->next; free(r); } free(q); } void Gamemodule() //方向控制及游戏运行 { lei *q,*r,*h; char str='d',str1='d'; q=(lei*)malloc(sizeof(lei)); q->next=NULL; score=0; //设置初始分数 nfood_1=0; nfood_2=0; speed=300; //设置初始速度 system("cls"); for(int i=6;i<19;i=i+2) //q为头结点 初始化蛇,分配6个结点 { r=(lei *)malloc(sizeof(lei)); r->x=i; r->y=5; r->next=q->next; q->next=r; } Createmap(); //输出地图 h=Createfood(q); while(1) { if(Collision(q)) //撞墙或咬到自己 { Recordeddata(); //保存分数到本地文件夹 Destruction(q); //销毁蛇身结点,释放存储空间 Endprompt(); //结束时的选择 break; } Setpox(86,12); Setcolor(13); printf("%d",score); //分数的输出 Outsnake(q); //输出蛇 Setpox(); Speedhint(); //速度的提示 if(kbhit()) //按键了 { str=getch(); if(str==' ') //如果是空格 { Suspend(q); //暂停函数 str=str1; //str1 记录暂停之前的方向 } } if(str<91) //兼容大写 str+=32; if((str=='d'&&str1=='a')||(str=='s'&&str1=='w')||(str=='a'&&str1=='d')||(str=='w'&&str1=='s')) str=str1; if(str!='a'&&str!='d'&&str!='w'&&str!='s') { if(str=='q') //按q加速 { Setspeed_plus(); //bool_=1; 可恢复自动加速 } if(str=='e') //按e减速 { Setspeed_reduce(); bool_=0; //按减速之后就不再自动加速 } str=str1; } if(str=='d'&&str1!='a') //右 { str1=str; if(q->next->x+2==h->x&&q->next->y==h->y) { h->next=q->next; //吃到食物 q->next=h; h=Createfood(q); //生成新的食物 score+=scoreup; //分数增加 nfood_2++; //记录吃到的食物数,用于提示信息的显示条件 nfood_1++; //记录吃到的食物数,用于自动加速的判断 if(((nfood_1==5&&speed>100)||(nfood_1==10&&speed==100))&&bool_)//前两次吃5个自动加速,第三次吃10个自动加速 { // bool_ 减速之后不在进行加速 Setspeed_plus(); } } else { Inherit(q->next); q->next->x+=2; } } else { if(str=='s'&&str1!='w') //下 { str1=str; if(q->next->x==h->x&&q->next->y+1==h->y) { h->next=q->next; q->next=h; h=Createfood(q); score+=scoreup; nfood_2++; nfood_1++; if(((nfood_1==5&&speed>100)||(nfood_1==10&&speed==100))&&bool_) { Setspeed_plus(); } } else { Inherit(q->next); q->next->y+=1; } } else { if(str=='a'&&str1!='d') //左 { str1=str; if(q->next->x-2==h->x&&q->next->y==h->y) { h->next=q->next; q->next=h; h=Createfood(q); score+=scoreup; nfood_2++; nfood_1++; if(((nfood_1==5&&speed>100)||(nfood_1==10&&speed==100))&&bool_) { Setspeed_plus(); } } else { Inherit(q->next); q->next->x-=2; } } else { if(str=='w'&&str1!='s')//上 { str1=str; if(q->next->x==h->x&&q->next->y-1==h->y)//吃到食物,插入新节点,创建新食物 { h->next=q->next; q->next=h; h=Createfood(q); score+=scoreup; nfood_2++; nfood_1++; if(((nfood_1==5&&speed>100)||(nfood_1==10&&speed==100))&&bool_) { Setspeed_plus(); } } else //没吃到,蛇身结点传递 { Inherit(q->next); q->next->y-=1; } } } } } } } void Endprompt() //结束页面 { int n; zhe: system("cls"); Setcolor(12); Setpox(54,8); printf("游戏结束了朋友\n"); Setpox(54,10); Setcolor(14); printf("你的得分是:%d",score); Setpox(53,12); Setcolor(12); printf("接下来你有三个选择"); Setcolor(14); Setpox(22,16); printf("1.你是想重新开始"); Setpox(44,16); printf("2.还是想去主页看看"); Setpox(68,16); printf("3.难道你想退出游戏? 不!你不想!!!"); Frame(1); Setpox(56,24); printf("前往:"); scanf("%d",&n); switch(n) { case 1: system("cls"); Gamemodule(); break; case 2:return; case 3: system("cls"); Setpox(56,10); printf("再见喽"); Setpox(); exit(0); default: printf("你输入错了,再给你次机会,朋友\n"); printf("按任意键继续"); getch(); goto zhe; } } int main() { int number; zhe: system("cls"); Setpox(53,8); Setcolor(14); printf("贪 吃 蛇 大 作 战"); Setpox(26,14); printf("1.开始游戏"); Setpox(46,14); printf("2.游戏说明"); Setpox(66,14); printf("3.得分排行"); Setpox(86,14); printf("4.退出游戏"); Frame(0); Setpox(56,24); Setcolor(14); printf("前往:"); scanf("%d",&number); switch(number) { case 1: Gamemodule(); goto zhe; case 2: Gamedescription(); Setpox(); getch(); goto zhe; case 3: Rankinglist(); getch(); goto zhe; case 4: system("cls"); Setpox(56,10); printf("再见喽"); Setpox(); exit(0); default: printf("朋友,请输入上面有的数字!\n"); printf("任意键继续"); getch(); goto zhe; } return 0; }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。