贪吃蛇

实现一个贪食蛇游戏

具有的功能:
  • 实现蛇的移动,通过上下左右键控制蛇移动的方向
  • 蛇每次吃到食物分数会在增加,蛇身变长
  • 不能撞墙或者碰到自己的蛇身

代码实现

snake.h

#ifndef __SNAKE_H__
#define __SANKE_H__

#include
#include
#include
#include


//蛇结点的结构
typedef struct SnakeNode
{
    int x;
    int y;
    struct SnakeNode * next;
}SnakeNode, *pSnakeNode;

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

enum GameStatus
{
    OK,
    NORMAL_END,
    KILL_BY_WALL,
    KILL_BY_SELF
};

//维护整个过程的结构
typedef struct Snake{
    pSnakeNode _psnake;  //维护蛇身的指针
    pSnakeNode _pFood;   //维护食物的指针
    //蛇的方向,游戏的状态,实现加速的功能,每次增加的分数
    enum Direction _dir;  //蛇的方向
    enum GameStatus  _Status;
    int TotalScore;
    int _AddScore;
    int _SleepTime;    //实现加速功能通过睡眠的时间,睡眠的时间稍长,速度就慢
}Snake,*pSnake;

#define WALL "■"
#define FOOD "●"
#define X_INIT 20
#define Y_INIT 10


//函数实现

void WelcomToGame();
void CreateMap();
void InitSnake(pSnake ps);
void CreateFood(pSnake ps);

void Pause();
void SnakeMove(pSnake ps);
int NextHasFood(pSnakeNode pn, pSnakeNode pf);
void EatFood(pSnake ps, pSnakeNode pn);
void NotFood(pSnake ps, pSnakeNode pn);
void KillByWall(pSnake ps);
void KillBySelf(pSnake ps);

void GameStart(pSnake ps);
void GameRun(pSnake ps);
void GameEnd(pSnake ps);

#endif
snake.c

#include"snake.h"

void HideCursor()
{
    CONSOLE_CURSOR_INFO cursor_info = { 1, 0 };
    SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &cursor_info);
}
void SetPos(int x,int y)
{
    COORD pos = { 0 };
    //获取句柄
    HANDLE handle = NULL;
    handle = GetStdHandle(STD_OUTPUT_HANDLE);
    pos.X = x;
    pos.Y = y;
    SetConsoleCursorPosition(handle, pos);
}

void WelcomToGame()
{
    //设置窗口大小
    system("mode con cols=100 lines=30");
    SetPos(39,13);
    printf("alisa 欢迎您来到贪吃蛇小游戏\n");
    SetPos(40, 28);
    //出现这个页面暂停,按任意键才往下走
    system("pause");
    //清空屏幕
    system("cls");
    SetPos(25, 13);
    printf("用↑.↓.←.→来控制蛇的移动。F1为加速,F2为减速.");
    SetPos(25, 14);
    printf("加速获得分数更多");
    SetPos(40, 28);
    //进入游戏之前,需要将之前的信息清空
    system("pause");
    system("cls");

}

//创建地图
void CreateMap()
{
    //因为墙与真实运作环境不同,从四个方面进行控制
    int i = 0;
    //上
    for (i = 0; i <= 58; i += 2)
    {
        SetPos(i, 0);
        printf(WALL);
    }
    //下,打印的是下面的行
    for (i = 0; i <= 58; i += 2)
    {
        SetPos(i, 27);
        printf(WALL);

    }
    //左,打印的是左边的列
    for (i = 1; i <= 26; i++)
    {
        SetPos(0,i);
        printf(WALL);
    }

    //右
    for (i = 1; i <= 26; i++)
    {
        SetPos(58, i);
        printf(WALL);
    }
}

//创建结点
pSnakeNode BuyNode()
{
    pSnakeNode pRet = (pSnakeNode)malloc(sizeof(SnakeNode));

    if (pRet == NULL)
    {
        perror("BuyNode::malloc()");
        exit(EXIT_FAILURE);
    }
    pRet->next = NULL;
    pRet->x = 0;
    pRet->y = 0;

    return pRet;
}


void InitSnake(pSnake ps)
{
    //蛇刚开始时的位置
    pSnakeNode first = BuyNode();
    first->x = X_INIT;
    first->y = Y_INIT;


    for (int i = 0; i < 4; i++)
    {
        pSnakeNode cur = BuyNode();
        cur->x = first->x + 2 ;
        cur->y = first->y;

        //头插
        cur->next = first;
        first = cur;
    }
    //蛇结点的连接
    pSnakeNode pCur = first;
    while (pCur != NULL)
    {
        SetPos(pCur->x, pCur->y);
        printf(FOOD);
        pCur = pCur->next;
    }
    printf("\n");
    ps->_psnake = first;  //记住位置
}

void CreateFood(pSnake ps)
{
    //随机创建食物
    pSnakeNode pFood = BuyNode();
    pSnakeNode pCur = ps->_psnake;
    pFood->y = rand() % 26 + 1;
    do  //生成x坐标
    {
        pFood->x = rand()%55+2;
    } while (pFood->x%2!=0);

    //x,y符合要求,判断创建是否和蛇身重叠

    while (pCur)
    {
        if (pCur->x == pFood->x&&pCur->y == pFood->y)
        {
            //递归调用
        }
        pCur = pCur->next;
    }
    ps->_pFood = pFood;
    SetPos(pFood->x,pFood->y);
    printf(FOOD);


}

void GameStart(pSnake ps)
{
    //打印欢迎界面
    WelcomToGame();
    //创建窗口
    CreateMap();
    //初始化蛇
    InitSnake(ps);
    //初始化食物
    CreateFood(ps);

    ps->_AddScore = 10;
    ps->TotalScore = 0;
    ps->_dir = RIGHT;
    ps->_SleepTime = 200;
    ps->_Status = OK;
}


void Pause()
{
    //睡眠,空格暂停,再次空格启动
    while (1)
    {
        Sleep(100);
        if (GetAsyncKeyState(VK_SPACE))
        {
            break;
        }
    }
}

int NextHasFood(pSnakeNode pn,pSnakeNode pf)
{
    return (pn->x == pf->x)&& (pn->y == pf->y);
}


void EatFood(pSnake ps, pSnakeNode pn)
{
    pSnakeNode Cur = NULL;
    pn->next = ps->_psnake;
    ps->_psnake = pn;

    Cur = ps->_psnake;
    ps->TotalScore += ps->_AddScore;

    while (Cur)
    {
        SetPos(Cur->x, Cur->y);
        printf(FOOD);
        Cur = Cur->next;
    }

    CreateFood(ps);
}

void NotFood(pSnake ps, pSnakeNode pn)
{
    pSnakeNode Cur = NULL;
    pn->next = ps->_psnake;
    ps->_psnake = pn;
    Cur = ps->_psnake;
    while (Cur->next->next)
    {
        SetPos(Cur->x, Cur->y);
        printf(FOOD);
        Cur = Cur->next;
    }

    SetPos(Cur->x, Cur->y);
    printf(FOOD);

    SetPos(Cur->next->x, Cur->next->y);
    printf(" ");
    free(Cur->next);
    Cur->next = NULL;
}

void SnakeMove(pSnake ps)
{
    pSnakeNode pNextNode = BuyNode();
    SetPos(65, 8);
    printf("总分:%d ", ps->TotalScore);
    SetPos(65,9);
    printf("每个食物的得分:%d ", ps->_AddScore);
    switch (ps->_dir){
    case UP:
        {
               pNextNode->x = ps->_psnake->x;
               pNextNode->y = ps->_psnake->y - 1;
               if (NextHasFood(pNextNode, ps->_pFood))
               {
                   //下一个结点是食物
                   EatFood(ps, pNextNode);
               }
               else{

                   NotFood(ps, pNextNode);
               }
        }
        break;
    case DOWN:
    {
                 pNextNode->x = ps->_psnake->x;
                 pNextNode->y = ps->_psnake->y + 1;
                 if (NextHasFood(pNextNode, ps->_pFood))
                 {
                     //下一个结点是食物
                     EatFood(ps, pNextNode);
                 }
                 else{

                     NotFood(ps, pNextNode);
                 }
    }
        break;
    case LEFT:
    {
        pNextNode->x = ps->_psnake->x - 2;
        pNextNode->y = ps->_psnake->y;
        if (NextHasFood(pNextNode, ps->_pFood))
        {
            //下一个结点是食物
            EatFood(ps, pNextNode);
        }
        else{

            NotFood(ps, pNextNode);
        }
    }
        break;
    case RIGHT:
    {
                  pNextNode->x = ps->_psnake->x+2;
                  pNextNode->y = ps->_psnake->y;
                  if (NextHasFood(pNextNode, ps->_pFood))
                  {
                      //下一个结点是食物
                      EatFood(ps, pNextNode);
                  }
                  else{

                      NotFood(ps, pNextNode);
                  }
    }

        break;
    }
}

void KillByWall(pSnake ps)
{
    //判断头
    if (ps->_psnake->x == 2
        || ps->_psnake->x == 58
        || ps->_psnake->y == 0
        || ps->_psnake->y == 27)
    {
        ps->_Status = KILL_BY_WALL;
    }

}
void KillBySelf(pSnake ps)
{
    pSnakeNode pNext= ps->_psnake->next;
    while(pNext)
    {
        if ((pNext->x == ps->_psnake->x) && (pNext->y == ps->_psnake->y))
        {
            ps->_Status = KILL_BY_SELF;
            return;
        }
        pNext = pNext->next;
    }
}

void PrintHelpInfo()
{
    SetPos(65, 12);
    printf("用↑.↓.←.→来控制蛇的移动");
    SetPos(65, 13);
    printf("F1为加速,F2为减速");
    SetPos(65, 14);
    printf("按ESC退出游戏");
    SetPos(65, 15);
    printf("按空格暂停游戏");
    SetPos(65, 14);
    printf("按ESC退出游戏");

}


void GameRun(pSnake ps)
{
    HideCursor();
    //检测状态
    //蛇的移动
    PrintHelpInfo();
    do
    {
        //确定方向
        if (GetAsyncKeyState(VK_UP) && ps->_dir != DOWN)
        {
            ps->_dir = UP;
        }
        else if (GetAsyncKeyState(VK_DOWN) && ps->_dir != UP)
        {
            ps->_dir = DOWN;
        }
        else if (GetAsyncKeyState(VK_LEFT) && ps->_dir != RIGHT)
        {
            ps->_dir = LEFT;
        }
        else if (GetAsyncKeyState(VK_RIGHT) && ps->_dir != LEFT)
        {
            ps->_dir = RIGHT;
        }
        else if (GetAsyncKeyState(VK_SPACE))
        {
            //暂停游戏
            Pause();
        }
        else if (GetAsyncKeyState(VK_ESCAPE))
        {
            //结束游戏
            ps->_Status = NORMAL_END;
            break;
        }
        else if (GetAsyncKeyState(VK_F1))
        {
            //加速
            if (ps->_SleepTime >= 40)
            {
                ps->_SleepTime -= 20;
                ps->_AddScore += 2;
            }
        }
        else if (GetAsyncKeyState(VK_F2))
        {
            //减速
            if (ps->_SleepTime <= 300)
            {
                ps->_SleepTime += 20;

                ps->_AddScore -= 2;
            }
            if (ps->_SleepTime > 300)
            {
                ps->_AddScore = 1;
            }
        }
        Sleep(ps->_SleepTime);
        //蛇移动
        SnakeMove(ps);
        KillByWall(ps);
        KillBySelf(ps);


    } while (ps->_Status == OK);
}


void GameEnd(pSnake ps)
{
    pSnakeNode pCur = ps->_psnake;
    SetPos(26, 14);
    if (ps->_Status == NORMAL_END)
    {
        printf("正常结束游戏\n");
    }
    else if (ps->_Status == KILL_BY_SELF)
    {
        printf("撞上自己\n");
    }
    else if (ps->_Status == KILL_BY_WALL)
    {
        printf("撞墙\n");
    }

    while (pCur)
    {
        pSnakeNode pDel = pCur;
        pCur = pCur->next;
        free(pDel);
        pDel = NULL;
    }
    ps->_psnake = NULL;
    free(ps->_pFood);
    ps->_pFood = NULL;
}
main.c


#include
#include"snake.h"

void test()
{
    //初始化一条蛇
    Snake snake = { 0 };
    srand((unsigned int)time(NULL));

        GameStart(&snake);

    GameRun(&snake);
    GameEnd(&snake);
}

int main()
{
    test();
    return 0;
}
效果如下图:

你可能感兴趣的:(贪吃蛇)