贪吃蛇 (自我修改添加)

#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;
}
//-----------------字符串输入家检验-----------------

//********************************************自定义函数代码********************************************

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值