链接: https://pan.baidu.com/s/1PIQjvM_tvDAJBWVlWSAtUQ
提取码: hmi4
|
|
#include
#include
#include
#include
#include
#define INC(x) ((x)%30+1)
#define DEC(x) (((x)+28)%30+1)
COORD snake[901],egg[22];
int slong=1,dir=3,eggnum=0,eggscore=90,speed=100;
int scoremax=0,score=0,voice=1,eggmax=1,hard=2,cheatopen=0,mode=0;
int speednum[5]={200,100,50,25,10};
char hd[5][10]={"Easy","Normal","Hard","Crazy","丧心病狂"};
void gotoxy(int x, int y); //移动光标
void color(int b); //设置颜色
void drawboard(); //绘制背景
void drawsnake(); //绘制蛇
void start(); //游戏流程控制
void options(); //游戏设置
void move(int d); //蛇的移动
int eat(); //吃蛋
int die(); //死亡判定
void drawegg(); //绘制蛋
void getegg(); //生成新蛋
void Pautoplay(); //自动操作模式1:扫荡
void autoplay(); //自动操作模式2:搜索
void (*cheatF)(); //自动模式设置指针
int main()
{
system("mode 64,34");
system("color 0f");
system("title 贪吃蛇 By Eyizoha");
HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
CONSOLE_CURSOR_INFO cci;
GetConsoleCursorInfo(hOut,&cci);
cci.bVisible=false;
SetConsoleCursorInfo(hOut,&cci);
srand(time(NULL));cheatF=autoplay;
char ch;
while(ch!=0x1B)
{
system("cls");drawboard();color(15);
gotoxy(15,4);printf("贪吃蛇");
gotoxy(14,5);printf("By Eyizoha");
gotoxy(14,6);printf("最高分:%d",scoremax);
gotoxy(13,7);printf("按空格开始游戏");
gotoxy(12,8);printf("按A查看说明和设置");
gotoxy(13,9);printf("按ESC退出游戏");
while (ch!=0x1B)
{
ch=getch();
if(ch==' '){start();break;}
if(ch=='a'||ch=='A'){options();break;}
}
}
}
void gotoxy(int x,int y)
{
COORD pos;
pos.X=2*x;
pos.Y=y;
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE),pos);
}
void color(int b)
{
HANDLE hConsole=GetStdHandle((STD_OUTPUT_HANDLE));
SetConsoleTextAttribute(hConsole,b) ;
}
void options()
{
char ch;
system("cls");drawboard();color(15);
gotoxy(12,4);printf("游戏说明:游戏中");
gotoxy(13,5);printf("按空格暂停,");
gotoxy(12,6);printf("按WASD控制蛇方向,");
gotoxy(13,7);printf("按ESC结束游戏,");
gotoxy(10,8);printf("蛇头触碰到蛇身则游戏失败。");
gotoxy(10,11);printf("Easy(一个蛋价值50分)");
gotoxy(10,12);printf("Normal(一个蛋价值90分)");
gotoxy(10,13);printf("Hard(一个蛋价值130分)");
gotoxy(10,14);printf("Crazy(一个蛋价值170分)");
gotoxy(10,15);printf("难度越高蛇速度越快。");
gotoxy(10,19);printf("每个多一个蛋使每个蛋价值减2分");
gotoxy(11,26);printf(".按空格返回上层菜单.");
while(ch!=' ')
{
gotoxy(10,10);printf("\t\t\t\t\t");
gotoxy(10,10);printf("设置游戏难度(W和S),当前为%s!",hd[hard-1]);
gotoxy(10,16);printf("当前蛇速度%d步/秒",1000/speed);
gotoxy(10,18);printf("设置蛋的数量(A减D加),当前为%d个",eggmax);
gotoxy(10,20);printf("当前一个蛋价值%d分",eggscore);
if(voice){gotoxy(14,22);printf(".音效:开.\a");}
else {gotoxy(14,22);printf(".音效:关.");}
if(cheatopen==0){
gotoxy(14,23);printf(".作弊:关.");
gotoxy(10,24);printf("\t\t\t\t");}
else {
gotoxy(14,23);printf(".作弊:开.");
gotoxy(10,24);
if(mode)printf(".扫荡模式:慢,稳定,不灵活.");
else printf(".搜索模式:快,灵活,不稳定.");}
ch=getch();
switch(ch)
{
case 'w':case 'W':hard=hard%4+1;break;
case 's':case 'S':hard=(hard+2)%4+1;break;
case 'a':case 'A':if(eggmax>1)eggmax-=1;break;
case 'd':case 'D':if(eggmax<21)eggmax+=1;break;
case 'e':case 'E':hard=5;break;
case 'q':case 'Q':voice=(voice+1)%2;break;
case '!':cheatopen=(cheatopen+1)%2;break;
case ' ':mode=(mode+1)%2;
if(mode)cheatF=Pautoplay;
else cheatF=autoplay;
break;
}
speed=speednum[hard-1];
if(hard==5) eggscore=240-2*eggmax+2;
else eggscore=10+40*hard-2*eggmax+2;
}
}
void start()
{
//蛇的初始位置设置
snake[0].X=16;snake[0].Y=16;
snake[1].X=15;snake[1].Y=16;
snake[2].X=14;snake[2].Y=16;
snake[3].X=13;snake[3].Y=16;
slong=3;score=0;dir=3;eggnum=0;
char ch;int cheat=1;
drawboard();getegg();
color(15);
gotoxy(0,32);printf("SCORE:%d",score);
gotoxy(8,32);printf(" LENGTH:%d",slong);
while (ch!=0x1B)
{
drawsnake();drawegg();
Sleep(speed);//此处调整游戏速度
if (kbhit())//键盘响应
{
ch=getch();
switch(ch)
{
case 'O':if(cheatopen)
{
cheat=(cheat+1)%3;
color(15);gotoxy(0,33);printf("AUTO MODE!");
if(dir!=2&&snake[0].Y!=1&&snake[0].Y!=30)dir=0;
}break;
case 'w':case 'W':
if(cheat==2||dir==0||dir==2)break;dir=0;break;
case 'a':case 'A':
if(cheat==2||dir==1||dir==3)break;dir=1;break;
case 's':case 'S':
if(cheat==2||dir==0||dir==2)break;dir=2;break;
case 'd':case 'D':
if(cheat==2||dir==1||dir==3)break;dir=3;break;
case ' ':{
ch='a';
gotoxy(0,33);color(15);printf("\t\t\r暂停!");
while(ch!=0x1B&&ch!=' ')if(kbhit())ch=getch();
gotoxy(0,33);printf("\t\t");
if(cheat==2){gotoxy(0,33);printf("AUTO MODE!");}
}
}
}
if(cheat==2)cheatF();
else if(cheat==0){gotoxy(0,33);printf(" ");cheat=1;}
move(dir);
if(die())break;
if(eat())score+=eggscore;
getegg();
color(15);
gotoxy(3,32);printf("%d",score);
gotoxy(12,32);printf("%d",slong);
}
gotoxy(0,33);
color(15);
printf("Game Over!");
if(score>scoremax)
{
printf("New High Score!");
scoremax=score;
}
printf("Press ESC to return!");
while (getch()!=0x1B);
}
void drawsnake()
{
for(int i=slong;i>=0;i--)
{ color(14);gotoxy(snake[i].X,snake[i].Y);
if(i==0){color(12);printf("◆");}
else if(i==slong)printf(" ");
else
{
if(snake[i-1].Y==snake[i].Y&&snake[i].Y==snake[i+1].Y)printf("━");
else if(snake[i-1].X==snake[i].X&&snake[i].X==snake[i+1].X)printf("┃");
else if(snake[i-1].X==DEC(snake[i].X)&&INC(snake[i].Y)==snake[i+1].Y)printf("┓");
else if(snake[i+1].X==DEC(snake[i].X)&&INC(snake[i].Y)==snake[i-1].Y)printf("┓");
else if(snake[i-1].X==INC(snake[i].X)&&INC(snake[i].Y)==snake[i+1].Y)printf("┏");
else if(snake[i+1].X==INC(snake[i].X)&&INC(snake[i].Y)==snake[i-1].Y)printf("┏");
else if(snake[i-1].X==DEC(snake[i].X)&&DEC(snake[i].Y)==snake[i+1].Y)printf("┛");
else if(snake[i+1].X==DEC(snake[i].X)&&DEC(snake[i].Y)==snake[i-1].Y)printf("┛");
else if(snake[i-1].X==INC(snake[i].X)&&DEC(snake[i].Y)==snake[i+1].Y)printf("┗");
else if(snake[i+1].X==INC(snake[i].X)&&DEC(snake[i].Y)==snake[i-1].Y)printf("┗");
}
if(i==slong)i=2;
}
}
void move(int d)
{
if(d==-1)return;
for(int i=slong+1;i>0;i--)
{
snake[i].X=snake[i-1].X;
snake[i].Y=snake[i-1].Y;
}
switch(d)
{
case 0:snake[0].Y=DEC(snake[0].Y);break;
case 1:snake[0].X=DEC(snake[0].X);break;
case 2:snake[0].Y=INC(snake[0].Y);break;
case 3:snake[0].X=INC(snake[0].X);break;
}
}
思路:不断地上下扫荡,右侧一列无蛋可跳过,有蛋或者有蛇身则上下触边时转弯。
效果:100%玩到满分,速度较慢
void Pautoplay()
{
if((snake[0].Y==1&&dir==0)||(snake[0].Y==30&&dir==2)){dir=3;return;}
if(dir==3)
{
int px=snake[0].X;
px=INC(INC(px));
for(int i=1;i<slong;i++)
if(px==snake[i].X){dir=(snake[0].Y==1?2:0);return;}
px=snake[0].X;
for(int i=1;i<=eggnum;i++)
if(px==egg[i].X){dir=(snake[0].Y==1?2:0);return;}
}
}
思路:扫描前左右三个方向,按如下规则选择方向:有蛋方向优先无蛋方向,蛋距离越近的方向越优先,无蛋时距离蛇身越远的方向越优先。优化点:识别出死胡同,即使有蛋也不进入死胡同方向。
效果:速度很快,但无法取得太高的分数
void autoplay()
{
int num,retype,block,sc[4]={0};COORD p;
for(int d=0;d<4;d++)
{
retype=0;num=0;p=snake[0];
if(d!=(dir+2)%4)do{
switch(d){
case 0:p.Y=DEC(p.Y);break;
case 1:p.X=DEC(p.X);break;
case 2:p.Y=INC(p.Y);break;
case 3:p.X=INC(p.X);break;}
num++;
for(int i=1;i<slong;i++)
{if(p.X==snake[i].X&&p.Y==snake[i].Y){retype=1;break;}}
if(retype==1||num==29){sc[d]=num;break;}
for(int i=1;i<=eggnum;i++)
{if(p.X==egg[i].X&&p.Y==egg[i].Y){retype=2;break;}}
if(retype==2){sc[d]=60-num;break;}
}while(1);
p=snake[0];
if(d!=(dir+2)%4)do
{
block=0;retype=0;
switch(d)
{
case 0: p.Y=DEC(p.Y);
for(int i=1;i<slong;i++)
{if(p.X==snake[i].X&&p.Y==snake[i].Y){retype=1;break;}}
for(int i=1;i<slong;i++)
if(DEC(p.X)==snake[i].X&&p.Y==snake[i].Y){block++;break;}
for(int i=1;i<slong;i++)
if(INC(p.X)==snake[i].X&&p.Y==snake[i].Y){block++;break;}
break;
case 1: p.X=DEC(p.X);
for(int i=1;i<slong;i++)
{if(p.X==snake[i].X&&p.Y==snake[i].Y){retype=1;break;}}
for(int i=1;i<slong;i++)
if(p.X==snake[i].X&&DEC(p.Y)==snake[i].Y){block++;break;}
for(int i=1;i<slong;i++)
if(p.X==snake[i].X&&INC(p.Y)==snake[i].Y){block++;break;}
break;
case 2: p.Y=INC(p.Y);
for(int i=1;i<slong;i++)
{if(p.X==snake[i].X&&p.Y==snake[i].Y){retype=1;break;}}
for(int i=1;i<slong;i++)
if(DEC(p.X)==snake[i].X&&p.Y==snake[i].Y){block++;break;}
for(int i=1;i<slong;i++)
if(INC(p.X)==snake[i].X&&p.Y==snake[i].Y){block++;break;}
break;
case 3: p.X=INC(p.X);
for(int i=1;i<slong;i++)
{if(p.X==snake[i].X&&p.Y==snake[i].Y){retype=1;break;}}
for(int i=1;i<slong;i++)
if(p.X==snake[i].X&&DEC(p.Y)==snake[i].Y){block++;break;}
for(int i=1;i<slong;i++)
if(p.X==snake[i].X&&INC(p.Y)==snake[i].Y){block++;break;}
break;
}
if((block!=2)&&(retype==0))break;
if(retype==1)sc[d]=1;
}while(1);
}
sc[(dir+2)%4]=-1;
int maxsc=sc[0];int maxdir=0;
for(int i=1;i<4;i++)if(maxsc<sc[i])maxsc=sc[i],maxdir=i;
dir=maxdir;
}