简易的贪吃蛇小游戏

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/zhang21722668/article/details/82189414
/***********************************************/
//Snake.h


#ifndef __SNAKE_H__
#define __SNAKE_H__

#include <Windows.h>
#include <stdio.h>
#include <stdlib.h>

#define WALL "◆"
#define FOOD "■"

#define INIT_X 10
#define INIT_Y 10

//蛇身结点
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; //维护食物位置
    int _TotalScore;  //总分数
    int _AddScore;   //增加的分数
    int _SleepTime;  //休眠时间
    enum Direction _Dir;//蛇头方向默认向右
    enum GameStatus _Status;//游戏状态
}Snake, *pSnake;


//打印欢迎界面
void WelcomeToGame();

//创建地图
void CreateMap();

//初始化蛇
void InitSnake(pSnake ps);

//初始化食物
void CreateFood(pSnake ps);

//创建贪吃蛇
void GameStart(pSnake ps);

//暂停游戏
void Pause();

//判断下一步是不是食物
int NextHasFood(pSnakeNode pn, pSnakeNode pf);

//吃食物
void EatFood(pSnakeNode pn, pSnake ps);

//没有食物吃
void NoFood(pSnakeNode pn, pSnake ps);

//蛇的移动
void SnakeMove(pSnake ps);

//撞墙
int KillByWall(pSnake ps);

//撞到自身
int KillBySelf(pSnake ps);

//打印帮助信息
PrintHelpInfo(pSnake ps);

//游戏开始跑起来
void GameRun(pSnake ps);

//结束游戏
void GameEnd(pSnake ps);


#endif //__SNAKE_H__




/***********************************************/
//Snake.c


#include "Snake.h"


//创新结点
pSnakeNode BuyNode()
{
    pSnakeNode pRet = (pSnakeNode)malloc(sizeof(SnakeNode));
    if (NULL == pRet)
    {
        perror("BuyNode::malloc()");
        exit(EXIT_FAILURE);
    }
    pRet->x = 0;
    pRet->y = 0;
    pRet->next = NULL;

    return pRet;
}

//设置位置函数
void SetPos(int x, int y)
{
    COORD pos = { 0 };
    HANDLE hOutput = NULL;

    pos.X = x;
    pos.Y = y;

    hOutput = GetStdHandle(STD_OUTPUT_HANDLE);
    SetConsoleCursorPosition(hOutput, pos);
}

//打印欢迎界面
void WelcomeToGame()
{
    //设置窗口大小
    system("mode con cols=120 lines=30");
    SetPos(45, 14);
    printf("欢迎来到贪吃蛇小游戏.");
    SetPos(45, 28);
    system("pause");
    system("cls");
    SetPos(40, 13);
    printf("用 ↑ ↓ ← → 来控制蛇的移动. F1为加速.F2为减速.");
    SetPos(40, 15);
    printf("加速获得分数更高");
    SetPos(40, 28);
    system("pause");
    system("cls");

}

//创建地图
void CreateMap()
{
    int i;
    SetPos(0, 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);
    }
}

//初始化蛇
void InitSnake(pSnake ps)
{
    pSnakeNode first = BuyNode();
    pSnakeNode cur = NULL;
    int i = 0;
    first->x = INIT_X;//蛇在地图中的起始位置
    first->y = INIT_Y;

    for (i = 1; i <= 4; i++)//蛇的起始长度为5☆
    {
        cur = BuyNode();
        cur->x = first->x + 2;
        cur->y = first->y;
        cur->next = first;
        first = cur;
    }

    cur = first;
    while (cur)
    {
        SetPos(cur->x, cur->y);
        printf(FOOD);
        SetPos(60, 27);
        cur = cur->next;
    }
    ps->_psnake = first;
}

//初始化食物
void CreateFood(pSnake ps)
{
    pSnakeNode pfood = BuyNode();
    pSnakeNode cur = ps->_psnake;
    pfood->y = rand() % 25 + 1;
    do
    {
        //0-56
        pfood->x = rand() % 55 + 2;
    } while (pfood->x % 2 != 0);

    while (cur)
    {
        if (cur->x == pfood->x && cur->y == pfood->y)
        {
            CreateFood(ps);
            return;
        }
        cur = cur->next;
    }
    ps->_pFood = pfood;
    SetPos(pfood->x, pfood->y);
    printf(FOOD);
    //SetPos(60, 27);
}

//创建贪吃蛇
void GameStart(pSnake ps)
{
    //打印欢迎界面
    WelcomeToGame();

    //创建地图
    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(pSnakeNode pn, pSnake ps)
{
    pSnakeNode cur = NULL;
    pn->next = ps->_psnake;
    ps->_psnake = pn;
    cur = ps->_psnake;

    while (cur != NULL)
    {
        SetPos(cur->x, cur->y);
        printf(FOOD);
        cur = cur->next;
    }
    ps->_TotalScore += ps->_AddScore;
    CreateFood(ps);
}

//没有食物吃
void NoFood(pSnakeNode pn, pSnake ps)
{
    pSnakeNode cur = NULL;
    pn->next = ps->_psnake;
    ps->_psnake = pn;

    cur = ps->_psnake;
    while (cur->next->next != NULL)
    {
        SetPos(cur->x, cur->y);
        printf(FOOD);
        cur = cur->next;
    }
    SetPos(cur->next->x, cur->next->y);
    printf(" ");
    free(cur->next);
    cur->next = NULL;
}

//蛇的移动
void SnakeMove(pSnake ps)
{
    pSnakeNode pNextNode = BuyNode();

    switch (ps->_Dir)
    {
    case UP:
        pNextNode->x = ps->_psnake->x;
        pNextNode->y = ps->_psnake->y-1;
        if (NextHasFood(pNextNode, ps->_pFood))
        {
            EatFood(pNextNode, ps);
        }
        else
        {
            NoFood(pNextNode, ps);
        }
        break;
    case DOWN:
        pNextNode->x = ps->_psnake->x;
        pNextNode->y = ps->_psnake->y+1;
        if (NextHasFood(pNextNode, ps->_pFood))
        {
            EatFood(pNextNode, ps);
        }
        else
        {
            NoFood(pNextNode, ps);
        }
        break;
    case LEFT:
        pNextNode->x = ps->_psnake->x-2;
        pNextNode->y = ps->_psnake->y;
        if (NextHasFood(pNextNode, ps->_pFood))
        {
            EatFood(pNextNode, ps);
        }
        else
        {
            NoFood(pNextNode, ps);
        }
        break;
    case RIGHT:
        pNextNode->x = ps->_psnake->x+2;
        pNextNode->y = ps->_psnake->y;
        if (NextHasFood(pNextNode, ps->_pFood))
        {
            EatFood(pNextNode, ps);
        }
        else
        {
            NoFood(pNextNode, ps);
        }
        break;
    }
}

//撞墙
int KillByWall(pSnake ps)
{
    if ((ps->_psnake->x == 0)
        || (ps->_psnake->x == 58)
        || (ps->_psnake->y == 0)
        || (ps->_psnake->y == 27))
    {
        ps->_Status = KILL_BY_WALL;
    }
}

//撞到自身
int KillBySelf(pSnake ps)
{
    pSnakeNode pNext = ps->_psnake->next;

    while (pNext != NULL)
    {
        if (pNext->x == ps->_psnake->x && pNext->y == ps->_psnake->y)
        {
            ps->_Status = KILL_BY_SELF;
            return;
        }
        pNext = pNext->next;
    }
}

//打印帮助信息
PrintHelpInfo(pSnake ps)
{
    SetPos(61, 6);
    printf("总分 = %d", ps->_TotalScore);
    SetPos(61, 8);
    printf("蛇移动的时间 = %d", ps->_SleepTime);
    SetPos(61, 10);
    printf("加减速变化的分数 = %d ", ps->_AddScore);

    SetPos(61, 15);
    printf("用 ↑ ↓ ← → 来控制蛇的移动. F1为加速.F2为减速.");
    SetPos(61, 17);
    printf("空格暂停游戏");
    SetPos(61, 19);
    printf("按 ESC键 退出游戏");



}

//游戏开始跑起来
void GameRun(pSnake ps)
{
    do
    {
        PrintHelpInfo(ps);//帮助提示
        //确定方向
        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;
            }

        }

        Sleep(ps->_SleepTime);

        //蛇的移动
        SnakeMove(ps);

        KillByWall(ps);

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

//结束游戏
void GameEnd(pSnake ps)
{
    pSnakeNode del;
    pSnakeNode cur = ps->_psnake;
    SetPos(20, 12);
    switch(ps->_Status)
    {
        case NORMAL_END:
            printf("游戏正常结束!");
            SetPos(61, 27);
            break;
        case KILL_BY_WALL:
            printf("你撞墙了!");
            SetPos(61, 27);
            break;
        case KILL_BY_SELF:
            printf("你把自己咬了!");
            SetPos(61, 27);
            break;
    }

    while (cur)
    {
        del = cur;
        cur = cur->next;
        free(del);
        del = NULL;
    }
}



/***********************************************/
//test.c


#include "Snake.h"

void test()
{
    Snake snake = { 0 };
    srand((unsigned int)time(NULL));
    GameStart(&snake);//创建贪吃蛇
    GameRun(&snake);
    GameEnd(&snake);
}

int main()
{
    test();
    system("pause");
    return 0;
}

猜你喜欢

转载自blog.csdn.net/zhang21722668/article/details/82189414