话不多说,先看效果
实现的基本思路是把蛇用链表表示出来,每隔一段时间用头插法在这个链表中添加头,然后再把最结尾的给删掉并用空格把他给填充掉。这样不会发生像其他人的那种疯狂清空屏幕再打印导致的闪花眼的现象了。至于食物随机数就行了吧,下面开始:
首先
#include<stdio.h>
#include<windows.h>
#include<stdlib.h>
#include<time.h>
typedef struct sheshen
{
int x;
int y;
struct sheshen*next;
} snake;
snake *head=NULL,*p1=NULL,*pd=NULL,*wei=NULL;
int fenshu=0,fangxiang=4,lenth=5,sleeptime=80,suijix=0,suijiy=0,begin=0,zhuangtai=0,panduan=0;//panduan为0无操作为1死亡为2加分
char caidankongzhi=0,jiemiankongzhi=0,name1[50]= {0};
然后
这个函数的作用是把光标移动到相应的地方
void zuobiao(int x,int y)
{
COORD xy;
xy.X=x;
xy.Y=y;
HANDLE guangbiao;
guangbiao=GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleCursorPosition(guangbiao,xy);
}
下面的代码时用来把光标隐藏的
不然光标一直显示影响观感
void yincangguangbiao()
{
CONSOLE_CURSOR_INFO guangbiao;
guangbiao.bVisible = FALSE;
guangbiao.dwSize = sizeof(guangbiao);
HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleCursorInfo(handle, &guangbiao);
}
为了使代码更短,我在这里写了一些图形,之后可以随便调用不用再辛苦的写了
传的参数
第一个函数x,y为坐标z是宽度
第二个函数x,y为坐标,widtn为宽度height为高度
以后使用直接传参就行了
void sucai001(int x,int y,int z)
{
zuobiao(x,y);
for(int i=1; i<=z; i++)
printf("■");
zuobiao(x,y+2);
for(int i=1; i<=z; i++)
printf("■");
zuobiao(x,y+1);
printf("■");
zuobiao(x+2*z-2,y+1);
printf("■\n");
}
void sucai002(int x,int y,int width,int height)
{
for(int i=0; i<=height; i+=height)
{
for(int j=1; j<=width; j++)
{
zuobiao(x+j,y+i);
printf("*");
}
}
for(int i=0; i<=width; i+=width)
{
for(int j=1; j<=height; j++)
{
zuobiao(x+i,y+j);
printf("*");
}
}
}
为了让场景切换不是那么的突兀
我无聊的写了个过渡动画(这玩意叫动画?
void donghua001()
{
for(int k=1; k<=2; k++)
{
for(int i=0; i<=119; i++)
{
Sleep(0.8);
for(int j=0; j<=27; j++)
{
zuobiao(i,j);
if(k==1)
printf("0");
else
printf(" ");
}
}
}
}
然后是随机数
int suijishu(int x)
{
if(x==1)
{
srand((unsigned)time(NULL));
suijix=rand()%52+4;
if(suijix%2==1)
suijix+=1;
suijiy=rand()%19+4;
}
if(x==2)
{
suijix=rand()%52+4;
if(suijix%2==1)
suijix+=1;
suijiy=(rand())%19+4;
}
}
撞击判定
int hit(int x,int y)
{
if(head->x==x&&head->y==y)
{
return 1;
}
return 0;
}
两种死亡方式(撞到自己/撞墙)
void death1()
{
p1=head->next;
while(1)
{
panduan=hit(p1->x,p1->y);
if(panduan==1)
break;
if(p1->next==NULL)
break;
p1=p1->next;
}
}
int death2()
{
for(int i=0; i<=60; i+=2)
{
panduan=hit(i,3);
if(panduan==1)
return 1;
}
for(int i=0; i<=20; i++)
{
panduan=hit(60,3+i);
if(panduan==1)
return 1;
}
for(int i=60; i>=0; i-=2)
{
panduan=hit(i,23);
if(panduan==1)
return 1;
}
for(int i=20; i>=0; i--)
{
panduan=hit(0,3+i);
if(panduan==1)
return 1;
}
}
得分判定
int defen()
{
zuobiao(suijix,suijiy);
printf("■");
int i=0;
i=hit(suijix,suijiy);
if(i==1)
{
if(caidankongzhi=='2')//这里我有两个模式第二个模式得分后会加速
{
if(sleeptime>=100)
{
sleeptime-=50;
}
else if(sleeptime>=60)
{
sleeptime-=5;
}
}
fenshu+=1;
zuobiao(72,20);
printf("分数:%d",fenshu);
panduan=2;
suijishu(2);
return 2;
}
}
提示
void tishi()
{
sucai002(70,3,35,20);
zuobiao(72,4);
printf("操作提示:");
zuobiao(72,5);
printf("按上键向上转头");
zuobiao(72,6);
printf("按下键向下转头");
zuobiao(72,7);
printf("按左键向左转头");
zuobiao(72,8);
printf("按右键向右转头");
}
打印地图,别问我为什么要加sleep(),,为了好看,,就像老式游戏机一样
void map()
{
tishi();
for(int i=0; i<=60; i+=2)
{
if(begin==0)
Sleep(20);
zuobiao(i,3);
printf("■");
}
for(int i=0; i<=20; i++)
{
if(begin==0)
Sleep(20);
zuobiao(60,3+i);
printf("■");
}
for(int i=60; i>=0; i-=2)
{
if(begin==0)
Sleep(20);
zuobiao(i,23);
printf("■");
}
for(int i=20; i>=0; i--)
{
if(begin==0)
Sleep(20);
zuobiao(0,3+i);
printf("■");
}
begin=0;
}
蛇身
void snakebody()
{
wei=(snake*)malloc(sizeof(snake));
wei->x=16;
wei->y=13;
wei->next=NULL;
p1=wei;
for(int i=1; i<=lenth; i++)
{
head=(snake*)malloc(sizeof(snake));
head->x=wei->x+2*i;
head->y=wei->y;
head->next=p1;
p1=head;
}
p1=head;
while(1)
{
zuobiao(p1->x,p1->y);
printf("■");
if(p1->next==NULL)
break;
p1=p1->next;
}
}
控制
void kongzhi()
{
if(GetAsyncKeyState(VK_UP)&&fangxiang!=3)
{
fangxiang=1;
}
else if(GetAsyncKeyState(VK_DOWN)&&fangxiang!=1)
{
fangxiang=3;
}
else if(GetAsyncKeyState(VK_LEFT)&&fangxiang!=4)
{
fangxiang=2;
}
else if(GetAsyncKeyState(VK_RIGHT)&&fangxiang!=2)
{
fangxiang=4;
}
}
移动,算是代码的核心地方了,你别看他长,其实里面四部分几乎一摸一样,写的时候就ctrl+c,ctrl+v
void yidong()
{
if(fangxiang==1)//上
{
p1=head;
head=(snake*)malloc(sizeof(snake));
head->x=p1->x;
head->y=p1->y-1;
head->next=p1;
zuobiao(head->x,head->y);
printf("■");
p1=head;
if(panduan==2)
{
while(1)
{
if(p1->next==NULL)
{
zuobiao(p1->x,p1->y);
printf("■");
zuobiao(head->x,head->y-5);
break;
}
zuobiao(p1->x,p1->y);
printf("■");
pd=p1;
p1=p1->next;
}
}
else
{
while(1)
{
if(p1->next==NULL)
{
zuobiao(p1->x,p1->y);
printf(" ");
zuobiao(head->x,head->y-5);
free(p1);
pd->next=NULL;
break;
}
zuobiao(p1->x,p1->y);
printf("■");
pd=p1;
p1=p1->next;
}
}
}
if(fangxiang==2)//左
{
p1=head;
head=(snake*)malloc(sizeof(snake));
head->x=p1->x-2;
head->y=p1->y;
head->next=p1;
zuobiao(head->x,head->y);
printf("■");
p1=head;
if(panduan==2)
{
while(1)
{
if(p1->next==NULL)
{
zuobiao(p1->x,p1->y);
printf("■");
zuobiao(head->x,head->y-5);
break;
}
zuobiao(p1->x,p1->y);
printf("■");
pd=p1;
p1=p1->next;
}
}
else
{
while(1)
{
if(p1->next==NULL)
{
zuobiao(p1->x,p1->y);
printf(" ");
zuobiao(head->x,head->y-5);
free(p1);
pd->next=NULL;
break;
}
zuobiao(p1->x,p1->y);
printf("■");
pd=p1;
p1=p1->next;
}
}
}
if(fangxiang==3)//下
{
p1=head;
head=(snake*)malloc(sizeof(snake));
head->x=p1->x;
head->y=p1->y+1;
head->next=p1;
zuobiao(head->x,head->y);
printf("■");
p1=head;
if(panduan==2)
{
while(1)
{
if(p1->next==NULL)
{
zuobiao(p1->x,p1->y);
printf("■");
zuobiao(head->x,head->y-5);
break;
}
zuobiao(p1->x,p1->y);
printf("■");
pd=p1;
p1=p1->next;
}
}
else
{
while(1)
{
if(p1->next==NULL)
{
zuobiao(p1->x,p1->y);
printf(" ");
zuobiao(head->x,head->y-5);
free(p1);
pd->next=NULL;
break;
}
zuobiao(p1->x,p1->y);
printf("■");
pd=p1;
p1=p1->next;
}
}
}
if(fangxiang==4)//右
{
p1=head;
head=(snake*)malloc(sizeof(snake));
head->x=p1->x+2;
head->y=p1->y;
head->next=p1;
zuobiao(head->x,head->y);
printf("■");
p1=head;
if(panduan==2)
{
while(1)
{
if(p1->next==NULL)
{
zuobiao(p1->x,p1->y);
printf("■");
zuobiao(head->x,head->y-5);
break;
}
zuobiao(p1->x,p1->y);
printf("■");
pd=p1;
p1=p1->next;
}
}
else
{
while(1)
{
if(p1->next==NULL)
{
zuobiao(p1->x,p1->y);
printf(" ");
zuobiao(head->x,head->y-5);
free(p1);
pd->next=NULL;
break;
}
zuobiao(p1->x,p1->y);
printf("■");
pd=p1;
p1=p1->next;
}
}
}
death1();
if(panduan!=1)
{
death2();
if(panduan!=1)
{
defen();
}
}
}
到这里代码其实已经算是结束了,后面都是锦上添花的
//登录
int denglu()
{
int TorF=0,changdu;
char name[50]= {0},password[50]= {0},fenge[3],password1[50];
system("Cls");
sucai001(30,10,28);
zuobiao(32,11);
printf("请输入账号:");
scanf("%s",&name);
changdu=strlen(name);
name[changdu]='\n';
sucai001(30,14,28);
zuobiao(32,15);
printf("请输入密码:");
scanf("%s",&password);
changdu=strlen(password);
password[changdu]='\n';
FILE*denglu1=fopen("zhanghao.txt","r");
while(1)
{
TorF=0;
if(fgets(fenge,50,denglu1)==NULL)//判断是否结束
{
fclose(denglu1);
return 0;
}
fgets(name1,50,denglu1);
fgets(password1,50,denglu1);
if(strcmp(name1,name)==0)
{
TorF+=1;
}
if(strcmp(password1,password)==0)
{
TorF+=1;
}
if(TorF==2)
{
fclose(denglu1);
return 1;
}
}
}
有没有感觉很熟悉,,没错这是从我上个程序里cp出来的,略加修改
继续:
菜单以及界面
void caidan()
{
zuobiao(57,4);
printf("贪吃蛇");
sucai001(50,6,10);
zuobiao(52,7);
if(zhuangtai==0)
{
printf(" 0登入游戏");
}
else
{
printf(" 0登出游戏");
sucai001(40,0,20);
zuobiao(42,1);
printf(" 欢迎玩家%s",name1);
}
sucai001(50,10,10);
zuobiao(52,11);
printf(" 1经典模式");
sucai001(50,14,10);
zuobiao(52,15);
printf(" 2急速模式");
sucai001(54,18,6);
zuobiao(58,19);
printf("3关于");
sucai001(50,22,10);
zuobiao(53,23);
printf("我的选择:");
while(1)
{
scanf("%c",&caidankongzhi);
if(caidankongzhi>'4'||caidankongzhi<'0')
{
zuobiao(62,23);
printf(" ");
zuobiao(62,23);
}
else
{
break;
}
}
}
int jiemian001()
{
sucai001(44,10,14);
zuobiao(46,11);
printf(" 游戏结束,返回主菜单 ");
sucai001(44,13,14);
zuobiao(46,14);
printf(" ");
system("pause");
}
int jiemian002()
{
while(1)
{
zuobiao(52,7);
printf(" 请选择");
sucai001(50,10,10);
zuobiao(52,11);
printf(" 1登录");
sucai001(50,14,10);
zuobiao(52,15);
printf(" 2注册");
sucai001(50,22,10);
zuobiao(53,23);
fflush(stdin); //清除键盘缓冲区
printf("我的选择:");
scanf("%c",&jiemiankongzhi);
if(jiemiankongzhi<'3'||jiemiankongzhi>'0')
{
break;
}
zuobiao(62,21);
printf(" ");
zuobiao(62,21);
}
return 1;
}
int jiemian003(int x)
{
sucai001(44,10,14);
zuobiao(46,11);
if(x==1)
{
printf(" 成功 ");
}
else
{
printf(" 失败 ");
}
sucai001(44,13,14);
zuobiao(46,14);
printf(" ");
system("pause");
}
链表不要忘了释放内存
void end()
{
p1=head;
while(p1->next==NULL)
{
pd=p1->next;
free(p1);
p1=pd;
}
}
最后就是那一疙瘩的主函数
int main()
{
yincangguangbiao();
suijishu(1);
system("title 贪吃蛇");
while(1)
{
system("mode con cols=120 lines=30");
fenshu=0;
fangxiang=4;
fflush(stdin); //清除键盘缓冲区
caidankongzhi=' ';
donghua001();
system("Cls");
caidan();
donghua001();
switch(caidankongzhi)
{
case '0':
system("Cls");
if(zhuangtai==1)
{
jiemian003(1);
zhuangtai=0;
break;
}
jiemian002();
if(jiemiankongzhi=='1')
{
zhuangtai=denglu();
}
if(jiemiankongzhi=='2')
{
zhuangtai=zhuce();
}
system("Cls");
if(zhuangtai==0)
{
jiemian003(0);
}
else
{
jiemian003(1);
}
break;
case '1':
system("Cls");
snakebody();
map();
sleeptime=80;
fangxiang=4;
while(1)
{
kongzhi();
yidong();
if(panduan==1)
{
break;
}
Sleep(sleeptime);
}
jiemian001();
break;
case '2':
system("Cls");
sleeptime=200;
snakebody();
map();
zuobiao(72,9);
printf("急速模式速度会逐渐加快");
fangxiang=4;
while(1)
{
kongzhi();
yidong();
if(panduan==1)
{
break;
}
Sleep(sleeptime);
}
jiemian001();
break;
case '3':
zuobiao(34,13);
printf("重要提示:");
zuobiao(34,14);
printf("本作品csdn头顶有点冷完全独立完成");
zuobiao(34,15);
printf("未经本人允许严禁他人用作商业用途");
zuobiao(34,16);
system("pause");
system("Cls");
break;
}
if(caidankongzhi=='1'||caidankongzhi=='2')
end();
}
}
结束
码字不易,多多支持
我以后应该还会学习一些c++,汇编,php之类的一些内容,喜欢的话关注一下吧
------------------某二本院校的大一学生