C/C++贪吃蛇游戏

首先我讲一下我写该游戏的思路
1.界面设计
可以利用数字0,1,2,3,
用0表示边界,接触边界便会死亡
用1表示可移动的区域范围
用2表示蛇的身体(有需要的可以单独给蛇头设置其他数字)
用3表示食物
那么,我们就能用二位数组将界面给表示出来,这里创建一个全局变量

    int show[N][N]={
    {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
    {0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0},
    {0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0},
    {0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0},
    {0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0},
    {0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0},
    {0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0},
    {0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0},
    {0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0},
    {0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0},
    {0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0},
    {0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0},
    {0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0},
    {0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0},
    {0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0},
    {0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0},
    {0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0},
    {0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0},
    {0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0},
    {0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0},
    {0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0},
    {0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0},
    {0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0},
    {0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0},
    {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}
    };
    void menu(int a[][N])
    {
	    for(int i=0;i<N;i++)
	    {
	        for(int j=0;j<N;j++)
	        {
	            if(a[i][j]==0)
	            {
	                set_color(10);
	                cout <<"□";
	            }
	            if(a[i][j]==1)
	            {
	                set_color(9);
	                cout <<"■";
	            }
	            if(a[i][j]==2)
	            {
	                set_color(4);
	                cout <<"●";
	            }
	            if(a[i][j]==3)
	            {
	                set_color(14);
	                cout <<"★";
	            }
	
	         }
	        cout <<"\n";
	    }
    }

2.颜色函数与坐标函数

   // color(0);	    printf("黑色\n");
   // color(1); 	printf("蓝色\n");
   // color(2); 	printf("绿色\n");
   // color(3); 	printf("湖蓝色\n");
   // color(4);  	printf("红色\n");
   // color(5);  	printf("紫色\n");
   // color(6); 	printf("黄色\n");
   // color(7);  	printf("白色\n");
   // color(8);  	printf("灰色\n");
   // color(9); 	printf("淡蓝色\n");
   // color(10); 	printf("淡绿色\n");
   // color(11); 	printf("淡浅绿色\n");
   // color(12);    printf("淡红色\n");
   // color(13);  	printf("淡紫色\n");
   // color(14); 	printf("淡黄色\n");
   // color(15); 	printf("亮白色\n");
   // color(16);    //因为这里大于15,恢复默认的颜色


void set_color(int x)
{
    HANDLE winHandle;
    winHandle = GetStdHandle((STD_OUTPUT_HANDLE)) ;//用来修改命令行窗口的颜色
    SetConsoleTextAttribute(winHandle,x) ;
}

//坐标函数
void set_position(int x,int y)
{
        HANDLE winHandle;   //句柄
        COORD pos={x,y};        //定义一个位置
        winHandle=GetStdHandle(STD_OUTPUT_HANDLE);  //将控制台窗口赋值给定义的句柄
        SetConsoleCursorPosition(winHandle,pos);         //设置光标位置
}

3.存储蛇的信息
我采用的是链表的方式

typedef struct _snake
{
    int x;
    int y;
    struct _snake *next;
}Snake;

4.蛇的移动与显示
在给代码之前我讲下思路
利用键值
使用while()函数使得蛇能一直移动,除非给出另一个键值

key=getch();  //按下按键//119 上 115下 97左 100右   ASCII码值

当时我碰到了两个问题
(1)每次我按下键值后蛇只移动一下,如果我让它一直移动的话就会无法接收我输入的下一个命令
解决:查阅一些资料后,我学到了一个非常适合这种情况的函数kbhit(),只要不操作就为假,只要按了按键就为真
头文件为:#include <conio.h>

        if(kbhit())
        {
            key=getch();
        }

(2)要实现蛇往下之后就不能在往上走,往左走之后就不能往右走,于是我设置了char key2来代表上一个输入的键值,但是还是无法实现想要的效果,它会中途暂停,然后在走就不按照我的想法
解决:首先将先前key赋值给key2,然后重新给key赋值

        if(kbhit())
        {
            key2=key;
            key=getch();
        }        

如果重新输入的值与上次相反,既先上后下,先左后右,先下后上,先右后左,这些都是要不操作的,可以运行以下代码

            key=key2;
            continue;

5.其他函数
比如,
触碰边界
触碰本身
吃下食物
显示分数以及其他数据

全部代码:

没有写很多注释,又不懂的可以参考链表的增删改查操作,万变不离其中,只要能实现功能就行

#include <iostream>
#include <windows.h>
#include <mmsystem.h>
#pragma comment(lib,"Winmm.lib")
#define N 25        //定义游戏边界
#include <time.h>
#include <strings.h>
#include <conio.h>
using namespace std;

int score;      //得分
int longs=3;      //蛇的长度
int c,d;        //食物坐标
char key,key2;       //移动方向
//颜色函数

   // color(0);	    printf("黑色\n");
   // color(1); 	printf("蓝色\n");
   // color(2); 	printf("绿色\n");
   // color(3); 	printf("湖蓝色\n");
   // color(4);  	printf("红色\n");
   // color(5);  	printf("紫色\n");
   // color(6); 	printf("黄色\n");
   // color(7);  	printf("白色\n");
   // color(8);  	printf("灰色\n");
   // color(9); 	printf("淡蓝色\n");
   // color(10); 	printf("淡绿色\n");
   // color(11); 	printf("淡浅绿色\n");
   // color(12);    printf("淡红色\n");
   // color(13);  	printf("淡紫色\n");
   // color(14); 	printf("淡黄色\n");
   // color(15); 	printf("亮白色\n");
   // color(16);    //因为这里大于15,恢复默认的颜色


void set_color(int x)
{
    HANDLE winHandle;
    winHandle = GetStdHandle((STD_OUTPUT_HANDLE)) ;//用来修改命令行窗口的颜色
    SetConsoleTextAttribute(winHandle,x) ;
}

//坐标函数
void set_position(int x,int y)
{
        HANDLE winHandle;   //句柄
        COORD pos={x,y};        //定义一个位置
        winHandle=GetStdHandle(STD_OUTPUT_HANDLE);  //将控制台窗口赋值给定义的句柄
        SetConsoleCursorPosition(winHandle,pos);         //设置光标位置
}

typedef struct _snake
{
    int x;
    int y;
    struct _snake *next;
}Snake;

//界面函数
//定义数组,用0表示边界,1表示背景,2表示蛇本体,3表示食物
void menu(int a[][N])
{

    set_position(0,0);
    for(int i=0;i<N;i++)
    {
        for(int j=0;j<N;j++)
        {
            if(a[i][j]==0)
            {
                set_color(10);
                cout <<"□";
            }
            if(a[i][j]==1)
            {
                set_color(9);
                cout <<"■";
            }
            if(a[i][j]==2)
            {
                set_color(4);
                cout <<"●";
            }
            if(a[i][j]==3)
            {
                set_color(14);
                cout <<"★";
            }

         }
        cout <<"\n";
    }
    set_position(62,10);
    set_color(5);
    cout <<score;
    set_position(0,0);

}
    //界面数组
    int show[N][N]={
    {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
    {0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0},
    {0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0},
    {0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0},
    {0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0},
    {0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0},
    {0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0},
    {0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0},
    {0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0},
    {0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0},
    {0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0},
    {0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0},
    {0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0},
    {0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0},
    {0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0},
    {0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0},
    {0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0},
    {0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0},
    {0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0},
    {0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0},
    {0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0},
    {0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0},
    {0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0},
    {0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0},
    {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}
    };
//游戏内容界面数组
void imformation()
{
    set_position(55,1);
    set_color(4);
    cout <<"游戏名称:吞星蟒之路";
    set_position(55,5);
    set_color(6);
    cout <<"W、S、A、D控制上下左右移动";
    set_position(55,10);
    set_color(5);
    cout <<"分数:";
}
//蛇碰壁结束函数
void death(Snake *head)
{
    if(head->x==0||head->x==24||head->y==0||head->y==24)
        {
            set_position(55,15);
            set_color(4);
            cout <<"游戏结束!得分"<<score<<"分";
            set_position(55,26);
            exit(0);
        }
}
//蛇吃到自己
void eat_self(Snake *head)
{
    Snake *p;
    p=head->next;
    for(int i=0;i<longs-1;i++)
    {
        if(p->x==head->x&&p->y==head->y)
        {
            set_position(55,15);
            set_color(4);
            cout <<"游戏结束!得分"<<score<<"分";
            set_position(55,26);
            exit(0);
        }
        p=p->next;
    }
}

//吃下食物
void eats(Snake *head)
{
    srand((unsigned)time(NULL));
    Snake *p,*q;
    if(head->x==c&&head->y==d)
    {

        score+=10;
        p=head;
        for(int i=0;i<longs-1;i++)
        {
            p=p->next;
            if(p->next==NULL)
            {
                if(key==119)
                {
                    q=new Snake;
                    q->x=p->x+1;
                    q->y=p->y;
                    q->next=NULL;
                    p->next=q;
                    p=q;
                    show[p->x][p->y]=2;

                }
                else if(key==115)
                {
                    q=new Snake;
                    q->x=p->x-1;
                    q->y=p->y;
                    q->next=NULL;
                    p->next=q;
                    p=q;
                    show[p->x][p->y]=2;
                }
                else if(key==97)
                {
                    q=new Snake;
                    q->x=p->x;
                    q->y=p->y+1;
                    q->next=NULL;
                    p->next=q;
                    p=q;
                    show[p->x][p->y]=2;
                }
                else if(key==100)
                {
                    q=new Snake;
                    q->x=p->x;
                    q->y=p->y-1;
                    q->next=NULL;
                    p->next=q;
                    p=q;
                    show[p->x][p->y]=2;
                }
            }
        }
        longs++;
        c=rand()%22+1;
        d=rand()%22+1;
        while(c==head->x&&d==head->y)
        {
            c=rand()%22+1;
            d=rand()%22+1;
        }
        show[c][d]=3;

    }
}

//蛇的移动
void moves(Snake *head)
{
    PlaySound("four.wav",NULL, SND_FILENAME | SND_ASYNC|SND_LOOP);     //背景音乐循环播放
    while(key!= 0x11b)
    {
        eats(head);
        death(head);
        Snake *p,*q,*t;
        if(kbhit())
        {
            key2=key;
            key=getch();
        }

        else if(key==119&&key2!=115)
        {
            t=head;
            p=head->next;
            q=new Snake;
            q->x=head->x-1;
            q->y=head->y;
            show[q->x][q->y]=2;
            q->next=head;
            head=q;
            for(int i=0;i<longs+1;i++)
            {
                if(!p->next)
                {
                    show[p->x][p->y]=1;
                    t->next=NULL;


                }
                else
                    {
                        p=p->next;
                        t=t->next;
                    }

            }
            menu(show);
            Sleep(100);		//控制速度
            eat_self(head);


        }
        else if(key==115&&key2!=119)
        {

            q=new Snake;
            q->x=head->x+1;
            q->y=head->y;
            show[q->x][q->y]=2;
            q->next=head;
            head=q;
            p=head->next;
            t=head;
            for(int i=0;i<longs+1;i++)
            {
                if(!p->next)
                {
                    show[p->x][p->y]=1;
                    t->next=NULL;


                }
                else
                    {
                        p=p->next;
                        t=t->next;
                    }

            }
            menu(show);
            Sleep(100);

        }
        else if(key==97&&key2!=100)
        {

            q=new Snake;
            q->x=head->x;
            q->y=head->y-1;
            show[q->x][q->y]=2;
            q->next=head;
            head=q;
            p=head->next;
            t=head;
            for(int i=0;i<longs+1;i++)
            {
                if(!p->next)
                {
                    show[p->x][p->y]=1;
                    t->next=NULL;


                }
                else
                    {
                        p=p->next;
                        t=t->next;
                    }

            }
            menu(show);
            Sleep(100);

        }
        else if(key==100&&key2!=97)
        {

            q=new Snake;
            q->x=head->x;
            q->y=head->y+1;
            show[q->x][q->y]=2;
            q->next=head;
            head=q;
            p=head->next;
            t=head;
            for(int i=0;i<longs+1;i++)
            {
                if(!p->next)
                {
                    show[p->x][p->y]=1;
                    t->next=NULL;


                }
                else
                    {
                        p=p->next;
                        t=t->next;
                    }

            }
            menu(show);
            Sleep(100);

        }
        else
        {
            key=key2;
            continue;
        }

    }
}


int main()
{
    int a,b;    //定义产生的随机数,确定食物以及蛇坐标

    SetConsoleTitle("吞星蟒之路");

    srand((unsigned)time(NULL));    //产生2个随机数
    a=rand()%22+1;
    b=rand()%18+3;
    c=rand()%22+1;
    d=rand()%22+1;
    while((a==c&&b==d)||(a==c&&b==d-1)||(a==c&&b==d-2))
    {
        c=rand()%22+1;
        d=rand()%22+1;
    }
    show[c][d]=3;       //食物初始位置

    Snake *head,*p,*last;       //定义蛇链表的头指针,普通指针,尾指针
    head =new Snake;
    head=NULL;
    last=head;

    for(int i=0;i<longs;i++)
    {
        p=new Snake;
        p->x=a;
        p->y=b-i;
        p->next=NULL;
        if(!head)
            head=p;
        else
            last->next=p;
        last=p;
        show[last->x][last->y]=2;

    }
    menu(show);
    imformation();
    key=getch();  //按下按键//119 115 97 100   ASCII码值
    key2 ='g';

    moves(head);

}

部分截图
在这里插入图片描述
背景音乐如果有问题可以看我的这篇博客
C++语言写养成类游戏

posted @ 2019-06-04 22:50  h云淡风轻  阅读(15)  评论(0编辑  收藏  举报  来源