#include<stdio.h>
#include<stdlib.h>
#include<windows.h>
#include<string.h>
#include<time.h>
#include<string.h>
#include<conio.h>
//********************************************按键控制********************************************
#define up 'w'
#define down 's'
#define left 'a'
#define right 'd'
#define stop 'p'
//********************************************按键控制********************************************
//********************************************自定义函数********************************************
void welcome();//开始界面
void Finish();//结束界面
void creatgraph();//打印围墙
void gotoxy(int x,int y);//坐标打印
void gotoprint(int x,int y);//配合坐标指定打印
void gotodelete(int x,int y);//配合坐标指定删除
void creatfood();//随机产生的食物链
int ClickControl();//以此获取键盘信号
int Judge();//游戏结束的信号
void MovingBody();//游戏中蛇的移动
void Eating();//蛇吃到东西后的操作(变长)
void ChangeBody(int a,int b);//蛇的坐标变换,后一个复制前一个STRUCT,a,b为head之前的坐标
char *s_get(char *st,int n);//字符串输入
//********************************************自定义函数********************************************
//********************************************全局变量+预处理********************************
typedef struct Snake{
int x;
int y;
struct Snake *next;
}snake;//蛇身的每一个坐标点
snake *head,*tail;//蛇的头跟尾部
struct Food{
int x;
int y;
}food;//蛇的食物呀!!!
char name[20];//用户登录贪吃蛇游戏名字
int score=0;//计算游戏时总的分数
char click=1;//用来获取用户控制游戏的信息
int speak;//每次的缓冲时间
//********************************************全局变量+预处理********************************
//********************************************主体函数********************************************
int main()
{
system("color 0B");
welcome();//开始的界面 第64行开始的代码
creatgraph();//打印出围墙(游戏范围) 第105行代码开始
creatfood();//用于产生贪吃蛇粮食的函数 第179行代码开始
if(ClickControl()==0)//获取键盘信号 第205行代码开始
Finish();//返回结束界面
return 0;
}
//********************************************主体函数********************************************
//********************************************自定义函数代码********************************************
//-----------------游戏开始界面-----------------
void welcome()//开始界面
{//注意了改距离是我经过试验后所得,可以根据实际情况更改
gotoxy(10,6);
printf("*****************************************");
gotoxy(10,20);
printf("*****************************************");
gotoxy(10,8);
printf("欢迎来到整修版贪吃蛇!!!");
gotoxy(10,13);
printf("控制wsad四键,暂停为p,q为退出!");
gotoxy(10,18);
printf("输入将要生成的贪吃蛇名字吧:");
s_get(name,20);
gotoxy(10,21);
system("pause");
system("cls");
}
//-----------------游戏开始界面-----------------
//-----------------游戏结束界面-----------------
void Finish()//结束界面
{
system("cls");//清除前面所有的内容(俗称清屏)
gotoxy(10,6);
printf("*****************************************");
gotoxy(10,20);
printf("*****************************************");
gotoxy(10,8);
printf("游戏结束了!!!");
gotoxy(10,13);
printf("友情提示:YOU GAME OVER!!!!");
gotoxy(10,18);
printf("游戏总得分:%d",score);
gotoxy(10,21);
free(head);//这里我们需要释放掉一直存在内存
free(tail);//从136行代码开始看
system("pause");
}
//-----------------游戏结束界面-----------------
//-----------------打印游戏范围和一开始的蛇-----------------
void creatgraph()//打印围墙
{
int i;
for(i=0;i<48;i+=2)//此处为打印上下部分的围墙
{//因为打印的每一个方块都是两个字节所以这里需要+2来平衡,
//另外48既是从左到右一共有48个字节,比喻:人要走48小步才到达终点
gotoprint(i,0);//
gotoprint(i,20);//请自行决定数值也可以
}
for(i=0;i<21;i++)//此处为了打印左右部分的围墙
{
gotoprint(0,i);
gotoprint(48,i);
}
//上面的坐标点可以参考x、y轴这种思考办法
gotoxy(51,6);//我们将输出光标移动一下位置
printf("欢迎来到贪吃蛇2.0改:%s。",name);//这个是你的名字
gotoxy(51,10);//为了美观我劝你还是照办得好(对齐)
printf("呵呵,这是你现有的分数:%d",score);
gotoxy(51,14);
printf("该游戏是萌新兔改进抄袭2.0版!");
//好吧!上面这一部分无关紧要
head=(snake *)malloc(sizeof(snake));
head->x=20;
head->y=17;
tail=(snake *)malloc(sizeof(snake));
snake *p=(snake *)malloc(sizeof(snake));
snake *q=(snake *)malloc(sizeof(snake));
snake *a;
(*p).x=18;
p->y=17;
q->x=16;
q->y=17;//这一部分是蛇一开始的坐标位置,一开始蛇就三节
head->next=p;//蛇头后的一节
p->next=q;//好吧,到这里是一开始三块中间块后面的尾巴(就是最后一块)
q->next=tail;//好吧,这里是尾巴了,我这个NULL是不是很惊喜
tail->next=NULL;
a=head;
while(a->next!=NULL)
{
gotoprint(a->x,a->y);
a=a->next;
}
}
//-----------------打印游戏范围和一开始的蛇-----------------
//-----------------给定坐标后再屏幕某坐标打印函数-----------------
void gotoxy(int x,int y)//坐标打印
{
COORD loc={x,y};//用户指定的某个坐标点
HANDLE houpt=GetStdHandle(STD_OUTPUT_HANDLE);//固定的函数,里面的output是标准输出
SetConsoleCursorPosition(houpt,loc);//固定函数,意思是将改坐标点输入到屏幕某点
}
//-----------------给定坐标后再屏幕某坐标打印函数-----------------
//-----------------输出打印小方块-----------------
void gotoprint(int x,int y)//配合坐标指定打印
{
gotoxy(x,y);
printf("■");
}
//-----------------输出打印小方块-----------------
//-----------------用于清空的函数-----------------
void gotodelete(int x,int y)//配合坐标指定删除
{
gotoxy(x,y);
printf(" ");//注意这里是两个空格,因为一个空格一个字节
}
//-----------------用于清空的函数-----------------
//-----------------用于产生贪吃蛇粮食的函数-----------------
void creatfood()//随机产生的食物链
{
srand((int)time(NULL));
lable://标签,与下面的goto一起用哦,goto回到这里
food.x=rand()%44+2;//我的地图可是48宽,第47和48还有0,1是墙
food.y=rand()%19+1;//高度为21哦,0和21我不用明说
if(food.x%2!=0)
food.x+=1;//因为输入的方块可是两个字节的,所以必须是双数
snake *judge=head;//这个是蛇头的,也就是头部的方块
while(1)
{
if(judge->next==NULL) break;//蛇头返回是空的
if(food.x==(*judge).x&&food.y==(*judge).y)//如果蛇与食物一开始就出现在同一个位置
{
goto lable;//返回上面的lable位置继续循环
}
judge=judge->next;
}
gotoxy(food.x,food.y);
printf("★");
}
//-----------------用于产生贪吃蛇粮食的函数-----------------
//-----------------方向键控制输入-----------------
int ClickControl()//以此获取键盘信号
{
int i=1;
char as;
while(1)
{
if(Judge()==0) return 0;
if(kbhit())//按键输入的函数,会读取键盘按键的信息
{
as=getch();
switch(as)
{
case up://如果输入的是上
if(click!=2)//那么就要杜绝掉下,以防止出现掉头
//这里的click保留的是上一个,打比方就是如果上一个是向下
//那么click就不能等于向上,杜绝掉头,所以必须保证click上一个操作不是下
//那么这次的click操作向上可以成立
click=1;
break;
case down://同上
if(click!=1)
click=2;
break;
case left://同上
if(click!=4)
click=3;
break;
case right://同上
if(click!=3)
click=4;
break;
case stop:click=5;break;
case 'q':Finish();
}
}
if(i==1)
{
click=4;
i--;
}
MovingBody();//蛇的移动操作等功能
Eating();//蛇吃到东西后的操作(变长) 第292行代码开始
}
return 1;
}
//-----------------方向键控制输入-----------------
//-----------------蛇的防撞解析-----------------
int Judge()//游戏结束的信号(吃自己(撞墙)还不结束)
{
if(head->x==0||head->x==46||head->y==0||head->y==20)//都直接撞墙了
{
return 0;//这里是我以防万一的设置
}
snake *p=head->next;//将蛇的链表节点接入
while(p!=NULL)//最后都等于清空了,还怎么玩
{
if(head->x==p->x&&head->y==p->y)
{
return 0.;
}//这里是保持头依旧是头的坐标,如果是蛇身上任意一点的话,呵呵
p=p->next;//这里的节点必须进入下一个
}
return 1;//恭喜你,这里是保证你吃自己活着撞墙了
}
//-----------------蛇的防撞解析-----------------
//-----------------蛇每次吃到食物后的操作以及蛇的移动算法(蛇的打印)-----------------
void MovingBody()//游戏中蛇的移动
{
int count=0;//这个是用来计分的,放心往下看你就知道了
int a=head->x,b=head->y;//蛇头的坐标点
snake *p=head;//整条蛇的结构
while(p->next!=NULL)
{
gotodelete(p->x,p->y);//每次移动后都得删减
p=p->next;
}
p=head->next;
switch(click)//键盘每次敲击输入的数
{
case 1: head->y-=1; ChangeBody(a,b); break;//第302行为蛇的坐标移动
case 2: head->y+=1; ChangeBody(a,b); break;//上下是一个字节
case 3: head->x-=2; ChangeBody(a,b); break;
case 4: head->x+=2; ChangeBody(a,b); break;//左右时两个字节
//这里的十字坐标轴区翻翻看你就明白了
case 5: getch(); break;//getchar()本身就是暂停呀!!!!!
case 6: Finish(); break;
}
p=head;//这个是把头给这个指针
while(p->next!=NULL)//每一次敲击键盘后上面数据更新这里就打印一次
{
gotoprint(p->x,p->y);//将每一个节点打印出来
count++;//计分每次加1
p=p->next;
}
p=head;//同上 第257行
gotoxy(0,24);
if(count<=30) speak=200;
else if(count>30&&count<=60) speak=150;
else if(count>60&&count<=90) speak=100;
else speak=50;
Sleep(speak);//每次你吃掉了食物后增加的速度也就是这个刷新了
}
//-----------------蛇每次吃到食物后的操作以及蛇的移动算法(蛇的打印)-----------------
//-----------------蛇长大的操作-----------------
void Eating()//蛇吃到东西后的操作(变长)
{
if(head->x==food.x&&head->y==food.y)
{
creatfood();//每次吃到食物后腰刷新出来
snake *knew=(snake *)malloc(sizeof(snake));//定义一个新的结构变量
snake *p;//没错,又是我
p=head;//一开始就等于头
while(p->next->next!=NULL)//尾巴没有到最后
{
p=p->next;//就给我一直冲
}
p->next=knew;
knew->next=tail;//第148行设置了tail->next为NULL
score+=10;//计分器
gotoxy(75,10);
printf("%d",score);
}
}
//-----------------蛇长大的操作-----------------
//-----------------蛇移动的坐标转换-----------------
void ChangeBody(int a,int b)//蛇的坐标变换
{
snake *p=head->next;//直接进入链表里面
int mix1,miy1,mix2,miy2;
mix1=p->x;
miy1=p->y;//将坐标给予
while(p->next->next!=NULL)//参考冒泡排序即可
{//坐标交换
mix2=p->next->x;
miy2=p->next->y;
p->next->x=mix1;
p->next->y=miy1;
mix1=mix2;
miy1=miy2;
p=p->next;//这个相当于for()里面最后的++循环
}
//将第一个(x,y)坐标丢给第二个(x,y)坐标,第二个的坐标保留
//依次将会一直推下去,知道NULL
p=head->next;
{//这里就等于将开头给出的坐标丢到第二个节点了,就是第二节蛇身
p->x=a;
p->y=b;
}
}
//-----------------蛇移动的坐标转换-----------------
//-----------------字符串输入家检验-----------------
char *s_get(char *st,int n)//字符串输入
{
char *find,*as;
as=fgets(st,n,stdin);
if(as)
{
find=strchr(st,'\n');
if(find) *find='\0';
else while(getchar()!='\n') continue;
}
return as;
}
//-----------------字符串输入家检验-----------------
//********************************************自定义函数代码********************************************
贪吃蛇 (自我修改添加)
最新推荐文章于 2021-06-17 16:29:17 发布