c++贪吃蛇

本文介绍了一个简单的贪吃蛇游戏的实现过程,使用C++语言完成。文章详细讲解了游戏的基本逻辑,包括地图生成、蛇的移动、食物生成及游戏控制等内容。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

最近想充实简历所以写了个贪吃蛇,先是在网上找了一个代码,地址是http://blog.youkuaiyun.com/ckcz123/article/details/8204365,然后读懂了里面的句子然后自己小小的改动了一点,下面分享一下经验,这个是原来作者的代码,注释都是我自己学习的时候百度的,留着提醒自己的

/**贪吃蛇,能走*///http://blog.youkuaiyun.com/ckcz123/article/details/8204365
#include <iostream>
#include <cstdio>
#include <cstdlib>/**产生随机数的时候用到了*/
#include <ctime>
#include <conio.h>/**控制台控制窗口函数*/
#include <cmath>
#include <windows.h>
using namespace std;
/*** 光标定位 ***/
HANDLE hout=GetStdHandle(STD_OUTPUT_HANDLE);/**句柄**///括号里的是标准输出句柄,句柄是调用文本界面控制的API函数,而API函数呢,是服务对象是应用程序的函数
COORD coord;/**表示字符在控制台屏幕上的坐标,是一个struct,有x,y属性可以用,在头Windows.h下面**///声明成全局变量
void locate(int x,int y)
{
    coord.X=y;/**coord左上角是(0,0)横坐标是x纵坐标是y向右下延伸*/
    coord.Y=x;//还不懂
    SetConsoleCursorPosition(hout,coord);/**定位光标位置函数**///参数是句柄和坐标,把标准输出的句柄传给函数,就可以定位光标的位置了
};
/*** 隐藏光标 ***/
void hide()
{
    CONSOLE_CURSOR_INFO cursor_info={1,0};/**定义光标信息结构体*///存储下面函数的返回值,高度是1,可见性是不可见;声明引用是必须对其进行初始化,所以给了初值
    SetConsoleCursorInfo(hout, &cursor_info);/**用来设置制定的控制台的光标的大小和可见性,参数是句柄和光标信息结构体的那个*///DWORD dwSize是高度,BOOL bVisible 是可见性
}
/*** 生成随机数 ***/
double random(double start, double end)
{//这是一个固定表达式,返回的是从start开始到end的有rand()函数长身的随机数
    return start+(end-start)*rand()/(RAND_MAX + 1.0);/**rand()是产生随机数的函数,但产生的其实是伪随机数,是有指定顺序的*///randmax是rand能返回的最大数值
}//为什么加的是1.0不是1呢,因为是double类型的,16位精度,float是8位
/*** 定义地图的长宽,蛇的坐标,长度,方向,食物的位置 ***/
int m,n;
struct node
{
    int x,y;
}snake[1000];
int snake_length,dir;//全局变量蛇身长度,dir是第几个direct,main里面是3,表示第一次输出蛇的时候是向右移动
node food;//node是上面声明的结构体。。。还查了半天。。。
int direct[4][2]={{-1,0},{1,0},{0,-1},{0,1}};/**向左上右下移动,只改变位置,不改变长度*/
/*** 输出墙 ***/
void print_wall()//墙的长宽都要输入,n是长,m是宽
{
    cout << " ";
    for (int i=1;i<=n;i++)//最上面的墙
        cout << "-";
    cout << endl;
    for (int j=0;j<=m-1;j++)//两边的墙
    {
        cout << "|";//输出的时候就是两个小的丨,换成中文也没用;
        for (int i=1;i<=n;i++) cout << " ";
        cout << "|" << endl;
    }
    cout << " ";//最下面的墙
    for (int i=1;i<=n;i++)
        cout << "-";
}
/*** 首次输出蛇,其中snake[0]代表头 ***/
void print_snake()
{
    locate(snake[0].x,snake[0].y);//最开始的函数,还不懂
    cout << "@";//蛇头
    for (int i=1;i<=snake_length-1;i++)
    {
        locate(snake[i].x,snake[i].y);
        cout << "*";//输出蛇身
    }
}
/*** 判断是否撞墙或者自撞 ***/
bool is_correct()
{
    if (snake[0].x==0 || snake[0].y==0 || snake[0].x==m+1 || snake[0].y==n+1) return false;//snake[0]是蛇头,撞墙,上,左,下,右,相等表示撞墙,死
    for (int i=1;i<=snake_length-1;i++)//到除了蛇头的所有蛇身
    {
        if (snake[0].x==snake[i].x && snake[0].y==snake[i].y) return false;//头的横坐标和任意一个蛇身的横坐标相等并且头的纵坐标和任何一个蛇身的纵坐标相等的话,自撞,死
    }
    return true;//没满足以上条件表明没有撞墙或者自撞,活
}
/*** 随机生成并输出食物位置 ***/
bool print_food()
{
    srand((unsigned)time(0));/**计算机是不会产生真正的随机数的,srand()是给rand()提供一个种子,由rand()根据种子来产生随机数,在stdlib.h头下*/
                             /**time()函数是返回系统时间的函数,返回类型是long int,从1970.1.1的0时0分0秒到现在的秒数,2038年1月18日19时14分07秒前,在time.h头里*/
                             /**(unsigned)time(0)是把time()函数返回值强转成unsigned类型,0是和NULL一样的,指返回的是数值不是指针*/
    bool e;
    while (1)
    {
        e=true;
        int i=(int) random(0,m)+1,j=(int) random(0,n)+1;/**random()是返回0到num-1之间的随机数,返回值是int型,在头stdlib.h下面,但是上面有定义,一开始不知道,还以为是系统的函数呢*///这里是指在长宽范围内长生随机数,+1是干什么???本来是double 所以要强转成int
        food.x=i;food.y=j;//产生的随机数作为食物的横纵坐标
        for (int k=0;k<=snake_length-1;k++)
        {
            if (snake[k].x==food.x && snake[k].y==food.y)//如果食物的横纵坐标和身体的某一个点的横纵坐标相同,返回false,跳出循环
            {
                e=false;break;
            }
        }
        if (e) break;
    }
    locate(food.x,food.y);//定位food的横纵坐标
    cout << "$";//输出食物
    return true;
}
/*** 蛇的前进 ***/
bool go_ahead()
{
    node temp;//node是上面定义的结构体,是蛇身的那个
    bool e=false;
    temp=snake[snake_length-1];//temp是蛇尾
    for (int i=snake_length-1;i>=1;i--)//把每一个蛇身赋值给他前一个,这样就使每一个蛇身都走上一个蛇身走过的路,最后就使都跟着蛇头走了
        snake[i]=snake[i-1];
    snake[0].x+=direct[dir][0];//direct是控制上下左右的,dir是控制全责direct里面的第几个;蛇头的横坐标加上方向位的横坐标赋给新的蛇头横坐标,【0】是指方向位横坐标
    snake[0].y+=direct[dir][1];//纵坐标是一样的,蛇头纵坐标加方向位纵坐标赋值给新的蛇头纵坐标;
    locate(snake[1].x,snake[1].y);//定位蛇身第一位
    cout << "*";//输出蛇身;
    /*** 吃到了食物 ***/
    if (snake[0].x==food.x && snake[0].y==food.y)//如果蛇头的横纵坐标和食物的横纵坐标相等表示吃到了食物
    {
        snake_length++;//蛇身长度+1
        e=true;
        snake[snake_length-1]=temp;//吃到了食物就把旧的蛇尾的走过的路径给新的蛇尾,让新的蛇尾和其他蛇身一样跟着蛇头走
    }
    /*** 输出此时蛇状态 ***/
    if (!e)//如果没吃到
    {
        locate(temp.x,temp.y);//定位蛇尾
        cout << " ";//把原来的*蛇尾换成空格输出,表示前进一个单位
    }
    else//吃到了
        print_food();//输出新的食物
    locate(snake[0].x,snake[0].y);//重新定位蛇头
    cout << "@";//重新输出蛇头
    /*** 如果自撞或者撞墙了 ***/
    if (!is_correct())
    {
        system("cls");//清屏
        cout << "你输了!" << endl << "Length: " << snake_length << endl;
        return false;
    }
    return true;
}
/*** 主函数 ***/
int main()
{
    cout << "--------------------贪吃蛇---------------------" << endl;
    cout << "请先输入两个数,表示地图大小.要求长宽均不小于10." << endl;
    cout << "请注意窗口大小,以免发生错位.建议将窗口调为最大." << endl;
    cout << "再选择难度.请在1-10中输入1个数,1最简单,10则最难" << endl;
    cout << "然后进入游戏画面,以方向键控制方向.祝你游戏愉快!" << endl;
    cout << "-----------------------------------------------" << endl;
    cin >> m >> n;
    if (m<10 || n<10 || m>25 || n>40)//游戏区域长宽不能小于10,不能大于25,40;
    {
        cout << "ERROR" << endl;
        system("pause");//系统调用pause指令,输出press any key to exit,等待用户按任意一个键返回;在stdlib.h头里面
        return 0;
    }
    int hard;//难度
    cin >> hard;
    if (hard<=0 || hard>100)//难度要0到100之间
    {
        cout << "ERROR" << endl;
        system("pause");
        return 0;
    }
    /*** 数据全部初始化,包括蛇长,位置,方向 ***/
    snake_length=5;//蛇的初始长度是5
    clock_t a,b;/**long int 类型,是clock()的返回值,指开启这个程序到调用这个函数之间CPU时钟计时单元数 */
    char ch;
    double hard_len;
    for (int i=0;i<=4;i++)//初始化第一个蛇的位置,蛇头是(0,4)蛇尾是(0,0)
    {
        snake[i].x=1;
        snake[i].y=5-i;
    }
    dir=3;//初始方向是向右
    /*** 输出初始地图,蛇与食物 ***/
    system("cls");/**执行控制台命令cls,作用是清屏,清除所有显示的信息*/
    //hide();//调用光标隐藏函数
    print_wall();//输出墙
    print_food();//输出食物
    print_snake();//输出蛇
    locate(m+2,0);//在墙的下面两行输出当前的长度,给now length定位的
    cout << "Now length: ";//输出当前长度
    /*** 开始游戏 ***/
    while (1)
    {
        /*** 难度随长度增加而提高 看不懂*/
        hard_len=(double)snake_length/(double) (m*n);
        /*** 调节时间,单位是ms看不懂*/
        a=clock();
        while (1)
        {
            b=clock();
            if (b-a>=(int)(400-30*hard)*(1-sqrt(hard_len))) break;/**sqrt是求平方根的函数,在math.h头里面*/
        }
        /*** 接受键盘输入的上下左右,并以此改变方向 ***/
        if (kbhit())/**kbhit()是检测当前是否有键盘输入的函数,在conio.h头里面*/
        {
            ch=getch();
            if (ch==-32)
            {
                ch=getch();
                switch(ch)
                {//就这么规定的,和键值37 38 39 40是不一样的
                case 72://上
                    if (dir==2 || dir==3)
                        dir=0;
                    break;
                case 80://下
                    if (dir==2 || dir==3)
                        dir=1;
                    break;
                case 75://左
                    if (dir==0 || dir==1)
                        dir=2;
                    break;
                case 77://右
                    if (dir==0 || dir==1)
                        dir=3;
                    break;
                }
            }
        }
        /*** 前进 ***/
        if (!go_ahead()) break;
        /*** 在最后输出此时长度 ***/
        locate(m+2,12);
        cout << snake_length;
    }
    system("pause");
    return 0;
}
下面是我自己改动的部分,基本上也没改什么

#include <iostream>
#include<windows.h>
#include<time.h>
#include<math.h>
#include<conio.h>
#include <cstdlib>
#include <cstdio>
using namespace std;

/**定位光标*/
HANDLE hout = GetStdHandle(STD_OUTPUT_HANDLE);
COORD coord;
void locate(int x,int y){
    coord.X=y;
    coord.Y=x;
    SetConsoleCursorPosition(hout,coord);
}

/**隐藏光标*/
void hide(){
    CONSOLE_CURSOR_INFO cursor_info = {1,0};
    SetConsoleCursorInfo(hout,&cursor_info);
}

/**生成随机数*/
double random(double start,double end){
    return start+(end-start)*rand()/(RAND_MAX+1.0);

}

/**地图的长宽,蛇的坐标,长度,方向,食物的位置*/
int m,n;
struct node{
    int x;
    int y;
}snake[1000];
int snake_length,dir;
node food;
int direct[4][2]={{-1,0},{1,0},{0,-1},{0,1}};

/**输出墙*/
void print_wall(int n,int m){
    cout<<" ";
    for(int i=0;i<n;i++){
        cout<<"-";
    }
    cout<<" "<<endl;
    for(int j=0;j<m;j++){
        cout<<"|";
        for(int k=0;k<n;k++){
            cout<<" ";
        }
        cout<<"|"<<endl;
    }
    cout<<" ";
    for(int i=0;i<n;i++){
        cout<<"-";
    }
}

/**首次输出蛇*/
void print_snake(){
    locate(snake[0].x,snake[0].y);
    cout<<"@";
    for(int i=1;i<=snake_length-1;i++){
            locate(snake[i].x,snake[i].y);
        cout<<"*";
    }
}

/**判断自撞以及撞墙*/
bool is_correct(){
    if(snake[0].x==0||snake[0].y==0||snake[0].x==21||snake[0].y==61){
        return false;
    }
    for(int i=1;i<=snake_length-1;i++){
        if(snake[0].x==snake[i].x&&snake[0].y==snake[i].y){
            return false;
        }
    }
    return true;
}

/**随机生成并输出食物*/
bool print_food(){
    srand((unsigned)time(0));
    bool e;
    while(1){
            e=true;
        int i=(int)random(0,20)+1,j=(int)random(0,60)+1;
        food.x=i;food.y=j;
        for(int k=0;k<=snake_length-1;k++){
            if(food.x==snake[k].x&&food.y==snake[k].y){
                e= false;
                break;
            }
        }
        if(e){
            break;
        }
    }
    locate(food.x,food.y);
    cout<<"$";
    return true;
}

void print_smileface(){
    locate(8,64);
     cout<<"  ********  "<<endl;
     locate(9,64);
    cout<<"*          *"<<endl;
    locate(10,64);
    cout<<"*  ^    ^  *"<<endl;
    locate(11,64);
    cout<<"*          *"<<endl;
    locate(12,64);
    cout<<"*    ˇ    *"<<endl;
    locate(13,64);
    cout<<"  ********  "<<endl;
    locate(14,66);
    cout<<"吃到了~"<<endl;
}
void print_face(){
  locate(8,64);
     cout<<"  ********  "<<endl;
     locate(9,64);
    cout<<"*          *"<<endl;
    locate(10,64);
    cout<<"*  *    *  *"<<endl;
    locate(11,64);
    cout<<"*          *"<<endl;
    locate(12,64);
    cout<<"*    *     *"<<endl;
    locate(13,64);
    cout<<"  ********  "<<endl;
    locate(14,66);

    cout<<"小心哦~"<<endl;
}
/**前进*/
bool go_ahead(){
    node temp;
    temp = snake[snake_length-1];
    bool e = false;
    for(int i=snake_length-1;i>=1;i--){
        snake[i]=snake[i-1];
    }
    snake[0].x=snake[0].x+direct[dir][0];
    snake[0].y=snake[0].y+direct[dir][1];
    locate(snake[1].x,snake[1].y);
    cout<<"*";
    /*如果吃到食物了*/
    if(snake[0].x==food.x&&snake[0].y==food.y){
        snake_length++;
        e = true;
        snake[snake_length-1]=temp;
    }
    /*输出此时蛇的状态*/
    if(!e){
        locate(temp.x,temp.y);
        cout<<" ";
        print_face();
    }
    else{
        print_food();
        print_smileface();
    }
    locate(snake[0].x,snake[0].y);
    cout<<"@";
    /*如果自撞或者撞墙了*/
    if(!is_correct()){
        system("cls");
        cout<<"你输了"<<endl;
        cout<<"最终长度是:"<<snake_length;
        return false;
    }
    return true;
}
void print_logo(){
    cout<<"**********   **       **        *        **           **********"<<endl;
    cout<<"**********   ***      **       ***       **      **   **********"<<endl;
    cout<<"**           ****     **      ** **      **    **     **        "<<endl;
    cout<<"**           ** **    **     **   **     **  **       **        "<<endl;
    cout<<"**********   **  **   **    **     **    ****         **********"<<endl;
    cout<<"**********   **   **  **    *********    ***          **********"<<endl;
    cout<<"        **   **    ** **    **     **    ** **        **        "<<endl;
    cout<<"        **   **     ****    **     **    **   **      **        "<<endl;
    cout<<"**********   **      ***   **       **   **     **    **********"<<endl;
    cout<<"**********   **       **  **         **  **       **  **********"<<endl;
    for(int i=1;i<65;i++){
        cout<<"-";
    }
cout<<endl;
    cout<<" * ** * "<<endl;
    cout<<"* .  . *"<<endl;
    cout<<"*      *"<<endl;
    cout<<"*   -  *"<<endl;
    cout<<" *    *     * *"<<endl;
    cout<<"   * *    * * * *        *"<<endl;
    cout<<"    * * * *    * * * * ** "<<endl;
    cout<<"     * * *       * * * *"<<endl;
    cout<<endl;
    locate(12,30);
    cout<<"游戏规则:按上下左右键控制蛇的移动"<<endl;
    locate(13,40);
    cout<<"每吃掉一个食物身体长长一节"<<endl;
    locate(14,40);
    cout<<"撞到墙或者自己的身体则游戏失败"<<endl;
    locate(15,40);
    cout<<"我们的目标是变大变长!"<<endl;
    locate(16,40);
    cout<<"请输入难度(1~100)开始游戏吧!"<<endl;
    cout<<endl;
}

/**主函数**/
int main(){
    print_logo();
    int hard;
    locate(17,40);
    cin>>hard;
    if(hard<1||hard>100){
        cout<<"游戏难度不得小于1不得大于100,请重新开始游戏"<<endl;
        system("pause");
        return 0;
    }
    snake_length=5;
    for(int i=0;i<5;i++){
        snake[i].x=1;
        snake[i].y=5-i;
    }
    dir=3;
    system("cls");
    hide();
    print_wall(60,20);
    print_food();
    print_snake();
    locate(3,62);
    cout<<"当前长度:";

    clock_t a,b;
    char ch;
    double hard_len;

    /**开始游戏*/
    while(1){
        hard_len=(double)snake_length/(double)(60*20);
        a=clock();
        while(1){
            b=clock();
            if(b-a>=(int)(400-30*hard)*(1-sqrt(hard_len))){
                break;
            }
        }
        /**键入上下左右*/
        if(kbhit()){
            ch=getch();
            if(ch==-32){
                ch=getch();
                switch(ch){
                case 72://上
                    if(dir==2||dir==3){
                        dir=0;
                    }
                    break;
                case 80:
                    if(dir==2||dir==3){
                        dir=1;
                    }
                    break;
                case 75:
                    if(dir==0||dir==1){
                        dir=2;
                    }
                    break;
                case 77:
                    if(dir==0||dir==1){
                        dir=3;
                    }
                    break;
                }
            }
        }
        if(!go_ahead()){
            break;
        }
        locate (3,73);
        cout<<snake_length<<endl;
    }
    system("pause");
    return 0;
}
今天也是收获满满的一天~


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值