用单链表做的贪吃蛇C语言程序

贪吃蛇由地图、蛇身、食物组成。它们的图形显示位置由下面这个函数表示:

 void draw(char x, char y)  \\显示坐标位置,其中左上角为坐标原点
    {
      COORD pos;                   \\写这个函数必须配windows.h头文件
    HANDLE hOutput;
    pos.X = x;
    pos.Y = y;
    hOutput = GetStdHandle(STD_OUTPUT_HANDLE);
    SetConsoleCursorPosition(hOutput, pos);
    }

初始化地图大小为100×25,通过显示光标位置打印图案:

` void Init_map()
{
    char i;
    for(i=0;i<100;i++)   
    {
        draw(i,0);
        printf("#");
        draw(i,25);
        printf("#");
    }
     for(i=0;i<25;i++)
    {
        draw(0,i);
        printf("#");
        draw(100,i);
        printf("#");
    }
}

用单链表初始化蛇身,链表中每一个结点都存储了x,y坐标:

struct snack
{
    char x;
    char y;
    struct snack*next;
}*head,*food,*pnew;


void Init_snack()
{
    struct snack* ptail;
    char i;
    ptail=(struct snack*)malloc(sizeof(struct snack));
    ptail->x=50;          //初始化蛇头在50,25坐标处
    ptail->y=15;
    ptail->next=NULL;
    for(i=1;i<=2;i++)   //初始化蛇身长为3
    {
        head=(struct snack*)malloc(sizeof(struct snack));
        head->next=ptail;
        head->x=50+i;    //初始化蛇为横向
        head->y=15;
        ptail=head;
    }
    while(ptail!=NULL)    //遍历结点中的坐标,打印蛇身图案
        {
            draw(ptail->x,ptail->y);
            printf("*");
            ptail=ptail->next;
        }
}

接下来是食物的随机出现,一要在地图内,二不能出现在蛇身的坐标上。刚开始写完后我发现食物的随机出现是有规律的,即每次打开食物出现的地方是固定,后来加了个时间种子才算达到了随机产生。

void rand_food()
{
    if(food!=NULL)
    {
        return;
    }
    srand(time(0));   //设置时间种子
    struct snack*food_tb=(struct snack*)malloc(sizeof(struct snack));
    food_tb->x=rand()%99+1;  //食物x坐标在1到99 y坐标在1到24
    food_tb->y=rand()%24+1;
    pnew=head;
    while(pnew!=NULL)
    {
        if(food_tb->x==pnew->x&&food_tb->y==pnew->y) //判断食物是否出现在蛇身上
        {
            free(food_tb);
            rand_food();
            break;
        }
        pnew=pnew->next;
    }
    food=food_tb;
    draw(food->x,food->y);
    printf("!");

}

蛇的移动是通过键盘控制的,由一个kbhit()函数判断键盘是否有按下,如果按下则有getch()读取按下的值,这两个函数都包含在conio.h头文件里。然后在调用case语句,以读取到的值作为其字符常量,通常是w=上,a=左,d=右,s=下。

蛇的死亡条件有两个,一个是撞墙,另一个是自食(按着朝运动方向相反的键也算),写一个函数用if大法判断,如果符合就exit(0)。

蛇的运动速度调节用while(i–)实现,每吃到一个舒服i的值就减少。
下面是整个代码:

#include<stdio.h>
#include<time.h>
#include<windows.h>
#include<stdlib.h>
#include<conio.h>
char ch='d'; \\默认移动向右
static int count;  
void draw(char x,char y);
struct snack
{
    char x;
    char y;
    struct snack*next;
}*head,*food,*pnew;


void Init_snack()
{
    struct snack* ptail;
    char i;
    ptail=(struct snack*)malloc(sizeof(struct snack));
    ptail->x=50;
    ptail->y=15;
    ptail->next=NULL;
    for(i=1;i<=2;i++)   //ÉßÉí³¤¶ÈΪ3£»
    {
        head=(struct snack*)malloc(sizeof(struct snack));
        head->next=ptail;
        head->x=50+i;
        head->y=15;
        ptail=head;
    }
    while(ptail!=NULL)
        {
            draw(ptail->x,ptail->y);
            printf("*");
            ptail=ptail->next;
        }
}

void Init_map()
{
    char i;
    for(i=0;i<100;i++)
    {
        draw(i,0);
        printf("#");
        draw(i,25);
        printf("#");
    }
     for(i=0;i<25;i++)
    {
        draw(0,i);
        printf("#");
        draw(100,i);
        printf("#");
    }
}

void rand_food()
{
    if(food!=NULL)
    {
        return;
    }
    srand(time(0));
    struct snack*food_tb=(struct snack*)malloc(sizeof(struct snack));
    food_tb->x=rand()%99+1;
    food_tb->y=rand()%24+1;
    pnew=head;
    while(pnew!=NULL)
    {
        if(food_tb->x==pnew->x&&food_tb->y==pnew->y)
        {
            free(food_tb);
            rand_food();
            break;
        }
        pnew=pnew->next;
    }
    food=food_tb;
    draw(food->x,food->y);
    printf("!");

}

    void draw(char x, char y)
    {
    COORD pos;
    HANDLE hOutput;
    pos.X = x;
    pos.Y = y;
    hOutput = GetStdHandle(STD_OUTPUT_HANDLE);
    SetConsoleCursorPosition(hOutput, pos);

    }
    void alive()
    {
        struct snack *self=head->next;
        while(self!=NULL)
        {
            if(self->x==head->x&&self->y==head->y)
            {
                exit(0);
            }
            if(head->x==0||head->x==100||head->y==0||head->y==25)
                exit(0);
            self=self->next;
        }

    }

    void snack_move()
    {

        if(kbhit())
           ch=getch();

        struct snack*nextnode=(struct snack*)malloc(sizeof(struct snack));
        switch(ch)
        {
            case 'w':nextnode->x=head->x;
                        nextnode->y=head->y-1;
                        break;
            case 's':nextnode->x=head->x;
                        nextnode->y=head->y+1;
                        break;
            case 'a':nextnode->x=head->x-1;
                        nextnode->y=head->y;
                        break;
            case 'd':nextnode->x=head->x+1;
                        nextnode->y=head->y;
                        break;
        }
        nextnode->next=head;    //nextnode指向第一个结点
        head=nextnode;       //这里head已经增加了一节
        pnew=head;
        if(nextnode->x==food->x&&nextnode->y==food->y) //吃到食物就增加一个结点
        {
            while(pnew!=NULL)
            {
                draw(pnew->x,pnew->y);    
                printf("*");
                pnew=pnew->next;
            }
            free(food);
            food=NULL;
            rand_food();
            count++;

        }
        else  //否则蛇继续移动
        {
            while(pnew->next->next!=NULL)
            {
                draw(pnew->x,pnew->y);
                printf("*");
                pnew=pnew->next;
            }
            draw(pnew->next->x,pnew->next->y);
            printf(" "); 
            free(pnew->next);
            pnew->next=NULL;     //倒数第二个结点地址指向NULL
        }
    }

    void main()
    {
        Init_map();
        Init_snack();
    while(1)
        {
        int i=50000000-count*5000000;
        rand_food();
        while(i--);
        snack_move();
        alive();
        }


    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值