C语言—— 贪吃蛇

前言:  学习C语言的目的绝不是理论知识,而是在实践中实现它,而学习,制作贪吃蛇或者其他的小游戏是对知识的总结和运用,它能够帮助我们更快的认识C语言。(不足之处,烦请斧正)

正文:

         其实对于初学者来说,制作小游戏非常困难, 对于贪吃蛇的制作可以寻找各种资源,达到理解的目的。

         它用到的知识除了课本中的,指针,数组,结构体以外还涉及对于系统库的调用和理解这是比较困难的,因为在这其中只给了用法,它更深层次的原理是晦涩难懂的,还涉及计算机软硬件的知识所以这是比较难理解的,但是在这个项目里会标明它所用到的函数及其作用,下面是贪吃蛇效果图的展示

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAV2hpc3BlciwsLCwsLCwsLA==,size_20,color_FFFFFF,t_70,g_se,x_16

        它的源代码如下:

#include<stdio.h>

#include<conio.h>

#include<windows.h>

#include<time.h>

#define framex 5

#define framey 5

#define wide 20

#define high 20

//将光标移动到指定位置

int i,j,a[2];

void getxy(int x,int y){

 HANDLE hout=GetStdHandle(STD_OUTPUT_HANDLE);

    COORD pos; //COORD是WindowsAPI中定义的一种结构,表示一个字符在控制台屏幕上的坐标,它是对于gotoxy函数而言的                  

    pos.X=x;

    pos.Y=y;

    SetConsoleCursorPosition(hout,pos); //SetConsoleCursorPosition是API中定位光标位置的函数。

}

//游戏封面

void cover (){

 HANDLE hout=GetStdHandle(STD_OUTPUT_HANDLE);

    getxy(framex+wide*2,framey);

    printf("欢迎使用贪吃蛇游戏1.0");

    getxy(framex+wide*2,framey+5);

    printf("开始游戏前请关闭中文输入法");

    getxy(framex+wide*2,framey+6);

    printf("按回车键准备开始");

    getxy(framex+wide*2,framey+20);

    printf( "游戏制作者:B21040315Whisper"); 

    getxy(framex+wide*2,framey+22);

    printf("制作时间:2022年3月"); 

    char a;

    a=getchar();

    system("cls");//实行清屏操作 

//定义蛇的结构体 

struct Snake{

    int x[100];

    int y[100];

    int speed;

    int length;

    int count;

};

//定义食物的结构体 

struct Food{

    int x;

    int y;

};

//制作框架 

void makeframe(struct Snake snake){

    //定义显示器变量句柄 

    HANDLE hout=GetStdHandle(STD_OUTPUT_HANDLE);

    getxy(framex+wide*2+5,framey);

    printf( " 贪吃蛇游戏"); 

    getxy(framex+wide*2+5,framey+3);

    printf("使用方向键或wasd移动");

    getxy(framex+wide*2+5,framey+5);

    printf("长按方向键可加速");

    getxy(framex+wide*2+5,framey+7);

    printf("按任意键暂停,方向键继续");

    //打印上边框 

    for(i=0;i<wide*2+1;i++){

        getxy(framex+i,framey);

        printf("*");

    }

    //打印下边框 

    for(i=0;i<wide*2+2;i++){

        getxy(framex+i,framey+high);

        printf("*");

    }

    //打印左边框 

    for(i=0;i<high;i++){

        getxy(framex,framey+i);

        printf("*");

    }

    //打印右边框 

    for(i=0;i<high;i++){

        getxy(framex+wide*2+1,framey+i);

        printf("*");

    }

}

void infor(struct Snake* snake){

 HANDLE hout=GetStdHandle(STD_OUTPUT_HANDLE);

    getxy(framex+wide*2+5,framey+15);

    printf("当前速度:%d",snake->speed+500);

    getxy(framex+wide*2+5,framey+17);

    printf("当前得分:%d",snake->count);

    getxy(framex+wide*2+5,framey+19);

    printf("当前长度:%d",snake->length);

//初始化蛇 

void initsnake(struct Snake *snake){

    snake->x[0]=framex+2; //初始化蛇尾的坐标光标 

    snake->y[0]=framey+high/2;

    snake->count=0;

    snake->length=3;

    snake->speed=400;

    //初始化由蛇尾至蛇头的坐标 

    for(i=1;i<snake->length;i++){ //循环两次,分别初始化蛇身和蛇头的坐标 

        snake->x[i]=snake->x[i-1]+1;

        snake->y[i]=snake->y[i-1];

    }

}

//打印蛇 

void printsnake(struct Snake *snake){

    for(i=0;i<snake->length;i++){

        getxy(snake->x[i],snake->y[i]);//光标从指定的 

        if(i==snake->length-1) 

            printf("@");

        else if(i==0)

            printf(">");

        else 

            printf("#"); 

    }

}

//移动蛇 

void movesnake(HANDLE hout,struct Snake *snake){

    getxy(snake->x[0],snake->y[0]);

    //清除蛇尾 

    printf(" ");

    //蛇的后一节坐标变成前一节的坐标 

    for(i=1;i<snake->length;i++){

        snake->x[i-1]=snake->x[i];

        snake->y[i-1]=snake->y[i];

    }

}

//打印食物 

void printfood (HANDLE hout,struct Snake *snake,struct Food* food){

    //用计算机时间获取随机值 

    srand((unsigned)time(NULL));

    while(1){

        //将食物的横纵坐标的大小限定在窗口大小内 

        food->x=rand()%(wide-2)+1;

        food->y=rand()%(high-2)+1;

        //避免食物出现在边框上 

        if(food->x==0&&food->y==0)

            continue;

        //将食物的坐标放置在窗口内 

        food->x=2*food->x+framex;

        food->y+=framey;

        //如果食物出现在蛇上,重新产生食物 

        for(i=0;i<snake->length;i++){

            if(food->x==snake->x[i]&&food->y==snake->y[i])

                break;

        }

        //食物不在蛇上,打印食物,结束循环 

        if(i==snake->length){

            getxy(food->x,food->y);

            printf("#");

            break;  

        }

    }

 

}

//吃食物 

void eatfood(HANDLE hout,struct Snake * snake,struct Food *food){

    //如果蛇头的坐标等于食物的坐标 

    if(snake->x[snake->length-1]==food->x&&snake->y[snake->length-1]==food->y){

        //蛇长加一 

        snake->length++;

        //蛇身(不包括蛇尾)整体像前移动一格 

        for(i=snake->length-1;i>0;i--){

            snake->x[i]=snake->x[i-1];

            snake->y[i]=snake->y[i-1];

        }

        //得到蛇尾的坐标(即蛇移动前的蛇尾坐标) 

        snake->x[0]=a[0];      

        snake->y[0]=a[1];

        printfood(hout,snake,food);

        snake->count++;

        if(snake->count%3==0)

            snake->speed-=50;

    }

}

//死亡判断 

int ifdead(struct Snake* snake){

    //如果碰到左边界 返回0;

    if(snake->x[snake->length-1]==framex)

        return 0;

    //如果碰到右边界 返回0;

    if(snake->x[snake->length-1]==framex+wide*2)

        return 0;

    //如果碰到上边界 返回0;

    if(snake->y[snake->length-1]==framey)

        return 0;

    //如果碰到下边界 返回0;

    if(snake->y[snake->length-1]==framey+high)

        return 0;

    //如果碰到自己身体 返回0; 

    for(i=0; i<snake->length-1; i++) 

        if( snake->x[snake->length-1]==snake->x[i] && snake->y[snake->length-1]==snake->y[i] ) 

            return 0;

    //否则返回1; 

    return 1;

}

//开始游戏 

int main(){

    unsigned char ch =77;

    //定义显示器句柄 

    HANDLE hout = GetStdHandle(STD_OUTPUT_HANDLE);

    cover(hout);

    struct Snake s, *snake=&s;

    struct Food f, *food=&f;

    makeframe(*snake);

    initsnake(snake);

    printfood(hout,snake,food);

    Sleep(500);

    while(1){

        infor(snake);

        //保存蛇尾横纵坐标 

        a[0]=snake->x[0];

        a[1]=snake->y[0];

        j=0;

        //如果用户敲击键盘

        if(kbhit()){ 

            //用ch接收输入 ,注意是getch(),不需敲击回车

            ch=getch();

            if(kbhit()){

            //长按时间

                Sleep(20);

                j=1;

            }

        }

 switch(ch){

            //向上移动 

            case'W':

            case 'w' :

            case 72:{

                movesnake(hout,snake);

                //蛇头纵坐标减一 

                snake->y[snake->length-1]-=1;

                break;

            }

            //向下移动 

            case'S':

            case 's':

            case 80:{

                movesnake(hout,snake);

                //蛇头纵坐标加一 

                snake->y[snake->length-1]+=1;

                break;

            }

            //向左移动 

            case'A':

            case 'a':

            case 75:{

                movesnake(hout,snake);

                //蛇头横坐标减二 

                snake->x[snake->length-1]-=2;

                break;

            }

            //向右移动 

            case'D':

            case 'd':

            case 77:{

                movesnake(hout,snake);

                //蛇头横坐标加二 

                snake->x[snake->length-1]+=2;

                break;

            }

        }

 

        eatfood(hout,snake,food);

        printsnake(snake);

        //如果判断蛇死亡,跳出循环 

        if(ifdead(snake)==0||ch==27||snake->speed==0){

            getxy(framex+wide/2,framey-2);

            if(snake->speed==0)

                printf("恭喜你通关了!!!");

            else

                printf("糟糕 T_T");

            break;

        }

 

        if(j==0)

        //如果没有长按,蛇滞留的时间为 

            Sleep(snake->speed);

        //如果长按,蛇滞留的时间为 20ms,即加速 

        else 

            Sleep(20);

    }

    //跳出循环时 ,滞留死亡场景一段时间

    Sleep(3000);

    //清屏 

    system("cls");

    //显示结束界面 

    if(snake->speed==0) 

        printf("\n\n\n\n\n\t\t\t哈哈,你赢了\n\n\t\t\t你得到了满分:24\n\n\n");

    else 

        printf("\n\n\n\n\n\t\t\t哈哈,你输了\n\n\t\t\t你的最终得分是:%d\n\n\n",snake->count); 

    Sleep(3000);

    return 0; 

}

      源代码运行以后就可以运行贪吃蛇了。当然对于其中用到的函数,执行特定的操作本质是对于系统提供的文件如windows.h和time.h以及conio.h它们所包含的函数具体的可以去问度娘;其中走不好理解的应该是句柄了,当然在源码中我们已经有简单的介绍了但是它是比较复杂的,在此不做赘述。

       在贪吃蛇中对于初次实操的同学,主要会遇到三个问题:

1,对于头文件的调用及其函数的运用。(可自行查找资料,也可看我以前发的)。

2,对于蛇🐍的移动和它的信息的变动所用到的C语言的数组,指针,结构体,函数等等的综合的知识的运用

3,对于它的改变方向以及蛇🐍的限制信息的指定,如蛇增长,蛇碰到边框,身体死亡等等

下面是一般的框图

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAV2hpc3BlciwsLCwsLCwsLA==,size_10,color_FFFFFF,t_70,g_se,x_16

 这就是一般的贪吃蛇的流程。

      对于C语言的学习是一个长久的事情,需要我们去坚持,中所谓万事开头难,一定要找好自己的状态。希望能对读者有帮助。有不足之处,烦请斧正。

  • 1
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值