C语言构建的链表贪吃蛇

用C语言链表写的贪吃蛇(程序设计时做的,做的不好大佬勿喷)

在这里插入图片描述

  1. 借助游戏内容分析贪吃蛇所需的功能主要包括这几块:

    1. 移动光标模块

    2. 打印地图模块和基本规则信息

       读取最高分文件
      
    3. 打印初始蛇模块

      打印时给予蛇的初始移动方向  
      
    4. 产生食物模块

       1)、保证食物在地图内产生
      
       2)、保证食物不能出现在蛇体
      
    5. 蛇的生命状态判断模块

      1)、撞墙导致死亡
      
      2)、头撞身体部位死亡
      

    6.运行模块

        1)、让蛇移动
    
        2)、根据按键来改变蛇的移动方向
    
        3)、对待分数的增加游戏难度的增加
    
        4)、蛇在吃食物后分数的增加
    

    7.结束模块

     在遇到撞墙或者撞自己部位死亡时结束程序,并进行分数与历史最高分作比较,最终达到最高分的更新
    

    以下为代码

#include <stdlib.h>
#include <stdio.h>
#include <conio.h>//控制台输入和输出
#include <windows.h>//窗口函数
#include <time.h>
#define W 1//蛇的运动方向W:上 S:下 A: 左 D:右
#define S 2
#define A 3
#define D 4
/*
定义全局变量
*/
typedef struct{
int x;
int y;
}place;//定义坐标结构体
typedef struct ZB{
place data;
struct ZB *next;
}snake;//定义蛇的链表
/*
定义全局链表
*/
snake *head,*p,*q,*h;//
place food;//定义食物坐标
int score=0,bestscore,game_flag=0,ch,sleep=400;//定义得分score死亡判断game_flag方向判断ch蛇的速度sleep
/*
函数声明
*/
void gotoxy(int x,int y);//定位光标
void map_creat();//运用定位函数打印地图
void ini_snack();//随机产生蛇
void cre_food();//随机产生食物
void live_jud_1();//判断自己是否撞墙死亡
void live_jud_2();//判断自己是否撞到自己
void move();//蛇的移动
void rungame();//游戏运行
void gameover();//游戏结束界面
void changch();//改变方向
int color(int c);//改颜色函数
/*
构建定位函数
*/
int color(int c)
{
 SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),c);        //更改文字颜色
 return 0;
}
void gotoxy(int x,int y)//定位光标
{
    COORD pos;
    HANDLE handle=GetStdHandle(STD_OUTPUT_HANDLE);
    pos.X=x;
    pos.Y=y;
    SetConsoleCursorPosition(handle,pos);
}
/*
打印地图
*/
void map_creat()//运用定位函数打印地图
{
    FILE *fp;//创建一个记录最高分的文件
    fp=fopen("score.1","r");
    fscanf(fp,"%d",&bestscore);//读取最高分
    fclose(fp);
    gotoxy(54,26);
    printf("Your Best Score : %d\t", bestscore);//打印出最高分
    int i,j;
    for(i=0;i<48;i++)
    {
        gotoxy(i,0);
        printf("#");
        color(6);
        gotoxy(i,26);
        printf("#");
        color(6);
    }
    for(j=0;j<26;j++)
    {
        gotoxy(0,j);
        printf("#");
        color(6);
        gotoxy(48,j);
        printf("#");
        color(6);
    }
    gotoxy(54,10);
    printf("游戏规则:");
    gotoxy(54,12);
    printf("向上移动:↑\n");
    gotoxy(54,14);
    printf("向下移动:↓\n");
    gotoxy(54,16);
    printf("向左移动:←\n");
    gotoxy(54,18);
    printf("向右移动:→\n");
    gotoxy(54,20);
    printf("吃一个食物分数加10");
    gotoxy(54,22);
    printf("按空格键暂停游戏");
    gotoxy(54,24);
    printf("按ESC直接结束游戏");
}
/*
构建初始蛇
*/
void ini_snack()//产生蛇
{
    int i;
    /*
    采用尾插法构建蛇的链表初始长度设为二
    */
    head=(snake *)malloc(sizeof(snake));
    head->data.x=48/2;
    head->data.y=26/2;
    head->next=NULL;
    h=head;
    for(i=1;i<=2;i++)
    {
        p=(snake *)malloc(sizeof(snake));
        p->data.x=48/2+i;
        p->data.y=26/2;
        h->next=p;
        h=p;
    }
    p->next=NULL;
    /*
    将蛇打印出来
    */
    h=head;
    while(h!=NULL)
    {
        gotoxy(h->data.x,h->data.y);
        color(5);
        printf("@");
        h=h->next;
    }
    ch=W;//蛇的初始方向
}
/*
随机产生食物
*/
void cre_food()//随机产生食物
{
    srand((unsigned)time(NULL));//为了防止每次产生的随机数相同,种子设置为time
    /*
    随机产生食物
    */
    food.x=rand()%(48-2)+1;
    food.y=rand()%(26-2)+1;
    while(p!=NULL)
    {
     /*
     判断食物是否与蛇重合,如果重合重新产生
     */
    if(p->data.x==food.x&&p->data.y==food.y)
    cre_food();
    p=p->next;
    }
    gotoxy(food.x,food.y);
    color(1);
    printf("$");//打印食物
}
/*
判断是否死亡
*/
void  live_jud_1()//判断自己是否撞墙死亡
{
    if(head->data.x==0||head->data.x==48||head->data.y==0||head->data.y==26)//撞墙
       {
           game_flag=1;
           gameover();
       }
}
void  live_jud_2()//判断自己是否撞到自己
{
    q=head->next;
    while(q!=NULL)
    {
        if(head->data.x==q->data.x&&head->data.y==q->data.y)//撞自己
        {
            {
            game_flag=2;
            gameover();
            }
            break;
        }
        q=q->next;
    }
}
/*
游戏进行界面
*/
void move()
{
    snake *l;
    live_jud_1();
    l=(snake *)malloc(sizeof(snake));
    /*
    构建一个新的节点通,过新节点来表示下一次头节点所在的位置
    将新节点当作移动后的头节点
    如果新头节点的坐标等于食物的坐标得分加10,食物的标志变为1
    因为蛇的链表长度加了一,如果是移动的话找出尾节点并打印出 然后删掉该尾节点
    如果吃到了食物就直接将蛇打印出来
    */
    if(ch==W)
        {
            l->data.x=head->data.x;
            l->data.y=head->data.y-1;
            if(l->data.x==food.x&&l->data.y==food.y)
            {
                l->next=head;
                head=l;
                q=head;
                while(q!=NULL)//将蛇重新打印一边
                {
                    gotoxy(q->data.x,q->data.y);
                    color(5);
                    printf("@");
                    q=q->next;
                }
                score+=10;
                cre_food();//构建新的食物
            }
            else
            {
                l->next=head;
                head=l;
                q=head;
                while(q->next->next!=NULL)
                {
                    gotoxy(q->data.x,q->data.y);
                    color(5);
                    printf("@");
                    q=q->next;
                }
                gotoxy(q->next->data.x,q->next->data.y);
                printf(" ");//将蛇尾去掉
                free(q->next);
                q->next=NULL;
            }
        }
    if(ch==A)
        {
            l->data.x=head->data.x-1;
            l->data.y=head->data.y;
            if(l->data.x==food.x&&l->data.y==food.y)
            {
                l->next=head;
                head=l;
                q=head;
                while(q!=NULL)
                {
                    gotoxy(q->data.x,q->data.y);
                    color(5);
                    printf("@");
                    q=q->next;
                }
                score+=10;
                cre_food();
            }
            else
            {
                l->next=head;
                head=l;
                q=head;
                while(q->next->next!=NULL)
                {
                    gotoxy(q->data.x,q->data.y);
                    color(5);
                    printf("@");
                    q=q->next;
                }
                gotoxy(q->next->data.x,q->next->data.y);
                printf(" ");
                free(q->next);
                q->next=NULL;
            }
        }
        if(ch==S)
        {
            l->data.x=head->data.x;
                  l->data.y=head->data.y+1;
            if(l->data.x==food.x&&l->data.y==food.y)
            {
                l->next=head;
                head=l;
                q=head;
                while(q!=NULL)
                {
                    gotoxy(q->data.x,q->data.y);
                    color(5);
                    printf("@");
                    q=q->next;
                }
                score+=10;
                cre_food();
            }
            else
            {
                l->next=head;
                head=l;
                q=head;
                while(q->next->next!=NULL)
                {
                    gotoxy(q->data.x,q->data.y);
                     color(5);
                    printf("@");
                    q=q->next;
                }
                gotoxy(q->next->data.x,q->next->data.y);
                printf(" ");
                free(q->next);
                q->next=NULL;
            }
        }
    if(ch==D)
        {
            l->data.x=head->data.x+1;
            l->data.y=head->data.y;
            if(l->data.x==food.x&&l->data.y==food.y)
            {
                l->next=head;
                head=l;
                q=head;
                while(q!=NULL)
                {
                    gotoxy(q->data.x,q->data.y);
                    color(5);
                    printf("@");
                    q=q->next;
                }
                score+=10;
                cre_food();
            }
            else
            {
                l->next=head;
                head=l;
                q=head;
                while(q->next->next!=NULL)
                {
                    gotoxy(q->data.x,q->data.y);
                    color(5);
                    printf("@");
                    q=q->next;
                }
                gotoxy(q->next->data.x,q->next->data.y);
                printf(" ");
                free(q->next);
                q->next=NULL;
            }
        }
   live_jud_2();//判断是否撞自己死亡
}
void rungame()//运行游戏
{
    while(1)
    {
    gotoxy(54,8);
    printf("Your Score:%d",score);
    /*
    以下确保不能向上运动时改方向为向下等情况
    */
    if(GetAsyncKeyState(VK_UP)&&ch!=S)
            ch=W;
    else if(GetAsyncKeyState(VK_DOWN)&&ch!=W)
            ch=S;
    else if(GetAsyncKeyState(VK_LEFT)&&ch!=D)
            ch=A;
    else if(GetAsyncKeyState(VK_RIGHT)&&ch!=A)
            ch=D;
    /*
    根据分数和Sleep函数来确定游戏难度
    */
    if(score>=50&&score<100)
        sleep=300;
    else if(score>=100&&score<300)
        sleep=250;
    else if(score>=300)
        sleep=200;
    if(GetAsyncKeyState(VK_SPACE))//输入space暂停游戏
    {
        while(1)
        {
            Sleep(300);
            if(GetAsyncKeyState(VK_SPACE))
            break;
        }
    }
    else if (GetAsyncKeyState(VK_ESCAPE))//输入ESC直接结束游戏
    {
        game_flag=3;
        gameover();
    }
    Sleep(sleep);
    move();
    }
}
/*
游戏结束界面
*/
void gameover()//游戏结束界面
{
    FILE *fp;
    system("cls");//清屏
    gotoxy(48/2,26/2-2);
    printf("\tGame Over!!!");//打印出游戏结束界面
    gotoxy(48/2,26/2);
    if(game_flag==1)
    printf("\t你撞墙了!!!\n");
    else if(game_flag==2)
    printf("\t傻孩子!你不能吃你自己!!!\n");
    else if(game_flag==3)
    printf("\t您已结束游戏!");
    gotoxy(48/2,26/2+2);
    printf("\tYour score:%d\n",score);//打印出得到的分数
    if(score>bestscore)//如果此次游戏分数大于以前最高分
    {
    fp=fopen("score.1","w");
    fprintf(fp,"%d",score);//将此次分数保存在最高分文件里
    fclose(fp);
    }
    system("pause");
    exit(0);
}
/*
主函数
*/
int main()
{
    system("color 9");
    map_creat();
    ini_snack();
    cre_food();
    rungame();
    return 0;
}




猜你喜欢

转载自blog.csdn.net/ippcp/article/details/106817372
今日推荐