整理电脑文件资料,发现的自己18年(大一下学期)写的数据结构大作业贪吃蛇。时光流逝,转眼间2年就过去了。
老师意见:有存档功能,就能满分了。
看代码,借思路,独自实现,成长自己。
游戏效果图如下:
代码如下:
#include<stdio.h>
#include<stdlib.h>
#include<windows.h>
#include<conio.h>
#include<time.h>
#define Wid 40
#define Hei 20
int speed;//蛇的速度
//蛇的节点
typedef struct Snake_node{
COORD pos;
struct Snake_node *next;
struct Snake_node *prev;
}Snake,*PSnake;
PSnake Head;//蛇的头指针
PSnake Tail;//蛇的尾指针
struct Snake_pos{
COORD pos;
int dir;
}HeadPos;//蛇头即将移动的方向和坐标
COORD Food;//食物坐标
int score;//积分记录
//光标定位
void GetPosition(COORD pos)
{
HANDLE hout=GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleCursorPosition(hout,pos);
}
//游戏玩家积分等级输出
void GameLevel()
{
COORD pos_1={Wid+2,11};
GetPosition(pos_1);
if(score>=70)
{
printf("当前游戏等级:恭喜你登顶了");
}
else if(score>=60)
{
printf("当前游戏等级:最强蛇人2颗心");
}
else if(score>=55)
{
printf("当前游戏等级:最强蛇人1颗心");
}
else if(score>=50)
{
printf("当前游戏等级:一代宗师3颗心");
}
else if(score>=45)
{
printf("当前游戏等级:一代宗师2颗心");
}
else if(score>=40)
{
printf("当前游戏等级:一代宗师1颗心");
}
else if(score>=36)
{
printf("当前游戏等级:炉火纯青3颗心");
}
else if(score>=32)
{
printf("当前游戏等级:炉火纯青2颗心");
}
else if(score>=28)
{
printf("当前游戏等级:炉火纯青1颗心");
}
else if(score>=24)
{
printf("当前游戏等级:马马虎虎3颗星");
}
else if(score>=19)
{
printf("当前游戏等级:马马虎虎2颗星");
}
else if(score>=16)
{
printf("当前游戏等级:马马虎虎1颗星");
}
else if(score>=13)
{
printf("当前游戏等级:初学乍练3颗星");
}
else if(score>=7)
{
printf("当前游戏等级:初学乍练2颗星");
}
else if(score>=0)
{
printf("当前游戏等级:初学乍练1颗星");
}
}
//添加蛇的头节点
void AddSnakeHead(COORD pos)
{
GetPosition(pos);//光标定位
printf("◆");//打印蛇头
//双链表操作,开辟结点,储存坐标,头插法插入,考虑实际情况,头部的前指针不用置空
PSnake q=(PSnake)malloc(sizeof(Snake));
q->pos=pos;
if(Head==NULL&Tail==NULL)
{
Head=Tail=q;
q->next=NULL;
}
else
{
q->next=Head;
Head->prev=q;
Head=q;
}
//输出头部的位置
COORD pos_1={Wid+2,2};
GetPosition(pos_1);
printf(" ");//涉及循环打印信息,空格覆盖,防止信息错乱
GetPosition(pos_1);
printf("蛇头位置:%d行 %d列",pos.Y,pos.X/2);
}
//删掉蛇的尾节点
void ReduceSnakeTail()
{
GetPosition(Tail->pos);//光标定位到尾部
printf(" ");//输出空格覆盖
Tail=Tail->prev;//尾指针前
free(Tail->next);//释放尾部空间
Tail->next=NULL;//新的尾部的后指针置空
}
//蛇的移动
void MoveSnake(COORD pos)
{
AddSnakeHead(pos);//增加头结点
ReduceSnakeTail();//删除尾结点
}
//方向控制
void ChangeDir()
{
//仅有蛇头时可以向四周转换方向,当有蛇身时不能突然直接转向
COORD pos_1={Wid+2,4};
int flag=0;//因为下面用的while循环,所以设置此标记,保证方向的单次改变 (如果没有会出现BUG,直接掉头)
while(_kbhit())
{
switch(getch())
{
case 72:
if(!(HeadPos.dir==1&&score>1)&&flag==0)//1.保证单次方向改变 2.仅有头可以四周改变方向 3.有了身体不能直接转变成相反方向
{
HeadPos.dir=0;
flag=1;
}
break;
case 80:
if(!(HeadPos.dir==0&&score>1)&&flag==0)
{
HeadPos.dir=1;
flag=1;
}
break;
case 75:
if(!(HeadPos.dir==3&&score>1)&&flag==0)
{
HeadPos.dir=2;
flag=1;
}
break;
case 77:
if(!(HeadPos.dir==2&&score>1)&&flag==0)
{
HeadPos.dir=3;
flag=1;
}
break;
case 32:
pos_1.Y=8;
GetPosition(pos_1);
system("pause");
GetPosition(pos_1);
printf(" ");
GetPosition(pos_1);
printf("按空格键暂停游戏");
break;
case '5':
speed=50;
GetPosition(pos_1);
printf("当前模式:噩梦");
break;
case '4':
speed=100;
GetPosition(pos_1);
printf("当前模式:困难");
break;
case '3':
speed=150;
GetPosition(pos_1);
printf("当前模式:一般");
break;
case '2':
speed=200;
GetPosition(pos_1);
printf("当前模式:简单");
break;
case '1':
speed=400;
GetPosition(pos_1);
printf("当前模式:蜗牛");
break;
default:
break;
};
}
switch (HeadPos.dir)
{
case 0:
HeadPos.pos.Y--;
break;
case 1:
HeadPos.pos.Y++;
break;
case 2:
HeadPos.pos.X-=2;
break;
case 3:
HeadPos.pos.X+=2;
break;
}
}
//划出游戏边框
void DrawBorder()
{
//边框打印
COORD pos;
for(pos.Y=0;pos.Y<=Hei-1;pos.Y++)
{
GetPosition(pos);
for(pos.X=0;pos.X<=Wid-2;pos.X+=2)
{
if(pos.Y==0||pos.Y==Hei-1||pos.X==0||pos.X==Wid-2)
{
printf("■");
}
else
{
printf(" ");
}
}
pos.X=0;
}
//边框右侧部分信息打印
COORD pos_1={Wid+2,4};
GetPosition(pos_1);
printf("模式选择提示:按键1~5分别对应傻瓜、简单、一般、困难、噩梦");
pos_1.Y++;
GetPosition(pos_1);
printf("游戏过程中,模式可以随意切换,请君量力而行!");
pos_1.Y++;
GetPosition(pos_1);
printf("当前模式:一般");
speed=150;
pos_1.Y=8;
GetPosition(pos_1);
printf("按空格键暂停游戏");
pos_1.Y=0;
GetPosition(pos_1);
printf("贪吃蛇游戏");
pos_1.Y=12;
GetPosition(pos_1);
printf("想要知道最高等级是什么吗?那就继续玩游戏吧!");
pos_1.Y=14;
GetPosition(pos_1);
printf("蛇头方向控制:↑↓←→");
pos_1.Y=15;
GetPosition(pos_1);
printf("大兄弟,祝你玩的开心!O(∩_∩)O");
pos_1.Y=Hei-3;
GetPosition(pos_1);
printf("开发者信息:信安1704-张鹏-学号xxxxxxxx");
}
//游戏结束判断
int GameOver()
{
if(HeadPos.pos.X<=0||HeadPos.pos.X>=Wid-2||HeadPos.pos.Y<=0||HeadPos.pos.Y>=Hei-1)//撞墙
{
return 1;
}
PSnake q=Head;
while(q!=NULL)
{
if(HeadPos.pos.X==q->pos.X&&HeadPos.pos.Y==q->pos.Y)//蛇食自身
{
return 1;
}
q=q->next;
}
return 0;
}
//食物和积分信息输出
void FoodInfo()
{
COORD pos={Wid+2,1};
GetPosition(pos);
printf(" ");//分数多次刷新,所需要用空格刷掉前面输出的文字,防止接下来输出混乱排版
GetPosition(pos);
printf("食物位置:%d行 %d列",Food.Y,Food.X/2);
pos.Y=9;
GetPosition(pos);
printf("当前得分:%d",score++);
}
//初始化食物
int InitFood()
{
srand((unsigned) time(NULL));//利用系统时间来改变系统的种子值
while(1)
{
//用取余法控制食物随机出现的位置的范围(保证出现在墙内)
Food.X=(rand()%(Wid/2-2)+1)*2;
Food.Y=rand()%(Hei-2)+1;
int flag=0;//flag为标志,初始化为0,表示假设食物位置不与蛇身重合
PSnake q=Head;
while(q!=NULL)//从头到尾遍历检查
{
if(Food.X==q->pos.X&&Food.Y==q->pos.Y)//判断随机获得的食物位置是否与蛇身重合
{
flag=1;
break; //如果重合,提前结束循环,重新获取随机食物位置
}
q=q->next;
}
if(flag==0)//假设成立跳出循环,
{
break;
}
}
GetPosition(Food);//光标定位
printf("●");//打印食物
GameLevel();//输出玩家积分所达到的等级
FoodInfo();//输出食物位置信息
}
//考虑到内存问题,链表空间释放(重新开始游戏需要用到)
void DestroySnake()
{
while(Tail!=Head)//释放蛇身节点
{
Tail=Tail->prev;
free(Tail->next);
}
free(Tail);//释放蛇头节点
}
//游戏数据初始化
void InitGame()
{
system("color 0E");//控制台颜色控制
DrawBorder();
//初始化蛇出现的位置(中间),默认方向向上
HeadPos.pos.X=Wid/2;
HeadPos.pos.Y=Hei/2;
HeadPos.dir=0;//0:向上 1:向下 2:向左 3:向右
//初始化蛇头
Head=NULL;
Tail=NULL;
AddSnakeHead(HeadPos.pos);
//初始化分数和食物
score=0;
InitFood();
}
//游戏运行控制
void RunGame()
{
while(1)
{
Sleep(speed);//挂起函数,控制蛇的速度
ChangeDir();
if(GameOver())//游戏结束
{
break;
}
else if(HeadPos.pos.X==Food.X&&HeadPos.pos.Y==Food.Y)//吃到食物
{
AddSnakeHead(HeadPos.pos);//增加蛇头
InitFood();//食物被吃,重新初始化打印食物
}
else
{
MoveSnake(HeadPos.pos);//蛇移动
}
}
//蛇死亡后
COORD pos_1={0,Hei};
GetPosition(pos_1);
printf("很遗憾,你撞墙了或者自食自己,游戏结束!\n");
}
//游戏重新开始
int RestartGame()
{
int restar;
printf("你是最棒的!是否重新挑战游戏?\n");
printf("0.否 1.是\n");
printf("请选择(按回车键确认):");
scanf("%d",&restar);
if(restar==1)
{
system("cls");
DestroySnake();
return 1;
}
else if(restar==0)
{
printf("游戏退出!\n");
return 0;
}
else
{
printf("选择无效!默认退出!\n");
return 0;
}
}
int main()
{
while(1)
{
InitGame();
RunGame();
if(RestartGame())
{
continue;
}
break;
}
return 0;
}
游戏下载:https://download.csdn.net/download/Boy_z/12367809