当前位置:   article > 正文

C语言小游戏 ---- 贪吃蛇_调整贪食蛇窗口大小

调整贪食蛇窗口大小

贪吃蛇是一个生活中很常见的小游戏,相信大家都玩过吧,下面我来说说具体的实现步骤。完整代码在文章最后

实现环境:VS2017

贪吃蛇具有以下功能:
1.按F1加速,F2减速。加速食物的分数增高,减速食物的分数降低
2.按空格暂停
3.按ESC退出游戏

下面有两种贪吃蛇:

  1. 撞墙会死
  2. 撞墙不会死

撞墙会死版贪吃蛇

1.首先实现刚开始的游戏界面,如下图

这里写图片描述
这里写图片描述

这里需要知道怎么控制光标的位置,以及怎样设定窗口的大小
设定窗口的大小
使用system库函数和DOS命令设置控制台窗口

system(“mode con cols=100 lises=30”);
//mode 为DOS命令
//cols —- 设置控制台的列数
//lines —- 设置控制台的行数

控制光标的位置
HANDLE GetStdHandle( DWORD nStdHandle );

//返回标准的输入、输出或错误的设备的 句柄,也就是获得输入、输出/错误的屏幕 缓冲区的句柄。
参数为三种
STD_INPUT_HANDLE //标准输入的句柄
STD_OUTPUT_HANDLE //标准输出的句柄
STD_ERROR_HANDLE //标准错误的句柄

BOOL SetConsoleCursorPosition( HANDLE hConsoleOutput, COORD dwCursorPosition );

如果用户定义了COORD pos,那么pos其实是一个结构体变量,其中X和Y是它的成员,通过修改pos.X和pos.Y的值就可以实现光标的位置控制
用例:SetConsoleCursorPosition(handle, pos);

知道了这两个函数我们的清屏就很好实现了

void SetPos(int x, int y)
{
    COORD pos = { 0 };
    HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);//获取设备
    pos.X = x;
    pos.Y = y;
    SetConsoleCursorPosition(handle, pos);
}
void WelcomeToGame()
{
    //窗口大小
    system("mode con cols=100 lines=30");
    SetPos(39, 14);
    printf("欢迎来到贪吃蛇游戏");
    Sign();
    SetPos(39, 25);
    system("pause");//暂停
    system("cls");//清屏
    SetPos(25, 14);
    printf("用↑,↓,←,→来控制蛇的移动,F1为加速,F2为减速");
    SetPos(35, 15);
    printf("提示:加速获得的分数更高");
    Sign();
    SetPos(39, 25);
    system("pause");
    system("cls");

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28

2.绘制地图

这里写图片描述

因为上图的小方框是输入法中的特殊字符,一个小方框站两个X单位一个Y单位。

根据上图,实现代码如下:

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, 29);
        printf(WALL);
    }
    //左
    for (i = 1; i <= 28; i++)
    {
        SetPos(0, i);
        printf(WALL);
    }
    //右
    for (i = 1; i <= 28; i++)
    {
        SetPos(58, i);
        printf(WALL);
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28

3.绘制蛇

这里的蛇使用链表保存,所以需要蛇身体节点,以及维护整条蛇的数据,另外蛇的前进放向以及游戏的运行状态我们定义成枚举。

typedef struct SnakeNode
{
    int x;
    int y;
    struct SnakeNode* next;
}SnakeNode,*pSnakeNode;

enum Dirction { 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 Dirction _Dir;//方向
    enum GameStatus _Status;//游戏状态
}Snake,*pSnake;

pSnakeNode BuyNode()
{
    pSnakeNode NewNode = (pSnakeNode)malloc(sizeof(SnakeNode));
    if (NewNode == NULL)
    {
        perror("BuyNode::malloc( )");
        exit(EXIT_FAILURE);
    }
    NewNode->x = 0;
    NewNode->y = 0;
    NewNode->next = NULL;
    return NewNode;
}

void InitSnake(pSnake snake)
{
    int i = 0;
    pSnakeNode Cur = NULL;
    pSnakeNode first = BuyNode();
    first->x = INIT_X;
    first->y = INIT_Y;
    for (i = 0; i < 4; i++)
    {
        Cur = BuyNode();
        Cur->x = first->x - 2;
        Cur->y = first->y;
        Cur->next = first;
        first = Cur;
    }
    while (Cur)
    {
        SetPos(Cur->x, Cur->y);
        printf(Food);
        Cur = Cur->next;
    }
    snake->_pSnake = first;
    Sign();
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59

4.产生食物

这里会用到随机函数,注意食物不能出现在墙以及墙以外和蛇身上
如下图为处是状态
这里写图片描述

void CreateFood(pSnake snake)
{

    pSnakeNode pFood = NULL;
    pFood = BuyNode();
    pSnakeNode Cur = snake->_pSnake;
    pFood->y = rand() % 28 + 1;
    do 
    {
        pFood->x = rand() % 55 + 2;
    } while (pFood->x % 2 != 0);
    while (Cur)
    {
        if (Cur->x == pFood->x && Cur->y == pFood->y)
        {
            CreateFood(snake);
            return;
        }
        Cur = Cur->next;
    }
    snake->_pFood = pFood;
    SetPos(pFood->x, pFood->y);
    printf(Food);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

4.让蛇动起来

根据pSnake中定义的方向,进行移动,如果有食物,就吃掉,并且身体长长

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

void EatFood(pSnakeNode pn,pSnake ps)
{
    pn->next = ps->_pSnake;
    ps->_pSnake = pn;
    SetPos(ps->_pSnake->x, ps->_pSnake->y);
    printf(Food);
    ps->ToTalScore += ps->_AddScore;
    CreateFood(ps);
}

void NoFood(pSnakeNode pn, pSnake ps)
{
    pSnakeNode Cur = NULL;
    pn->next = ps->_pSnake;
    ps->_pSnake = pn;
    SetPos(pn->x, pn->y);
    printf(Food);
    Cur = ps->_pSnake;
    while (Cur->next->next)
    {
        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;
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103

5.获取键盘上的方向键,控制蛇

Windows下的int GetAsyncKeyState(int vkey)函数,自上次调用以来,如果对应 的键被按下,则返回1,否则返回0。


void PrintfHelpInfo(pSnake ps)
{
    SetPos(70, 9);
    printf("总分:%d  ", ps->ToTalScore);
    SetPos(70, 10);
    printf("单次吃食物得分:%d  ", ps->_AddScore);
    SetPos(70, 15);
    printf("用↑,↓,←,→来控制蛇的移动");
    SetPos(70, 16);
    printf("F1为加速,F2为减速");
    SetPos(70, 17);
    printf("按空格暂停");
    SetPos(70, 18);
    printf("按Esc退出");

}

void KillBySelf(pSnake ps)
{
    pSnakeNode Cur = NULL;
    Cur = ps->_pSnake->next;
    while (Cur)
    {
        if (ps->_pSnake->x == Cur->x && ps->_pSnake->y == Cur->y)
        {
            ps->_Status = KILL_BY_SELF;
            break;
        }
        Cur = Cur->next;
    }

}

void KillByWall(pSnake ps)
{
    if (ps->_pSnake->x == 0 || ps->_pSnake->x == 58//蛇撞墙会死
        || ps->_pSnake->y == 0 || ps->_pSnake->y == 29)
    {
        ps->_Status = KILL_BY_WALL;

    }

}
void GameRun(pSnake ps)
{
    do
    {
        PrintfHelpInfo(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 >= 100)
            {
                ps->_AddScore += 2;
                ps->_SleepTime -= 20;
            }
        }
        else if (GetAsyncKeyState(VK_F2))//减速
        {
            if (ps->_SleepTime <= 300)
            {
                if (ps->_AddScore > 2)
                {
                    ps->_AddScore -= 2;
                }

                ps->_SleepTime += 20;
            }
        }
        Sleep(ps->_SleepTime);
        SnakeMove(ps);
        //蛇移动
        KillBySelf(ps);
        KillByWall(ps);
    } while (ps->_Status == OK);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93

6.判断游戏结束

void GameEnd(pSnake ps)
{
    switch (ps->_Status)
    {
    case KILL_BY_SELF:
    {
        SetPos(24, 15);
        printf("撞身体");
        SetPos(22, 16);
        printf("GAME OVER!!!");
    }
    break;
    case KILL_BY_WALL://撞墙会死
    {
        SetPos(24, 15);
        printf("撞墙");
        SetPos(22, 16);
        printf("GAME OVER!!!");
    }
    break;
    }
    pSnakeNode Cur = ps->_pSnake;
    pSnakeNode Del = NULL;
    while (Cur)
    {
        Del = Cur;
        Cur = Cur->next;
        free(Del);
    }
    Del = NULL;
    free(ps->_pFood);
    ps->_pFood = NULL;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33

以上就是基本原理,下面是源代码

//snake.h

#pragma once
#include<Windows.h>
#include<stdio.h>
#include<time.h>
#include<stdlib.h>

#define WALL "■"
#define Food "□"
#define SIGN "@"
#define INIT_X 30
#define INIT_Y 10

typedef struct SnakeNode
{
    int x;
    int y;
    struct SnakeNode* next;
}SnakeNode,*pSnakeNode;

enum Dirction { 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 Dirction _Dir;//方向
    enum GameStatus _Status;//游戏状态
}Snake,*pSnake;


void  GameStart(pSnake snake);
void SetPos(int x, int y);
void WelcomeToGame();
void CreateMap();
void InitSnake(pSnake snake);
void CreateFood(pSnake snake);



void GameRun(pSnake ps);
void EatFood(pSnakeNode pn, pSnake ps);
void NoFood(pSnakeNode pn, pSnake ps);
void SnakeMove(pSnake ps);
void PrintfHelpInfo(pSnake ps);
void KillBySelf(pSnake ps);
void KillByWall(pSnake ps);


void GameEnd(pSnake ps);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
//snake.c
#include"snake.h"

void SetPos(int x, int y)
{
    COORD pos = { 0 };
    HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);//获取设备
    pos.X = x;
    pos.Y = y;
    SetConsoleCursorPosition(handle, pos);
}

void Sign()
{
    SetPos(88, 27);
    printf(SIGN);
    printf("阿巴卡");
}

void WelcomeToGame()
{
    //窗口大小
    system("mode con cols=100 lines=30");
    SetPos(39, 14);
    printf("欢迎来到贪吃蛇游戏");
    Sign();
    SetPos(39, 25);
    system("pause");
    system("cls");//清屏
    SetPos(25, 14);
    printf("用↑,↓,←,→来控制蛇的移动,F1为加速,F2为减速");
    SetPos(35, 15);
    printf("提示:加速获得的分数更高");
    Sign();
    SetPos(39, 25);
    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, 29);
        printf(WALL);
    }
    //左
    for (i = 1; i <= 28; i++)
    {
        SetPos(0, i);
        printf(WALL);
    }
    //右
    for (i = 1; i <= 28; i++)
    {
        SetPos(58, i);
        printf(WALL);
    }
}

pSnakeNode BuyNode()
{
    pSnakeNode NewNode = (pSnakeNode)malloc(sizeof(SnakeNode));
    if (NewNode == NULL)
    {
        perror("BuyNode::malloc( )");
        exit(EXIT_FAILURE);
    }
    NewNode->x = 0;
    NewNode->y = 0;
    NewNode->next = NULL;
    return NewNode;
}

void InitSnake(pSnake snake)
{
    int i = 0;
    pSnakeNode Cur = NULL;
    pSnakeNode first = BuyNode();
    first->x = INIT_X;
    first->y = INIT_Y;
    for (i = 0; i < 4; i++)
    {
        Cur = BuyNode();
        Cur->x = first->x - 2;
        Cur->y = first->y;
        Cur->next = first;
        first = Cur;
    }
    while (Cur)
    {
        SetPos(Cur->x, Cur->y);
        printf(Food);
        Cur = Cur->next;
    }
    snake->_pSnake = first;
    Sign();
}

void CreateFood(pSnake snake)
{

    pSnakeNode pFood = NULL;
    pFood = BuyNode();
    pSnakeNode Cur = snake->_pSnake;
    pFood->y = rand() % 28 + 1;
    do 
    {
        pFood->x = rand() % 55 + 2;
    } while (pFood->x % 2 != 0);
    while (Cur)
    {
        if (Cur->x == pFood->x && Cur->y == pFood->y)
        {
            CreateFood(snake);
            return;
        }
        Cur = Cur->next;
    }
    snake->_pFood = pFood;
    SetPos(pFood->x, pFood->y);
    printf(Food);
}



void  GameStart(pSnake snake)
{
    //打印界面
    WelcomeToGame();

    //创建地图
    CreateMap();

    //初始化蛇
    InitSnake(snake);

    //初始化食物
    CreateFood(snake);

    snake->ToTalScore = 0;
    snake->_AddScore = 10;
    snake->_Dir = LEFT;
    snake->_SleepTime = 200;
    snake->_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)
{
    pn->next = ps->_pSnake;
    ps->_pSnake = pn;
    SetPos(ps->_pSnake->x, ps->_pSnake->y);
    printf(Food);
    ps->ToTalScore += ps->_AddScore;
    CreateFood(ps);
}

void NoFood(pSnakeNode pn, pSnake ps)
{
    pSnakeNode Cur = NULL;
    pn->next = ps->_pSnake;
    ps->_pSnake = pn;
    SetPos(pn->x, pn->y);
    printf(Food);
    Cur = ps->_pSnake;
    while (Cur->next->next)
    {
        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;
    }
}

void PrintfHelpInfo(pSnake ps)
{
    SetPos(70, 9);
    printf("总分:%d  ", ps->ToTalScore);
    SetPos(70, 10);
    printf("单次吃食物得分:%d  ", ps->_AddScore);
    SetPos(70, 15);
    printf("用↑,↓,←,→来控制蛇的移动");
    SetPos(70, 16);
    printf("F1为加速,F2为减速");
    SetPos(70, 17);
    printf("按空格暂停");
    SetPos(70, 18);
    printf("按Esc退出");

}

void KillBySelf(pSnake ps)
{
    pSnakeNode Cur = NULL;
    Cur = ps->_pSnake->next;
    while (Cur)
    {
        if (ps->_pSnake->x == Cur->x && ps->_pSnake->y == Cur->y)
        {
            ps->_Status = KILL_BY_SELF;
            break;
        }
        Cur = Cur->next;
    }

}

void KillByWall(pSnake ps)
{
    if (ps->_pSnake->x == 0 || ps->_pSnake->x == 58//蛇撞墙会死
        || ps->_pSnake->y == 0 || ps->_pSnake->y == 29)
    {
        ps->_Status = KILL_BY_WALL;

    }

}

void GameRun(pSnake ps)
{
    do
    {
        PrintfHelpInfo(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 >= 100)
            {
                ps->_AddScore += 2;
                ps->_SleepTime -= 20;
            }
        }
        else if (GetAsyncKeyState(VK_F2))//减速
        {
            if (ps->_SleepTime <= 300)
            {
                if (ps->_AddScore > 2)
                {
                    ps->_AddScore -= 2;
                }

                ps->_SleepTime += 20;
            }
        }
        Sleep(ps->_SleepTime);
        SnakeMove(ps);
        //蛇移动
        KillBySelf(ps);
        KillByWall(ps);
    } while (ps->_Status == OK);
}


void GameEnd(pSnake ps)
{
    switch (ps->_Status)
    {
    case KILL_BY_SELF:
    {
        SetPos(24, 15);
        printf("撞身体");
        SetPos(22, 16);
        printf("GAME OVER!!!");
    }
    break;
    case KILL_BY_WALL://撞墙会死
    {
        SetPos(24, 15);
        printf("撞墙");
        SetPos(22, 16);
        printf("GAME OVER!!!");
    }
    break;
    }
    pSnakeNode Cur = ps->_pSnake;
    pSnakeNode Del = NULL;
    while (Cur)
    {
        Del = Cur;
        Cur = Cur->next;
        free(Del);
    }
    Del = NULL;
    free(ps->_pFood);
    ps->_pFood = NULL;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212
  • 213
  • 214
  • 215
  • 216
  • 217
  • 218
  • 219
  • 220
  • 221
  • 222
  • 223
  • 224
  • 225
  • 226
  • 227
  • 228
  • 229
  • 230
  • 231
  • 232
  • 233
  • 234
  • 235
  • 236
  • 237
  • 238
  • 239
  • 240
  • 241
  • 242
  • 243
  • 244
  • 245
  • 246
  • 247
  • 248
  • 249
  • 250
  • 251
  • 252
  • 253
  • 254
  • 255
  • 256
  • 257
  • 258
  • 259
  • 260
  • 261
  • 262
  • 263
  • 264
  • 265
  • 266
  • 267
  • 268
  • 269
  • 270
  • 271
  • 272
  • 273
  • 274
  • 275
  • 276
  • 277
  • 278
  • 279
  • 280
  • 281
  • 282
  • 283
  • 284
  • 285
  • 286
  • 287
  • 288
  • 289
  • 290
  • 291
  • 292
  • 293
  • 294
  • 295
  • 296
  • 297
  • 298
  • 299
  • 300
  • 301
  • 302
  • 303
  • 304
  • 305
  • 306
  • 307
  • 308
  • 309
  • 310
  • 311
  • 312
  • 313
  • 314
  • 315
  • 316
  • 317
  • 318
  • 319
  • 320
  • 321
  • 322
  • 323
  • 324
  • 325
  • 326
  • 327
  • 328
  • 329
  • 330
  • 331
  • 332
  • 333
  • 334
  • 335
  • 336
  • 337
  • 338
  • 339
  • 340
  • 341
  • 342
  • 343
  • 344
  • 345
  • 346
  • 347
  • 348
  • 349
  • 350
  • 351
  • 352
  • 353
  • 354
  • 355
  • 356
  • 357
  • 358
  • 359
  • 360
  • 361
  • 362
  • 363
  • 364
  • 365
  • 366
  • 367
  • 368
  • 369
  • 370
  • 371
  • 372
  • 373
  • 374
  • 375
  • 376
  • 377
  • 378
  • 379
  • 380
  • 381
  • 382
  • 383
  • 384
  • 385
  • 386
  • 387
  • 388
  • 389
  • 390
  • 391
  • 392
  • 393
  • 394
  • 395
  • 396
  • 397
  • 398
//test.c

#include"snake.h"

void test()
{
    Snake snake = { 0 };
    srand((unsigned)time(NULL));
    GameStart(&snake);
    GameRun(&snake);
    GameEnd(&snake);
}

int main()
{
    test();
    SetPos(20, 20);
    system("pause");
    return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

具体实现形式:
这里写图片描述

撞墙不会死

其实撞墙不会死的情况与撞墙会死的情况以下几个函数不一样

void GameEnd(pSnake ps);
void KillByWall(pSnake ps);
void NoFood(pSnakeNode pn, pSnake ps);
代码如下:

void NoFood(pSnakeNode pn, pSnake ps)
{
    pSnakeNode Cur = NULL;
    pn->next = ps->_pSnake;
    ps->_pSnake = pn;
    SetPos(pn->x, pn->y);
    printf(Food);
    Cur = ps->_pSnake;
    while (Cur->next->next)
    {
        Cur = Cur->next;
        SetPos(Cur->x, Cur->y);
        printf(Food);
    }
    if (Cur->next->x == 0 || Cur->next->x == 58
        || Cur->next->y == 0 || Cur->next->y == 29)
    {
        SetPos(Cur->next->x, Cur->next->y);
        printf(WALL);

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

void KillByWall(pSnake ps)
{
    pSnakeNode pn = BuyNode();
    if (ps->_pSnake->x == 0)//撞左墙
    {

        pn->x = ps->_pSnake->x + 56;
        pn->y = ps->_pSnake->y;
        if (NextHasFood(pn, ps->_pFood))
        {
            EatFood(pn, ps);
        }
        else
        {
            NoFood(pn, ps);
        }
    }

    if (ps->_pSnake->x == 58)//撞右墙
    {

        pn->x = ps->_pSnake->x - 56;
        pn->y = ps->_pSnake->y;
        if (NextHasFood(pn, ps->_pFood))
        {
            EatFood(pn, ps);
        }
        else
        {
            NoFood(pn, ps);
        }
    }

    if (ps->_pSnake->y == 0)//撞上墙
    {

        pn->x = ps->_pSnake->x;
        pn->y = ps->_pSnake->y + 28;
        if (NextHasFood(pn, ps->_pFood))
        {
            EatFood(pn, ps);
        }
        else
        {
            NoFood(pn, ps);
        }
    }

    if (ps->_pSnake->y == 29)//撞下墙
    {

        pn->x = ps->_pSnake->x;
        pn->y = ps->_pSnake->y - 28;
        if (NextHasFood(pn, ps->_pFood))
        {
            EatFood(pn, ps);
        }
        else
        {
            NoFood(pn, ps);
        }
    }

}

void GameEnd(pSnake ps)
{
    switch (ps->_Status)
    {
    case KILL_BY_SELF:
    {
        SetPos(24, 15);
        printf("撞身体");
        SetPos(22, 16);
        printf("GAME OVER!!!");
    }
    break;
    }
    pSnakeNode Cur = ps->_pSnake;
    pSnakeNode Del = NULL;
    while (Cur)
    {
        Del = Cur;
        Cur = Cur->next;
        free(Del);
    }
    Del = NULL;
    free(ps->_pFood);
    ps->_pFood = NULL;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120

要想实现不会撞墙死的贪吃蛇,只需要将这几个函数与撞墙会死中相对应的函数进行替换就可以
具体实现结果:

这里写图片描述

这里写图片描述

如果有疑问或者有什么更好的建议欢迎留言。

声明:本文内容由网友自发贡献,转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号