贪吃蛇


#include<stdio.h>
#include<stdlib.h>
#include<conio.h>
#include<time.h>
#include<windows.h>

#define WIGTH  50
#define HEIGHT 25
//const int iWight  = 50;
//const int iHeight = 50;
char cBody   = '#';
char cFloor  = ' ';
char cFood   = '$';

typedef struct SnakeNode
{
    int  x;
    int  y;
    struct SnakeNode *pNext;
} SnakeNode;

char GlobleMap[HEIGHT][WIGTH] = {0};
int iLengt = 2;

SnakeNode* CreatSnake();                                                // 创建一个蛇头
SnakeNode* CreatFood(SnakeNode *pHead);                                 // 创建一个食物
int  IsBump(SnakeNode *pFood, SnakeNode *pHead);                        // 检测与食物、墙壁、身体的碰撞
char MoveSnake(char cDirection, SnakeNode **pHead);                     // 给一个方向移动蛇,要改变蛇头,所以这里用二级指针
void Init();                                                            // 初始化地图
void GetKey(int x);
void Elongate(char cDirection, SnakeNode *pHead);                       // 增加蛇的长度
void PrintSnake(SnakeNode *pHead);                                      // 将蛇身打印在地图里
void PrintFood(SnakeNode *pFood);                                       // 将食物打印在地图里
void DrewGloble();                                                      // 打印地图
void Free(SnakeNode *pHead);                                            // 释放内存,结束时调用
void GoToXY(int x, int y);                                              // 辅助函数

int main()
{
    SnakeNode *pHead = CreatSnake();
    SnakeNode *pFood = CreatFood(pHead);
    int t;
    char cDirection = 0;
    GoToXY(40, 10);
    printf("开始之前请将输入法设置为英文小写\n");
    GoToXY(40, 12);
    printf("w--上;s--下;a--左;d--右;其他键暂停");
    GoToXY(40, 14);
    printf("按回车键开始游戏。。。。。。");
    getchar();
    system("cls");
    while(1)
    {
        Init();
        PrintSnake(pHead);
        PrintFood(pFood);
        DrewGloble();
//------------这一段没写在函数里,有点麻烦------------
        if(!kbhit())
        {
            cDirection = MoveSnake(cDirection, &pHead);                 // 如果没有按键盘,按原来的方向走
        }
        else
        {
            char cTmp = getch();                                             // 按下键盘,检测键盘的值,确保不会回头
            if(cDirection == 's' && cTmp == 'w')
                MoveSnake(cDirection, &pHead);
            else if(cDirection == 'w' && cTmp == 's')
                MoveSnake(cDirection, &pHead);
            else if(cDirection == 'd' && cTmp == 'a')
                MoveSnake(cDirection, &pHead);
            else if(cDirection == 'a' && cTmp == 'd')
                MoveSnake(cDirection, &pHead);
            else
                cDirection = MoveSnake(cTmp, &pHead);
        }
//--------------按下键盘,检测键盘的值,确保不会回头--------------
//--------------碰撞检测--------------------
        t = IsBump(pFood, pHead);
        if(t == 1)                                                      // 吃到食物, 蛇身边长,更新食物
        {
            Elongate(cDirection, pHead);
            pFood = CreatFood(pHead);
        }
        else if(t == 2)                                       // 撞到墙或者身体,游戏结束
        {
            GoToXY(60, 12);
            printf("\aGAME OVER");
            GoToXY(60, 14);
            printf("哎呀,你撞到墙了!");
            break;
        }
        else if(t == 3)                                       // 撞到墙或者身体,游戏结束
        {
            GoToXY(60, 12);
            printf("\aGAME OVER");
            GoToXY(60, 14);
            printf("哎呀,你吃到自己了!");
            break;
        }
//-------------------------------------------
    }
    Free(pHead);
    getchar();
    GoToXY(0, 26);
    return 0;
}
void Init()
{
    GoToXY(0, 0);                                                       // 回到左上角的位置,重新打印地图
    for(int i=0; i<HEIGHT; i++)
    {
        for(int j=0 ;j<WIGTH; j++)
        {
            if(i==0 || i==HEIGHT-1)
                GlobleMap[i][j] = '_';
            else if(j==0 || j==WIGTH-1)
                GlobleMap[i][j] = '|';
            else
                GlobleMap[i][j] = ' ';
        }
    }
}
SnakeNode* CreatSnake()
{
    SnakeNode *pHead = (SnakeNode*)malloc(sizeof(SnakeNode));                       // 创建两个节点的蛇
    pHead->x = 6;
    pHead->y = 9;
    pHead->pNext = (SnakeNode*)malloc(sizeof(SnakeNode));
    pHead->pNext->x = 7;
    pHead->pNext->y = 9;
    pHead->pNext->pNext = NULL;
    return pHead;
}
SnakeNode* CreatFood(SnakeNode *pHead)
{
    srand(time(NULL));
    SnakeNode *pFood = (SnakeNode*)malloc(sizeof(SnakeNode));
    pFood->pNext = NULL;
    SnakeNode *pNon  = pHead;

    int x = rand()%48 + 1;                                           // 确保食物不会出现在边界, 还应该写 食物不能出现在蛇身,我暂时没写
    int y = rand()%23 + 1;
    A:
    while(pNon != NULL)
    {
        if(pNon->x == x && pNon->y == y)
        {
            x = rand()%48 + 1;
            y = rand()%22 + 1;
            pNon = pHead;
            goto A;
        }
        pNon = pNon->pNext;
    }

    pFood->x = x;
    pFood->y = y;
    return pFood;
}

void Elongate(char cDirection, SnakeNode *pHead)
{
    SnakeNode *pNon = pHead;
    SnakeNode *pTmp;
    while(pNon->pNext != NULL)
    {
        pNon = pNon->pNext;
    }
    pTmp = (SnakeNode*)malloc(sizeof(SnakeNode));                                   // 在蛇尾添加一个节点
    pNon->pNext = pTmp;
    pTmp->pNext = NULL;

    switch(cDirection)                                                  // 添加的节点,与移动方向相反,例如:蛇头往上走,添加的节点在尾巴的下面
    {
        case 's': pTmp->y = pNon->y - 1;
                  pTmp->x = pNon->x;
                  break;
        case 'w': pTmp->y = pNon->y + 1;
                  pTmp->x = pNon->x;
                  break;
        case 'd': pTmp->x = pNon->x - 1;
                  pTmp->y = pNon->y;
                  break;
        case 'a': pTmp->x = pNon->x + 1;
                  pTmp->y = pNon->y;
                  break;
        default : break;
    }
//    printf("\a");
}

void PrintSnake(SnakeNode *pHead)
{
    SnakeNode *pNon = pHead;                                            // 将蛇的位置,标注在地图上
    while(pNon != NULL)
    {
        GlobleMap[pNon->y][pNon->x] = cBody;
        pNon = pNon->pNext;
    }
}
void PrintFood(SnakeNode *pFood)
{
    GlobleMap[pFood->y][pFood->x] = cFood;                              // 将食物的位置,标注在地图上
}
///这里改变了头指针的值,所以要传入指针的地址
char MoveSnake(char cDirection, SnakeNode **pHead)
{
    SnakeNode *pNon = *pHead;
    while(pNon->pNext->pNext != NULL)                                   // 找到尾节点的前一个节点
        pNon = pNon->pNext;

    SnakeNode *pTmp = pNon->pNext;                                      // pTmp为尾节点
    pNon->pNext = NULL;                                                 // pNon变成尾节点
    pTmp->pNext = *pHead;                                               // pTmp指向头节点
    *pHead = pTmp;                                                      // 更新pHead*pHead

    switch(cDirection)                                                  // 整体思想是 把蛇尾拿下来,放在蛇头上,来蛇的整体实现移动
    {
        case 'w': (*pHead)->y = (*pHead)->pNext->y - 1;
                  (*pHead)->x = (*pHead)->pNext->x;
                  break;
        case 's': (*pHead)->y = (*pHead)->pNext->y + 1;
                  (*pHead)->x = (*pHead)->pNext->x;
                  break;
        case 'a': (*pHead)->x = (*pHead)->pNext->x - 1;
                  (*pHead)->y = (*pHead)->pNext->y;
                  break;
        case 'd': (*pHead)->x = (*pHead)->pNext->x + 1;
                  (*pHead)->y = (*pHead)->pNext->y;
                  break;
        default : break;
    }

    return cDirection;
}

void DrewGloble()
{
    for(int i=0; i<HEIGHT; i++)
    {
        for(int j=0 ;j<WIGTH; j++)
        {
            printf("%c", GlobleMap[i][j]);
        }
        printf("\n");
    }
    GoToXY(60, 3);
    printf("您的得分是:%d", (iLengt-2)*5);
    GoToXY(60, 6);
    printf("食物一共有:%d", iLengt-2);
    GoToXY(60, 9);
    printf("蛇的长度是:%d", iLengt);
}
void Free(SnakeNode *pHead)
{
    SnakeNode *pNon = pHead->pNext;
    free(pHead);
    while(pNon != NULL)
    {
        SnakeNode *pTmp = pNon->pNext;
        free(pNon);
        pNon = pTmp;
    }
}

int IsBump(SnakeNode *pFood, SnakeNode *pHead)
{
    int iFlag = 0;
    if(pHead->x == pFood->x && pHead->y == pFood->y)
    {
        iLengt++;
        iFlag = 1;                                           // 1 代表吃到食物
    }
    else if(pHead->x == 0 || pHead->x == WIGTH-1 || pHead->y == 0 || pHead->y == HEIGHT-1)
    {
        iFlag = 2;                                           // 2 代表撞墙
    }

    SnakeNode *pNon = pHead->pNext;
    while(pNon != NULL)
    {
        if(pHead->x == pNon->x && pHead->y == pNon->y)
        {
            iFlag = 3;                                       // 3 表示撞到自己
            break;
        }
        pNon = pNon->pNext;
    }

    return iFlag;
}
//  抄的API
void GoToXY(int x, int y)                                   // x, y代表想去的像素点的位置,其他不用知道
{
    HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
    COORD coord;
    coord.X = x;
    coord.Y = y;
    SetConsoleCursorPosition(handle, coord);
}


 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值