实现了贪吃蛇游戏的基本功能,并实现每次得分的记录及排行。
效果如下图
主页
游戏页面
失败页面
排行榜
直接上代码
代码中有基本的注释
注:如果用.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;
}
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/37623.html