C++手打游戏--<<贪吃蛇>>讲解

其实这并不是很难。。。只是时间问题
纯属无聊—–
基本思路: 开一个地图数组不断更新蛇的位置,记录蛇的头坐标与尾坐标…
然后怎么解决蛇的身体是怎么”扭”的呢?
也不是很难。。。
只需学习并查集的思路即可,每个身体节点都指向他前一个身体,即这个节点处保存了他前一个节点的相对位置,如在左边(LEFT) 在右边(RIGHT) 在上面(UP) 在下面(DOWN)

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<windows.h>
#include<conio.h>
#include<iostream>
#include<ctime>
#define LEFT 1
#define RIGHT 2
#define UP 3
#define DOWN 4
#define FOODMAX -2
#define FOOD -1
#define F 100000
#define MMM 707070 //乱打的标记数 怪物占位数
#define AMMO 503853  //BOSS子弹占位数
#define PYS 392002   //蛇子弹占位数
#define KIND int
#define IN_map(x,y) 1<=x && x<=m && 1<=y && y<=n 
using namespace std;
int map[1000][1000],map_t[1000][1000];
int flag=0,ma_flag=0;
int n=50,m=30,foodn=0,e=0; 
struct pos
{
    int x,y;
};
struct SKILL
{
    char key;
    char file[100];
    int num;
}list[1000];
pos maste;
class Snake
{
    public:pos head,end;
    public:int boss;
    public:int len,fx,ex;
    public:void spawn(int x,int y) //生成蛇
    {
        map[x][y]=F;
        ex=0;
        this->fx=RIGHT;
        this->len=0;
        this->head.x=x,this->head.y=y;
        this->end.x=x,this->end.y=y;
        return;
    }
    public:void move() //蛇的移动
    {
        int gg=1;
        if(fx==UP)
        {
            if(map[this->head.x-1][this->head.y]!=0 && map[this->head.x-1][this->head.y]!=FOOD) flag=1;
            else if(map[this->head.x-1][this->head.y]==FOOD) {foodn--;gg=0;}
            map[this->head.x-1][this->head.y]=F; //F是指头
            map[this->head.x][this->head.y]=UP;
            this->head.x-=1;
        }
        if(fx==DOWN)
        {
            if(map[this->head.x+1][this->head.y]!=0 && map[this->head.x+1][this->head.y]!=FOOD) flag=1;
            else if(map[this->head.x+1][this->head.y]==FOOD) {foodn--;gg=0;}
            map[this->head.x+1][this->head.y]=F;
            map[this->head.x][this->head.y]=DOWN;
            this->head.x+=1;
        }
        if(fx==LEFT)
        {
            if(map[this->head.x][this->head.y-1]!=0 && map[this->head.x][this->head.y-1]!=FOOD) flag=1;
            else if(map[this->head.x][this->head.y-1]==FOOD) {foodn--;gg=0;}
            map[this->head.x][this->head.y-1]=F;
            map[this->head.x][this->head.y]=LEFT;
            this->head.y-=1;
        }
        if(fx==RIGHT)
        {
            if(map[this->head.x][this->head.y+1]!=0 && map[this->head.x][this->head.y+1]!=FOOD) flag=1;
            else if(map[this->head.x][this->head.y+1]==FOOD) {foodn--;gg=0;}
            map[this->head.x][this->head.y+1]=F;
            map[this->head.x][this->head.y]=RIGHT;
            this->head.y+=1;
        }
        if(gg==1 && !this->ex) //这里是指如果吃到FOOD那么就不删除尾节点,与将头结点向前移一位结合,就形成了增长的效果
        {
            int tx=this->end.x,ty=this->end.y;
            if(map[tx][ty]==UP) this->end.x-=1;
            if(map[tx][ty]==DOWN) this->end.x+=1;
            if(map[tx][ty]==LEFT) this->end.y-=1;
            if(map[tx][ty]==RIGHT) this->end.y+=1;
            map[tx][ty]=0;
            return;
        }
        this->len++; 
        return;
    }
};
class Ammo //空格发射子弹
{
    public:pos state;
    public:KIND Cmd;
    public:int fx,step,alive;
    Ammo()
    {
        this->alive=0;
    }
    public:void create(int x,int y,KIND arg)
    {
        if(map[x][y]!=0) return;
        map[x][y]=Cmd;
        this->state.x=x;
        this->Cmd=arg;
        this->state.y=y;
        this->alive=1;
        return;
    }
    public:void shoot()
    {
        if(this->fx==UP) 
        {
            if(map[this->state.x-1][this->state.y]==F) flag=1;
            if(map[this->state.x-1][this->state.y]!=0 && !(map[this->state.x-1][this->state.y]==AMMO)){/*map[this->state.x][this->state.y]=0*/;this->alive=0;return;}
            if(this->state.x-1<=1 || this->state.x-1>=m || this->state.y<=1 || this->state.y>=n){/*map[this->state.x][this->state.y]=0*/;this->alive=0;return;}
            map[this->state.x-1][this->state.y]=Cmd;
            map[this->state.x][this->state.y]=0;
            state.x-=1;
        }
        else if(this->fx==DOWN) 
        {
            if(map[this->state.x+1][this->state.y]==F) flag=1;
            if(map[this->state.x+1][this->state.y]!=0 && !(map[this->state.x+1][this->state.y]==AMMO)){/*map[this->state.x][this->state.y]=0*/;this->alive=0;return;}
            if(this->state.x+1<=1 || this->state.x+1>=m || this->state.y<=1 || this->state.y>=n){/*map[this->state.x][this->state.y]=0*/;this->alive=0;return;}
            map[this->state.x+1][this->state.y]=Cmd;
            map[this->state.x][this->state.y]=0;
            state.x+=1;
        }
        else if(this->fx==LEFT) 
        {
            if(map[this->state.x][this->state.y-1]==F) flag=1;
            if(map[this->state.x][this->state.y-1]!=0 && !(map[this->state.x][this->state.y-1]==AMMO)){/*map[this->state.x][this->state.y]=0;*/this->alive=0;return;}
            if(this->state.x<=1 || this->state.x>=m || this->state.y-2<=1 || this->state.y-2>=n){/*map[this->state.x][this->state.y]=0;*/this->alive=0;return;}
            map[this->state.x][this->state.y-1]=Cmd;
            map[this->state.x][this->state.y]=0;
            state.y-=1;
        }
        else if(this->fx==RIGHT) 
        {
            if(map[this->state.x][this->state.y+1]==F) flag=1;
            if(map[this->state.x][this->state.y+1]!=0 && !(map[this->state.x][this->state.y+1]==AMMO)){/*map[this->state.x][this->state.y]=0*/;this->alive=0;return;}
            if(this->state.x<=1 || this->state.x>=m || this->state.y+2<=1 || this->state.y+2>=n){/*map[this->state.x][this->state.y]=0*/;this->alive=0;return;}
            map[this->state.x][this->state.y+1]=Cmd;
            map[this->state.x][this->state.y]=0;
            state.y+=1;
        }
        return;
    }  
};
void hide()
{
    ShowCursor(false);
    HANDLE hOut=GetStdHandle(STD_OUTPUT_HANDLE);
    CONSOLE_CURSOR_INFO cci;
    GetConsoleCursorInfo(hOut,&cci);
    cci.bVisible=false;
    SetConsoleCursorInfo(hOut,&cci);
}
void init() //不必在意
{
    FILE *fp=fopen("install.info","r");
    if(fp==NULL) return;
    char str[100],kk;
    int ns=0,conts=0;
    while(~fscanf(fp,"%d %c %s",&ns,&kk,&str) && conts<100)
    {
        conts++;
        list[++e].num=ns;
        list[e].key=kk;
        strcat(list[e].file,str);
    }
    for(int i=1;i<=e;i++,Sleep(100))
        printf("Get Plugin:%d %c %s\n",list[i].num,list[i].key,list[i].file);
    system("cls");
}
void cls() //清屏
{
    ShowCursor(false);
    HANDLE hOut=GetStdHandle(STD_OUTPUT_HANDLE);
    CONSOLE_CURSOR_INFO cci;
    SetConsoleCursorPosition(hOut,(COORD){0,0});
}
void draw(int score,int x,int y) //显示图
{
    for(int i=1;i<=m;i++)
    {
        for(int j=1;j<=n;j++)
        {
            if(i==1 || j==1 || i==m || j==n) printf("#");
            else if(map[i][j]==0) printf(" ");
            else if(map[i][j]!=0)
            {
                if(map[i][j]==F) printf("@");
                else if(1<=map[i][j] && map[i][j]<=4) printf("*");
                else if(map[i][j]==FOOD) printf("X");
                else if(map[i][j]==MMM) printf("O");
                else if(map[i][j]==AMMO) printf("$");
                else if(map[i][j]==PYS) printf("K");
            }
        }
        puts("");
    }       
    printf("    score:%d\n",score);
    printf("    X:%d    Y:%d\n",x,y);
    return ;
}
void spawn() //生成怪物
{
    if(ma_flag==1) return;
    int tx=rand()%m,ty=rand()%n;
    if(map[tx][ty]==0 && 3<tx && tx<m-3 && 3<ty && ty<n-3)
    {
        if(map[tx+1][ty-1]==0 && map[tx+1][ty]==0 && map[tx+1][ty+1]==0 && map[tx][ty-1]==0 && map[tx][ty]==0 && map[tx][ty+1]==0 && map[tx-1][ty-1]==0 && map[tx-1][ty]==0 && map[tx-1][ty+1]==0)
        {
            maste.x=tx;
            maste.y=ty;
            ma_flag=1;
            map[maste.x+1][maste.y-1]=map[maste.x+1][maste.y]=map[maste.x+1][maste.y+1]=MMM;
            map[maste.x][maste.y-1]=map[maste.x][maste.y]=map[maste.x][maste.y+1]=MMM;
            map[maste.x-1][maste.y-1]=map[maste.x-1][maste.y]=map[maste.x-1][maste.y+1]=MMM;
        }
    }
}
void boss(int num) //不必在意
{
    //cout<<list[num].num;
    int ans=list[num].num,s=1;
    while(s<=ans)
    {
        char sss[100];
        memcpy(sss,list[num].file,sizeof(list[num].file));
        char sg,ta[10];
        sg=s+'0';
        ta[0]=sg,ta[1]='\0';
        strcat(sss,ta);
        Sleep(50);
        FILE *fp=fopen(sss,"r");
        if(fp==NULL) return;
        for(int i=1;i<=m;i++)
            for(int j=1;j<=n;j++)
            {
                char pos;
                fscanf(fp,"%c",&pos);
                if(pos=='\n'){j--;continue;}
                map_t[i][j]=(int)(pos-'0');
            }
        for(int i=1;i<=m;i++)
        {
            for(int j=1;j<=n;j++)
            {
                if(map_t[i][j]==1) printf("*");
                else printf(" ");
                if(map[i][j]==MMM)
                {
                    map[i][j]=0;
                    ma_flag=0;
                }
                if(map[i][j]==AMMO) map[i][j]=0;
                if(map[i][j]==PYS) map[i][j]=0;
            }
            puts("");
        }           
        s++;
        fclose(fp);
        cls();
    } 
}
void ma_move(Snake *s) //怪物向S移动
{
    if(ma_flag)
    {
        int a=maste.x,b=maste.y;
        if(s->head.x-a>0) //向下
        {
            maste.x+=1;
            map[a-1][b-1]=map[a-1][b]=map[a-1][b+1]=0;
            if(map[a+2][b-1]!=0 || map[a+2][b]!=0 || map[a+2][b+1]!=0) {ma_flag=0;goto s;}
            map[a+2][b-1]=map[a+2][b]=map[a+2][b+1]=MMM;
        } 
        else if(s->head.y-b>0) //向右 -=
        {
            maste.y+=1;
            map[a-1][b-1]=map[a][b-1]=map[a+1][b-1]=0;
            if(map[a-1][b+2]!=0 || map[a][b+2]!=0 || map[a+1][b+2]!=0) {ma_flag=0;goto s;}
            map[a-1][b+2]=map[a][b+2]=map[a+1][b+2]=MMM;
        } 
        else if(s->head.x-a<0) //向上
        {
            maste.x-=1;
            map[a+1][b-1]=map[a+1][b]=map[a+1][b+1]=0;
            if(map[a-2][b-1]!=0 || map[a-2][b]!=0 || map[a-2][b+1]!=0) {ma_flag=0;goto s;}
            map[a-2][b-1]=map[a-2][b]=map[a-2][b+1]=MMM;
        } 
        else if(s->head.y-b<0) //向左 --BUG
        {
            maste.y-=1; 
            map[a-1][b+1]=map[a][b+1]=map[a+1][b+1]=0;
            if(map[a-1][b-2]!=0 || map[a][b-2]!=0 || map[a+1][b-2]!=0) {ma_flag=0;goto s;}
            map[a-1][b-2]=map[a][b-2]=map[a+1][b-2]=MMM;
        } 
        s:
        if(ma_flag==0) //撞到东西怪物死亡
        {
            for(int i=1;i<=m;i++)
                for(int j=1;j<=n;j++)
                    if(map[i][j]==MMM) map[i][j]=0;
        }
    }
}
int play_1() //主进程
{
    cls();
    Snake player_1;
    player_1.spawn(m/2,n/2); //出生
    int scor=0;
    player_1.move(); //移动
    draw(scor,player_1.head.x,player_1.head.y);
    int zh=0;
    Ammo skill[20];
    Ammo py[30];
    int ammonum=0;
    int ff=0;
    while(flag==0 && (1<=player_1.head.x && player_1.head.x<=m && 1<=player_1.head.y && player_1.head.y<=n)) //如果没死且没撞墙
    {
        Sleep(10);//调节速度,也可去掉
        player_1.boss=0; //毫无意义的东西
        int ggg=0,ggk=0; //标记是否还有子弹存在
        for(int i=1;i<=5;i++)
            if(py[i].alive==1)
            {
                py[i].shoot(); //移动子弹
                ggk=1;
            }
        for(int i=1;i<=12;i++)
            if(skill[i].alive==1)
            {
                skill[i].shoot();
                ggg=1;
            }       
        zh++;
        cls();
        if(kbhit())
        {
            char cmd=getch();
            for(int i=1;i<=e;i++)
                if(cmd==list[i].key)
                    boss(i);
            switch(cmd) //按键
            {
                case 'W': 
                case 'w':
                    if(player_1.fx==UP || player_1.fx==DOWN) break;
                    player_1.fx=UP; //更新方向
                    break;
                case 'A': 
                case 'a':
                    if(player_1.fx==RIGHT || player_1.fx==LEFT) break;
                    player_1.fx=LEFT;
                    break;
                case 'D':
                case 'd':
                    if(player_1.fx==RIGHT || player_1.fx==LEFT) break;
                    player_1.fx=RIGHT;
                    break;
                case 'S':
                case 's':
                    if(player_1.fx==UP || player_1.fx==DOWN) break;
                    player_1.fx=DOWN;
                    break;
                case ' ': //放子弹
                    player_1.boss=1;
                    break;
                case 'g': //开挂
                    if(player_1.ex==0) player_1.ex=1;
                    else player_1.ex=0;
                    break;
                case 'n':
                    if(!ff) ff=1;
                    else ff=0;
                    break;
                default:    
                    break;
            }
        }
        if(foodn<=0) //如果没有FOOD,则生成
            while(1)
            {
                int x=rand()%m,y=rand()%n;
                if(map[x][y]==0 && 1<x && x<m && 1<y && y<n)
                {
                    map[x][y]=FOOD;
                    foodn++;
                    scor++;
                    break;
                }
            }
        if(player_1.boss && !ggk) //放子弹
        {
            int bornx,borny;
            py[1].fx=player_1.fx;
            py[2].fx=player_1.fx;
            py[3].fx=player_1.fx;
            if(player_1.fx==LEFT)
            {
                bornx=player_1.head.x;
                borny=player_1.head.y-2;
                py[1].create(bornx-1,borny,PYS);
                py[2].create(bornx,borny,PYS);
                py[3].create(bornx+1,borny,PYS);
            }
            else if(player_1.fx==RIGHT)
            {
                bornx=player_1.head.x;
                borny=player_1.head.y+2;
                py[1].create(bornx-1,borny,PYS);
                py[2].create(bornx,borny,PYS);
                py[3].create(bornx+1,borny,PYS);
            }
            else if(player_1.fx==UP)
            {
                bornx=player_1.head.x-2;
                borny=player_1.head.y;
                py[1].create(bornx,borny-1,PYS);
                py[2].create(bornx,borny,PYS);
                py[3].create(bornx,borny+1,PYS);
            }
            else if(player_1.fx==DOWN)
            {
                bornx=player_1.head.x+2;
                borny=player_1.head.y;
                py[1].create(bornx,borny-1,PYS);
                py[2].create(bornx,borny,PYS);
                py[3].create(bornx,borny+1,PYS);
            }
            player_1.boss=0;
        }
        if(player_1.len>=10 && !ma_flag && !ff){ spawn();scor+=20;} //生成怪物
        if(zh%5==0 && ma_flag) ma_move(&player_1); //移动BOSS
        int sk=rand()%10;
        if(sk<5 && !ggg && ma_flag && !ff) //怪物放子弹
        {
            skill[1].create(maste.x+4,maste.y-1,AMMO);
            skill[1].fx=DOWN;
            skill[2].create(maste.x+4,maste.y,AMMO);
            skill[2].fx=DOWN;
            skill[3].create(maste.x+4,maste.y+1,AMMO);
            skill[3].fx=DOWN;
            skill[4].create(maste.x-4,maste.y-1,AMMO);
            skill[4].fx=UP;
            skill[5].create(maste.x-4,maste.y,AMMO);
            skill[5].fx=UP;
            skill[6].create(maste.x-4,maste.y+1,AMMO);
            skill[6].fx=UP;
            skill[7].create(maste.x-1,maste.y+4,AMMO);
            skill[7].fx=RIGHT;
            skill[8].create(maste.x,maste.y+4,AMMO);
            skill[8].fx=RIGHT;
            skill[9].create(maste.x+1,maste.y+4,AMMO);
            skill[9].fx=RIGHT;
            skill[10].create(maste.x-1,maste.y-4,AMMO);
            skill[10].fx=LEFT;
            skill[11].create(maste.x,maste.y-4,AMMO);
            skill[11].fx=LEFT;
            skill[12].create(maste.x+1,maste.y-4,AMMO);
            skill[12].fx=LEFT;
        }
        player_1.move();
        draw(scor,player_1.head.x,player_1.head.y); //显示地图
        zh%=100000007;
    }
    system("cls");
    printf("            LOSE!!!!\n          Again\n");
    getchar();
    system("cls");
    player_1.len=0;
    ma_flag=0;
    return 0;
}
int play_2() //同上,只是多一个人
{
    cls();
    Snake player_1,player_2;
    player_1.spawn(m/2,n/2);
    player_1.move();
    player_2.spawn(10,10);
    player_2.move();
    draw(0,player_1.head.x,player_1.head.y);
    int zh=0;
    while(flag==0 && (1<=player_1.head.x && player_1.head.x<=m && 1<=player_1.head.y && player_1.head.y<=n) && (1<=player_2.head.x && player_2.head.x<=m && 1<=player_2.head.y && player_2.head.y<=n))
    {
        zh++;
        Sleep(10);
        cls();
        if(kbhit())
        {
            char cmd=getch();
            switch(cmd)
            {
                case 'W': 
                case 'w':
                    if(player_1.fx==UP || player_1.fx==DOWN) break;
                    player_1.fx=UP;
                    break;
                case '5':
                    if(player_2.fx==UP || player_2.fx==DOWN) break;
                    player_2.fx=UP;
                    break;
                case 'A': 
                case 'a':
                    if(player_1.fx==RIGHT || player_1.fx==LEFT) break;
                    player_1.fx=LEFT;
                    break;
                case '1':
                    if(player_2.fx==RIGHT || player_2.fx==LEFT) break;
                    player_2.fx=LEFT;
                    break;
                case 'D':
                case 'd':
                    if(player_1.fx==RIGHT || player_1.fx==LEFT) break;
                    player_1.fx=RIGHT;
                    break;
                case '3':
                    if(player_2.fx==RIGHT || player_2.fx==LEFT) break;
                    player_2.fx=RIGHT;
                    break;
                case 'S':
                case 's':
                    if(player_1.fx==UP || player_1.fx==DOWN) break;
                    player_1.fx=DOWN;
                    break;
                case '2':
                    if(player_2.fx==UP || player_2.fx==DOWN) break;
                    player_2.fx=DOWN;
                    break;
                case 'g':
                    if(player_1.ex==0) player_1.ex=1;
                    else player_1.ex=0;
                    break;
                case '9':
                    if(player_2.ex==0) player_2.ex=1;
                    else player_2.ex=0;
                    break;
                default:    
                    break;
            }
        }
        if(foodn<=0)
            while(1)
            {
                int x=rand()%m,y=rand()%n;
                if(map[x][y]==0 && 1<x && x<m && 1<y && y<n)
                {
                    map[x][y]=FOOD;
                    foodn++;
                    break;
                }
            }
        if(player_1.len>=20 || player_2.len>=20) spawn();
        if(zh%177==0) ma_move(&player_1);
        if(zh%13==0) ma_move(&player_2);
        player_1.move();
        player_2.move();
        draw(0,player_1.head.x,player_1.head.y);
        zh%=100000007;
    }
    system("cls");
    printf("            LOSE!!!!\n          Again\n");
    getchar();
    system("cls");
    player_1.len=0;
    player_2.len=0;
    ma_flag=0;
    return 0;
}
int menu()
{
    printf("        *****************************************\n");
    printf("        *            The Snack Game             *\n");
    printf("        *    -To Commemorate LSZ Who Has Gone   *\n");
    printf("        *    1.Play now 1 player                *\n");
    printf("        *                                       *\n");
    printf("        *    2.Play now 2 player                *\n");
    printf("        *                                       *\n");
    printf("        *    3.Help                             *\n");
    printf("        *                                       *\n");
    printf("        *    4.Change Color                     *\n");
    printf("        *                                       *\n");
    printf("        *****************************************\n");
    printf("        Please Input:");
}
int main()
{
    int i,j,k,m,n;
    hide();
    srand(time(0));
    while(1)
    {
        system("cls");
        init();
        menu();
        char c;
        scanf("%c",&c);
        if(c=='1')
            while(1)
            {
                system("cls");
                foodn=0;
                flag=0;
                play_1();
                memset(map,0,sizeof(map));
            }
        if(c=='2')
            while(1)
            {
                system("cls");
                foodn=0;
                flag=0;
                play_2();
                memset(map,0,sizeof(map));
            }
        else if(c=='3')
        {
            system("cls");
            printf("    There Is Noting For Help!!!!!\n");
            printf("    You Don Not 贪吃蛇?????\n");
            printf("    You Kidding me????      'a' to LEFT 'd' to RIGHT 'w' to UP 's' to DOWN!\n"); 
            printf("        *:The Snack\n");
            printf("        @:The Head\n");
            printf("    X:The Food\n");
            printf("    #:The Wall\n");
            getchar();
            getchar();
        }
        else if(c=='4')
        {
            char c='0',c2='0';
            int arg=rand()%7;
            int arg2=rand()%7;
            c=c+arg;c2=c2+arg2;
            char ss[2];
            ss[0]=c,ss[1]=c2;
            ss[2]='\0';
            char sss[100]="color ";
            strcat(sss,ss);
            system(sss);
        }
    }
    return 0;
}

总体来说太水太水太水太水太水太水太水太水太水太水太水太水。。。。。。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值