看到别的学校大一同学的期末作业是贪吃蛇,我也斗胆尝试自己code一个简易版娱乐一下。
我采用的是链表(主要是刚学链表想试试手),其实也可以用数组(参考其他大佬)。
总的来说代码难度不是很大,都是入门时学的内容(我这个蒟蒻能完成,大家也一定可以)。主要的困惑点在于对光标控制,这超出了我的知识范畴,所以搜了一些资料,从一无所知到大体明白(也算有进步吧)。
以下代码能够实现贪吃蛇的主要操作,但是也还有可以优化的地方。
可能的的优化方向:
1、加减速
2、穿墙
3、随机生成超级奖励
4、界面优化等
---------------------------------------------------------分割线---------------------------------------------------------------
更新版来啦!已实现上述优化欢迎体验!
#include<stdio.h>
#include<windows.h>
#include<stdlib.h>
#include<math.h>
#include<stdbool.h>
#include<string.h>
#include<time.h>/*用于调用 time_t time(time_t *seconds)函数。
返回自纪元 Epoch(1970-01-01 00:00:00 UTC)起经过的时间*/
#include<conio.h>/*用于调用int getch(void)函数,返回从控制台读取的一个字符。
就本程序而言用于获得键盘的上下左右键信息来指导蛇的移动*/
#define chance 10 //触发big食物
#define minspeed 100
#define shang 72 //上键对应的getch()值为22472
#define you 77 //右键对应的getch()值为22477
#define xia 80 //下键对应的getch()值为22480
#define zuo 75 //左键对应的getch()值为22475
#define space 32 //空格键对应的getch()值为22432
#define Ecs 27 //退出键对应的getch()值为22427
#define f1 59
#define f2 60
struct Snake//链表储存蛇蛇信息
{
int x;
int y;
struct Snake *next;
};
struct Food//储存食物的位置
{
int x;
int y;
};
int border_X=26; //确定图的横向边界
int border_Y=15; //确定图的纵向边界
struct Food food;
struct Snake *head,*tail;
int state=shang;//记录用户按下的键
int score=0;//总得分
int score_small=10;//每个$食物的得分
int score_big=50;
int addscore=0;
int endgamereason=0;//endgamereason=1表示撞墙而亡 endgamereason=2表示我吃我自己 endgamereason=3表示我自己玩不下去了要退出
int sleeptime=300;
void welcome(void);
void gamecircle(void);//游戏主体
void Pos(int x,int y);//光标定位
void initgraph(void);//初始化界面
void createfood(void);//生成食物
void createfood_small(void);
void createfood_big(void);
void initsnake(void);//初始化蛇蛇
void endgame(void);//结束游戏
void reachborder(void);//判断蛇蛇是否到达边界
bool biteself(int x,int y);//判断蛇蛇是否咬自己
void movesnake(void);//蛇蛇动起来
void Pause(void);//暂停
void color(int i);
void colorchoose(void);
void colorchoose(void)
{
system("cls");
int key;
int i;
Pos(border_X/2-5,border_Y/2-5);
printf("请选择你想用的颜色吧(按下对应键即可):");
for(i=1;i<=15;i++)
{
color(i);
Pos(border_X/2+7,border_Y/2-4+i);
printf("%c:Hello world!",i+96);
}
while(1)
{
if(_kbhit())
{
key=getch();
switch (key)
{
case 97:
color(1);
break;
case 98:
color(2);
break;
case 99:
color(3);
break;
case 100:
color(4);
break;
case 101:
color(5);
break;
case 102:
color(6);
break;
case 103:
color(7);
break;
case 104:
color(8);
break;
case 105:
color(9);
break;
case 106:
color(10);
break;
case 107:
color(11);
break;
case 108:
color(12);
break;
case 109:
color(13);
break;
case 110:
color(14);
break;
case 111:
color(15);
break;
default:
break;
}
}
if(key>=97&&key<=111) break;
}
system("cls");
}
void welcome(void)
{
Pos(border_X/2,border_Y/2+1);
printf("欢迎来到pqy的贪吃蛇小游戏");
Pos(border_X/2+2,border_Y/2+3);
printf("请按SPACE键开始游戏吧!");
int key;
while(1)
{
if(_kbhit())
{
key=getch();
if(key==32)
{
system("cls");
Pos(border_X/2+10,border_Y/2+1);
printf("请选择地图");
Pos(border_X/2,border_Y/2+3);
printf("1、小型地图 2、大型地图");
while(1)
{
if(_kbhit())
{
key=getch();
if(key==49)
{
colorchoose();
border_X=26;
border_Y=15;
system("cls");
system("mode con cols=55 lines=23");
initgraph();
initsnake();
return ;
}
else if(key==50)
{
colorchoose();
border_X=104;
border_Y=45;
system("cls");
system("mode con cols=133 lines=50");
initgraph();
initsnake();
return ;
}
else continue;
}
}
/*
initgraph();
initsnake();
break;
*/
}
}
else continue;
}
}
void Pos(int x,int y)
{
HANDLE hOut;
COORD pos;
pos.X=x;
pos.Y=y;
hOut=GetStdHandle(STD_OUTPUT_HANDLE); //句柄
SetConsoleCursorPosition(hOut,pos); //确定光标位置
}
void initgraph(void)
{
for(short i=1;i<border_Y;i++)
{
Pos(0,i);printf("■");
Pos(border_X,i);printf("■");
}
for(short i=0;i<=border_X;i++)
{
Pos(i,0);
printf("■");
Pos(i,border_Y);
printf("■");
}
Pos(0,border_Y+1);
printf("请用上下左右键控制蛇蛇的运动方向");
Pos(0,border_Y+2);
printf("可以按F1键使蛇蛇加速 可以按F2键使蛇蛇减速");
Pos(0,border_Y+3);
printf("可以双击Esc退出游戏 可以双击space暂停游戏");
Pos(0,border_Y+4);
printf("开始游戏吧!");
}
void createfood(void)
{
srand((unsigned)time(NULL)); //用时间作为种子刻意让rand() 产生的随机数随机化。
int judge=rand()%chance;
if(judge==6) createfood_big(),addscore=score_big;
else createfood_small(),addscore=score_small;
}
void createfood_big(void)
{
srand((unsigned)time(NULL)); //用时间作为种子刻意让rand() 产生的随机数随机化。
while(1)
{
food.x=rand()%border_X;
while(food.x<=1||food.x>=border_X-1) food.x=rand()%border_X;
food.y=rand()%border_Y;
while(food.y<=1||food.y>=border_Y-1) food.y=rand()%border_Y;
struct Snake *p=head;
int judge=0;
while(p!=NULL)
{
if(p->x==food.x&&p->y==food.y)
{
judge=1;break;
}
p=p->next;
}
if(judge==0)
{
Pos(food.x,food.y);
printf("¥");
return ;
}
else continue;
}
}
void createfood_small(void)
{
srand((unsigned)time(NULL)); //用时间作为种子刻意让rand() 产生的随机数随机化。
while(1)
{
food.x=rand()%border_X;
while(food.x<=1||food.x>=border_X-1) food.x=rand()%border_X;
food.y=rand()%border_Y;
while(food.y<=1||food.y>=border_Y-1) food.y=rand()%border_Y;
struct Snake *p=head;
int judge=0;
while(p!=NULL)
{
if(p->x==food.x&&p->y==food.y)
{
judge=1;break;
}
p=p->next;
}
if(judge==0)
{
Pos(food.x,food.y);
printf("$");
return ;
}
else continue;
}
}
void initsnake(void)
{
head=(struct Snake*)malloc(sizeof(struct Snake));
head->x=border_X/2;
head->y=border_Y/2;
head->next=NULL;
struct Snake* p;
p=(struct Snake*)malloc(sizeof(struct Snake));
p->x=border_X/2;
p->y=border_Y/2+1;
p->next=NULL;
head->next=p;
struct Snake *q=head;
Pos(q->x,q->y);
printf("*");
q=q->next;
while(q!=NULL)
{
Pos(q->x,q->y);
printf("*");
q=q->next;
}
createfood();
}
void endgame(void)
{
system("cls");
if(endgamereason==1)
{
Pos(border_X/2+1,border_Y/2-1);
printf("你成功撞墙而亡!");
Pos(border_X/2+1,border_Y/2+1);
printf("你最终的得分是:%d",score);
exit(0);
}
else if(endgamereason==2)
{
Pos(border_X/2+1,border_Y/2-1);
printf("你成功把自己吃掉了!");
Pos(border_X/2+1,border_Y/2+1);
printf("你最终的得分是:%d",score);
exit(0);
}
else if(endgamereason==3)
{
Pos(border_X/2+1,border_Y/2-1);
printf("自己玩不下去就别玩。。。");
Pos(border_X/2+1,border_Y/2+1);
printf("你最终的得分是:%d",score);
exit(0);
}
}
void reachborder(void)
{
if(head->x==0||head->x==border_X||head->y==0||head->y==border_Y)
{
endgamereason=1;
endgame();
}
}
bool biteself(int x,int y)
{
struct Snake *p=head;
while(p!=NULL)
{
if(p->x==x&&p->y==y)
{
return true;
}
else p=p->next;
}
return false;
}
void movesnake(void)
{
reachborder();
struct Snake *newnode;
newnode=(struct Snake*)malloc(sizeof(struct Snake));
if(state==shang)
{
if(biteself(head->x,head->y-1))
{
endgamereason=2;endgame();
}
if(head->x==food.x&&head->y-1==food.y)
{
newnode->x=head->x;
newnode->y=head->y-1;
newnode->next=head;
head=newnode;
score+=addscore;
struct Snake *p=head;
while(p!=NULL)
{
Pos(p->x,p->y);
printf("*");
p=p->next;
}
createfood();
}
else
{
newnode->x=head->x;
newnode->y=head->y-1;
newnode->next=head;
head=newnode;
struct Snake *p=head;
while(p->next->next!=NULL)
{
Pos(p->x,p->y);
printf("*");
p=p->next;
}
Pos(p->next->x,p->next->y);
printf(" ");
free(p->next);
p->next=NULL;
}
}
else if(state==you)
{
if(biteself(head->x+1,head->y))
{
endgamereason=2;endgame();
}
if(head->x+1==food.x&&head->y==food.y)
{
newnode->x=head->x+1;
newnode->y=head->y;
newnode->next=head;
head=newnode;
score+=addscore;
struct Snake *p=head;
while(p!=NULL)
{
Pos(p->x,p->y);
printf("*");
p=p->next;
}
createfood();
}
else
{
newnode->x=head->x+1;
newnode->y=head->y;
newnode->next=head;
head=newnode;
struct Snake *p=head;
while(p->next->next!=NULL)
{
Pos(p->x,p->y);
printf("*");
p=p->next;
}
Pos(p->next->x,p->next->y);
printf(" ");
free(p->next);
p->next=NULL;
}
}
else if(state==xia)
{
if(biteself(head->x,head->y+1))
{
endgamereason=2;endgame();
}
if(head->x==food.x&&head->y+1==food.y)
{
newnode->x=head->x;
newnode->y=head->y+1;
newnode->next=head;
head=newnode;
score+=addscore;
struct Snake *p=head;
while(p!=NULL)
{
Pos(p->x,p->y);
printf("*");
p=p->next;
}
createfood();
}
else
{
newnode->x=head->x;
newnode->y=head->y+1;
newnode->next=head;
head=newnode;
struct Snake *p=head;
while(p->next->next!=NULL)
{
Pos(p->x,p->y);
printf("*");
p=p->next;
}
Pos(p->next->x,p->next->y);
printf(" ");
free(p->next);
p->next=NULL;
}
}
else if(state==zuo)
{
if(biteself(head->x-1,head->y))
{
endgamereason=2;endgame();
}
if(head->x-1==food.x&&head->y==food.y)
{
newnode->x=head->x-1;
newnode->y=head->y;
newnode->next=head;
head=newnode;
score+=addscore;
struct Snake *p=head;
while(p!=NULL)
{
Pos(p->x,p->y);
printf("*");
p=p->next;
}
createfood();
}
else
{
newnode->x=head->x-1;
newnode->y=head->y;
newnode->next=head;
head=newnode;
struct Snake *p=head;
while(p->next->next!=NULL)
{
Pos(p->x,p->y);
printf("*");
p=p->next;
}
Pos(p->next->x,p->next->y);
printf(" ");
free(p->next);
p->next=NULL;
}
}
}
void Pause(void)
{
int newstate;
while(1)
{
Pos(border_X+2,border_Y/2+2);
printf("暂停中,请双击SPACE继续游戏");
Sleep(300);
if(_kbhit())
{
newstate=getch();
if(newstate==32)
{
Pos(border_X+2,border_Y/2+2);
printf(" ");
return;
}
}
}
}
void gamecircle(void)
{
int newstate;
while(1)
{
Pos(border_X+2,border_Y/2-2);
time_t cur_time;
time(&cur_time);
printf("%s",ctime(&cur_time));
Pos(border_X+2,border_Y/2-1);
printf("你现在的得分是:%d",score);
Pos(border_X+2,border_Y/2);
printf("每吃一个$的得分:%03d",score_small);
Pos(border_X+2,border_Y/2+1);
printf("每吃一个Y的得分:%03d",score_big);
Sleep(sleeptime);
if(_kbhit())//如果用户使用了键盘就会进入if语句之中,对所按键进行进一步处理
{
newstate=getch();//这个会保存224
newstate=getch();
if(newstate==shang&&state!=xia)
{
state=shang;
}
else if(newstate==xia&&state!=shang)
{
state=xia;
}
else if(newstate==zuo&&state!=you)
{
state=zuo;
}
else if(newstate==you&&state!=zuo)
{
state=you;
}
else if(newstate==space)
{
Pause();
}
else if(newstate==Ecs)
{
endgamereason=3;
endgame();
}
else if(newstate==f1)//加速
{
if(sleeptime>100)
{
sleeptime-=20;
score_small+=1;
score_big+=2;
Pos(border_X+2,border_Y/2+2);
printf("蛇蛇速度+1 $得分+1 ¥得分+2");
}
else
{
Pos(border_X+2,border_Y/2+2);
printf("已经是最快速度啦!");
}
}
else if(newstate==f2)//减速
{
if(sleeptime<500)
{
sleeptime+=20;
score_small=score_small-1;
score_big-=2;
Pos(border_X+2,border_Y/2+2);
printf("蛇蛇速度-1 $得分-1 ¥得分-2");
}
else
{
Pos(border_X+2,border_Y/2+2);
printf("已经是最慢速度啦!");
}
}
}
movesnake();
//Sleep(200);
}
}
void color(int i)
{
if (0 <= i && i <= 15)
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), i);
else return;
}
int main()
{
system("mode con cols=55 lines=23");//设定黑框框大小
welcome();
gamecircle();
system("pause>nul");//不要出现“按任意键继续。。。”这句话
}