c语言控制台贪吃蛇的实现

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

文章目录


前言


一、源码

无聊心血来潮写了个控制台的贪吃蛇,正常能玩。当然隐藏bug也有很多,比如食物位置与蛇身重合的情况判定,这里没有去实现了,如果感兴趣可以自己添加一下这部分功能。另外代码写的很烂勿喷,都是临时想到什么逻辑就写什么,没花啥时间去优化。总而言之参考学习的话可能没啥帮助,临时用来应付作业应该没问题。

#include <stdio.h>
#include <conio.h>
#include <unistd.h>
#include <pthread.h>
#include <stdlib.h>
int map[20][20]={0};
int Score=0;

struct snack{
    int x;
    int y;
    int pre_x;
    int pre_y;
    int direc;
    struct snack *tail;
    struct snack *pre;
};

struct food{
    int x;
    int y;
    int pre_x;
    int pre_y;
};

enum Direction{
    LEFT=0,
    RIGHT,
    UP,
    DOWN
};


void *delay(void *arg){
    usleep(100000);
    return NULL;

}

void initmap()
{
    for(int i=0;i<20;i++)
    {
        map[0][i]=1;
        map[19][i]=1;
        map[i][0]=1;
        map[i][19]=1;
    }
}

void RefreshMap()
{
    int i,j;
    for(i=0;i<20;i++)
    {
        for(j=0;j<20;j++)
        {
            switch(map[i][j]){
                case 1:printf("#");break;
                case 0:printf(" ");break;
                case 2:printf("*");break;
                case 3:printf("0");break;
                default:break;
            }
        }
        if(i==4&&j==20){
            printf("  press \'e\' to stop game");
        }
        if(i==3&&j==20){
            printf("  Score:%d",Score);
        }
        putchar('\n');
    }
    
}

void ClearSnackTail(struct snack *pcheck)
{
    struct snack *p=pcheck;
    struct snack *temp;
    while(p->tail!=NULL){
        p=p->tail;//先找到最后的节点
    }
    while(p!=pcheck){
        temp=p;
        p=p->pre;
        map[p->x][p->y]=0;
        free(temp);
    }
    map[p->x][p->y]=0;
    free(p);//删除剩下的一个节点

}

int CloseGame(struct snack *pcheck,int IsAutoStop)
{
    char value;
     struct snack *p=pcheck;
    struct snack *temp;
    if(!IsAutoStop){
        printf("do you want exit the game? [y/n]\n");
        while(1){
            value=getchar();
            if(value=='y'){
                if(pcheck==NULL){
                    return 1;
                }
                else{
                    goto exit_handle;
                 }
            }
            else if(value=='n'){
                return 0;
            }
            else{
                printf("enter error,please enter again\n");
            }
        }
    }
    else if(IsAutoStop){
        if(pcheck==NULL){
            return 1;
        }
        else{
            goto exit_handle;
        }
    }

exit_handle://头部不是malloc的不需要释放
    while(p->tail!=NULL){
        p=p->tail;//先找到最后的节点
    }
    while(p!=pcheck){
        temp=p;
        p=p->pre;
        map[p->x][p->y]=0;
        free(temp);
    }
    map[p->x][p->y]=0;
    free(p);//删除剩下的一个节点
    return 1;


}
void play()
{
    struct snack SnackHeader;
    struct food fd={
        .x=1,
        .y=1,
        .pre_x=1,
        .pre_y=1
    };
    char getvalue;
    SnackHeader.x=5;
    SnackHeader.y=5;
    SnackHeader.pre_y=5;
    SnackHeader.pre_x=5;
    SnackHeader.direc=RIGHT;
    SnackHeader.tail=NULL;
    SnackHeader.pre=NULL;
    struct snack *snack_tail=&SnackHeader;
    struct snack *snack_head=&SnackHeader;
    fd.x=(rand()%18+1);
    fd.y=(rand()%18+1);
    map[fd.x][fd.y]=3;
    while(1){
        RefreshMap();
        pthread_t delay_thread;
        if(kbhit()){
            getvalue=getch();
            switch(getvalue){
                case 'w':
                    if(SnackHeader.direc!=DOWN){
                        SnackHeader.direc=UP;
                    }
                    break;
                case 's':if(SnackHeader.direc!=UP){
                        SnackHeader.direc=DOWN;
                    }
                    break;
                case 'a':if(SnackHeader.direc!=RIGHT){
                        SnackHeader.direc=LEFT;
                    }
                    break;
                case 'd':if(SnackHeader.direc!=LEFT){
                        SnackHeader.direc=RIGHT;
                    }
                    break;
                case 'e':
                    if(CloseGame(SnackHeader.tail,0)==1){
                        return;
                    }
                    break;
                default :
                    break;
            }
        }
        SnackHeader.pre_y=SnackHeader.y;
        SnackHeader.pre_x=SnackHeader.x;
        if(SnackHeader.direc==UP)
        {
            SnackHeader.x--;
            if(SnackHeader.x==0){
                SnackHeader.x=18;
            }
        }
        else if(SnackHeader.direc==DOWN){
            SnackHeader.x++;
            if(SnackHeader.x==19){
                SnackHeader.x=1;
            }
        }
        else if(SnackHeader.direc==LEFT){
            SnackHeader.y--;
            if(SnackHeader.y==0){
                SnackHeader.y=18;
            }
        }
        else if(SnackHeader.direc==RIGHT){
            SnackHeader.y++;
            if(SnackHeader.y==19){
                SnackHeader.y=1;
            }
        }
        
        map[SnackHeader.pre_x][SnackHeader.pre_y]=0;
        map[SnackHeader.x][SnackHeader.y]=2;

        if((SnackHeader.x==fd.x)&&(SnackHeader.y==fd.y)){
            Score++;
            fd.x=(rand()%18+1);
            fd.y=(rand()%18+1);
            map[fd.x][fd.y]=3;
            struct snack *p_tail=(struct snack*)malloc(sizeof(struct snack));
            p_tail->tail=NULL;
            p_tail->x=snack_tail->pre_x;
            p_tail->y=snack_tail->pre_y;
            p_tail->pre_x=p_tail->x;
            p_tail->pre_y=p_tail->y;

            snack_tail->tail=p_tail;
            p_tail->pre=snack_tail;
            snack_tail=p_tail; 
        }
        struct snack *pcheck=SnackHeader.tail;
        while(pcheck!=NULL)
        {
            pcheck->pre_x=pcheck->x;
            pcheck->pre_y=pcheck->y;
            pcheck->x=pcheck->pre->pre_x;
            pcheck->y=pcheck->pre->pre_y;
            map[pcheck->x][pcheck->y]=2;
            map[pcheck->pre_x][pcheck->pre_y]=0;
           // printf("%d %d %d %d",pcheck->pre_x,pcheck->pre_y,pcheck->x,pcheck->y);
            pcheck=pcheck->tail;
        }
        if(CollideCheck(&SnackHeader)==1){
            printf("do you want to continue game? [y/n]\n");
            char value;
            while(1){
                value=getchar();
                if(value =='y'){
                    if(SnackHeader.tail!=NULL){
                        ClearSnackTail(SnackHeader.tail);
                        SnackHeader.tail=NULL;//删除完后重归NULL
                        map[SnackHeader.pre_x][SnackHeader.pre_y]=0;//头部也要归0
                        snack_tail=&SnackHeader;
                    }
                    break;
                }
                else if(value =='n'){
                    CloseGame(SnackHeader.tail,1);//退出时需要释放申请的内存
                    return;
                }
                else
                {
                    printf("enter error! please enter again\n");
                    continue;
                }
            }
        }
        
        //sleep(1);
        if(pthread_create(&delay_thread,NULL, delay, NULL)!=0)
        {
            printf("creat thread fail\r\n");
        }
        pthread_join(delay_thread,NULL);
        

        system("cls");
        //RefreshMap();

    }
}


//碰撞检测
int CollideCheck(struct snack *phead)
{
    int head_x,head_y,Iscollide=0;
    head_x=phead->x;
    head_y=phead->y;
    struct snack *pcheck=phead->tail;
    while(pcheck!=NULL)
    {
        if((pcheck->x==head_x)&&(pcheck->y==head_y))
        {
            Iscollide=1;
            return Iscollide;
        }
        pcheck=pcheck->tail;
    }
    return Iscollide;
    

}
int main(int argc, char const *argv[])
{
    //printf("Hello World!\n");
    initmap();
    play();
    getchar();
    return 0;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值