C--贪吃蛇

news2024/11/26 14:24:14

目录

前言

简单的准备工作

蛇的节点

开始前 void GameStart(pSnake ps)

void WelcomeToGame()

void CreateMap()

  void InitSnake(pSnake ps)

 void CreateFood(pSnake ps)

游戏进行 void GameRun(pSnake ps)

  int NextIsFood(pSnakeNode psn, pSnake ps)

 void NoFood(pSnakeNode psn, pSnake ps)

void SnakeMove(pSnake ps)

游戏结束 void GameEnd(pSnake ps)

源码

test.c

snake.h

snake.cpp

总结


前言

贪吃蛇游戏是一个耳熟能详的小游戏,本次我们讲解他的简单的实现,需要掌握基本的API知识(http://t.csdnimg.cn/uHH6y),简单的C语言知识和基本的数据结构链表

简单的准备工作

蛇的节点

在游戏运⾏的过程中,蛇每次吃⼀个⻝物,蛇的⾝体就会变⻓⼀节,如果我们使⽤链表存储蛇的信 息,那么蛇的每⼀节其实就是链表的每个节点。每个节点只要记录好蛇⾝节点在地图上的坐标就⾏, 所以蛇节点结构如下:

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

但是这样不好维护这一条蛇,要管理整条贪吃蛇,我们再封装⼀个Snake的结构来维护整条贪吃蛇

typedef struct Snake
 {
 pSnakeNode _pSnake;维护整条蛇的指针 
pSnakeNode _pFood;维护⻝物的指针 
enum DIRECTION _Dir;头的⽅向默认是向右 
enum GAME_STATUS _Status;游戏状态 
int _Socre;当前获得分数 
int _Add;默认每个⻝物10分 
int _SleepTime;每⾛⼀步休眠时间
}Snake, * pSnake;

开始前 void GameStart(pSnake ps)

游戏开始,先打印蛇的身体和地图,以及一些帮助的提示语句,先完成一些准备工作

void GameStart(pSnake ps)
 {
 
设置控制台窗⼝的⼤⼩,30⾏,100列 
//mode 为DOS命令
 system("mode con cols=100 lines=30");
 //设置cmd窗⼝名称
 system("title 贪吃蛇"); 
//获取标准输出的句柄(⽤来标识不同设备的数值) 
HANDLE hOutput = GetStdHandle(STD_OUTPUT_HANDLE); //影藏光标操作 
CONSOLE_CURSOR_INFO CursorInfo; //打印欢迎界⾯ 
WelcomeToGame(); //打印地图 
CreateMap(); //初始化蛇 
GetConsoleCursorInfo(hOutput, &CursorInfo);//获取控制台光标信息 
CursorInfo.bVisible = false; //隐藏控制台光标 
SetConsoleCursorInfo(hOutput, &CursorInfo);//设置控制台光标状态 
InitSnake(ps);
 //创造第⼀个⻝物 
CreateFood(ps);
 }
 

void WelcomeToGame()

在游戏正式开始之前,做⼀些功能提醒,来让玩家了解游戏方法与规则,其中SetPos是一个已经封装后的函数,可以把这个字体打在这个坐标

 void WelcomeToGame()
 {
 SetPos(40, 15);
 printf("欢迎来到贪吃蛇⼩游戏");
 SetPos(40, 25);//让按任意键继续的出现的位置好看点 
system("pause");
 system("cls");
 SetPos(25, 12);
 printf("⽤ ↑ . ↓ . ← . → 分别控制蛇的移动, F3为加速,F4为减速\n");
 SetPos(25, 13);
 printf("加速将能得到更⾼的分数。\n");
 SetPos(40, 25);//让按任意键继续的出现的位置好看点 
system("pause");
 system("cls");
 }

void CreateMap()

创建地图就是将强打印出来,因为是宽字符打印,所有使⽤wprintf函数,打印格式串前使⽤L 打印地图的关键是要算好坐标,才能在想要的位置打印墙体。

 void CreateMap()
 {
 int i = 0;
 //上(0,0)-(56, 0) 
SetPos(0, 0);
 for (i = 0; i < 58; i += 2)
 {
 wprintf(L"%c", WALL);
 } //下(0,26)-(56, 26)  
 SetPos(0, 26); for (i = 0; i < 58; i += 2)
 { wprintf(L"%c", WALL);
 } //左//x是0,y从1开始增⻓ 
for (i = 1; i < 26; i++)
 {
 SetPos(0, i);
 wprintf(L"%c", WALL);}  //是56y从1开始增⻓ 
for (i = 1; i < 26; i++)
 {
 SetPos(56, i);
 wprintf(L"%c", WALL);
 }
 } 

  void InitSnake(pSnake ps)

蛇最开始⻓度为5节,每节对应链表的⼀个节点,蛇⾝的每⼀个节点都有⾃⼰的坐标。 创建5个节点,然后将每个节点存放在链表中进⾏管理。创建完蛇⾝后,将蛇的每⼀节打印在屏幕上。 再设置当前游戏的状态,蛇移动的速度,默认的⽅向,初始成绩,蛇的状态,每个⻝物的分数。

void InitSnake(pSnake ps)
 {
    pSnakeNode cur = NULL;
    int i = 0;
    //创建蛇⾝节点,并初始化坐标 
    //头插法
    for (i = 0; i < 5; i++)
    {
        //创建蛇⾝的节点 
        cur = (pSnakeNode)malloc(sizeof(SnakeNode));
        if (cur == NULL)
        {
            perror("InitSnake()::malloc()");
            return;
        }
        //设置坐标 
        cur->next = NULL;
        cur->x = POS_X + i * 2;
        cur->y = POS_Y;
        //头插法 
        if (ps->_pSnake == NULL)
        {
            ps->_pSnake = cur;
        }
        else
        {
            cur->next = ps->_pSnake;
            ps->_pSnake = cur;
        }
    }
    //打印蛇的⾝体
    cur = ps->_pSnake;
    while (cur)
    {
 SetPos(cur->x, cur->y);
 wprintf(L"%c", BODY);
 cur = cur->next;
 }
 //
初始化贪吃蛇数据 
ps->_SleepTime = 200;
 ps->_Socre = 0;
 ps->_Status = OK;
 ps->_Dir = RIGHT;
 ps->_Add = 10;
 }

 void CreateFood(pSnake ps)

先随机⽣成⻝物的坐标 ◦

  • x坐标必须是2的倍数 ◦
  • ⻝物的坐标不能和蛇⾝每个节点的坐标重复 
  • 创建⻝物节点,打印⻝物
 void CreateFood(pSnake ps)
 {
    int x = 0;
    int y = 0;
 again:
    //产⽣的x坐标应该是2倍数,这样才可能和蛇头坐标对⻬。 
    do
    {
        x = rand() % 53 + 2;
        y = rand() % 25 + 1;
    } while (x % 2 != 0);
    pSnakeNode cur = ps->_pSnake;//获取指向蛇头的指针
     //⻝物不能和蛇⾝冲突
    while (cur)
    {
        if (cur->x == x && cur->y == y)
        {
            goto again;
        }
        cur = cur->next;
    }
    pSnakeNode pFood = (pSnakeNode)malloc(sizeof(SnakeNode)); //创建⻝物
    if (pFood == NULL)
    {
        perror("CreateFood::malloc()");
        return;
    }
    else
    {
        pFood->x = x;
        pFood->y = y;
        SetPos(pFood->x, pFood->y);
        wprintf(L"%c", FOOD);
        ps->_pFood = pFood;
    }
 }

游戏进行 void GameRun(pSnake ps)

游戏运⾏期间,右侧打印帮助信息,提⽰玩家 根据游戏状态检查游戏是否继续,如果是状态是OK,游戏继续,否则游戏结束。 如果游戏继续,就是检测按键情况,确定蛇下⼀步的⽅向,或者是否加速减速,是否暂停或者退出游 戏。 确定了蛇的⽅向和速度,蛇就可以移动了。

 void GameRun(pSnake ps)
 {
 //打印右侧帮助信息
PrintHelpInfo();
 do
 {
 SetPos(64, 10); printf("得分:%d ", ps->_Socre);
 printf("每个⻝物得分:%d分", ps->_Add);
 if (KEY_PRESS(VK_UP) && ps->_Dir != DOWN)
 {
 ps->_Dir = UP;
 }
 else if (KEY_PRESS(VK_DOWN) && ps->_Dir != UP)
 {

            ps->_Dir = DOWN;
        }
        else if (KEY_PRESS(VK_LEFT) && ps->_Dir != RIGHT)
        {
            ps->_Dir = LEFT;
        }
        else if (KEY_PRESS(VK_RIGHT) && ps->_Dir != LEFT)
        {
            ps->_Dir = RIGHT;
        }
        else if (KEY_PRESS(VK_SPACE))
        {
            pause();
        }
        else if (KEY_PRESS(VK_ESCAPE))
        {
            ps->_Status = END_NOMAL;
            break;
        }
        else if (KEY_PRESS(VK_F3))
        {
            if (ps->_SleepTime >= 50)
            {
                ps->_SleepTime -= 30;
                ps->_Add += 2;
            }
        }
        else if (KEY_PRESS(VK_F4))
        {
            if (ps->_SleepTime < 350)
            {
                ps->_SleepTime += 30;
                ps->_Add -= 2;
                if (ps->_SleepTime == 350)
                {
                    ps->_Add = 1;
                }
            }
        }
        //蛇每次⼀定之间要休眠的时间,时间短,蛇移动速度就快
         Sleep(ps->_SleepTime);
        SnakeMove(ps);
    } while (ps->_Status == OK);
 }
 

  int NextIsFood(pSnakeNode psn, pSnake ps)

是一个判断下一个位置是食物的函数,会在下面SnakeMove起到作用,是食物的话将吃掉,不是的话将继续按按键运动

 
int NextIsFood(pSnakeNode psn, pSnake ps)
 {
    return (psn->x == ps->_pFood->x) && (psn->y == ps->_pFood->y);
 }
 

 void NoFood(pSnakeNode psn, pSnake ps)

将下⼀个节点头插⼊蛇的⾝体,并将之前蛇⾝最后⼀个节点打印为空格,放弃掉蛇⾝的最后⼀个节点,在时间是毫米的瞬间完成,造成移动的效果

void NoFood(pSnakeNode psn, pSnake ps)
 {
 //头插法 
psn->next = ps->_pSnake;
 ps->_pSnake = psn;
 pSnakeNode cur = ps->_pSnake;
 //打印蛇 
while (cur->next->next)
 {
 SetPos(cur->x, cur->y);
 wprintf(L"%c", BODY);
 }
 //最后⼀个位置打印空格,然后释放节点 
SetPos(cur->next->x, cur->next->y);
 printf("  ");
 free(cur->next);
 cur->next = NULL;
 }

void SnakeMove(pSnake ps)

蛇⾝移动先创建下⼀个节点,根据移动⽅向和蛇头的坐标,蛇移动到下⼀个位置的坐标。 确定了下⼀个位置后,看下⼀个位置是否是⻝物(NextIsFood),是⻝物就做吃⻝物处理 (EatFood),如果不是⻝物则做前进⼀步的处理(NoFood)。 蛇⾝移动后,判断此次移动是否会造成撞墙(KillByWall)或者撞上⾃⼰蛇⾝(KillBySelf),从⽽影 响游戏的状态

 void SnakeMove(pSnake ps)
 {
 //创建下⼀个节点 
pSnakeNode pNextNode = (pSnakeNode)malloc(sizeof(SnakeNode));
 if (pNextNode == NULL)
 {
 perror("SnakeMove()::malloc()");
 return;
 } //确定下⼀个节点的坐标,下⼀个节点的坐标根据,蛇头的坐标和⽅向确定 
switch (ps->_Dir)
 {
 case UP:
 {
 pNextNode->x = ps->_pSnake->x;
 pNextNode->y = ps->_pSnake->y - 1;

        }
        break;
        case DOWN:
        {
            pNextNode->x = ps->_pSnake->x;
            pNextNode->y = ps->_pSnake->y + 1;
        }
        break;
        case LEFT:
        {
            pNextNode->x = ps->_pSnake->x - 2;
            pNextNode->y = ps->_pSnake->y;
        }
        break;
        case RIGHT:
        {
            pNextNode->x = ps->_pSnake->x + 2;
            pNextNode->y = ps->_pSnake->y;
        }
        break;
    }
    //如果下⼀个位置就是⻝物
 
    if (NextIsFood(pNextNode, ps))
    {
        EatFood(pNextNode, ps);
    }
    else//如果没有⻝物 
    {
        NoFood(pNextNode, ps);
    }
    KillByWall(ps);
    KillBySelf(ps);
 }

游戏结束 void GameEnd(pSnake ps)

游戏结束 游戏状态不再是OK(游戏继续)的时候,要告知游戏技术的原因,并且释放蛇⾝节点。

 void GameEnd(pSnake ps)
 {
 pSnakeNode cur = ps->_pSnake;
 SetPos(24, 12);
 switch (ps->_Status)
 {
 case END_NOMAL:
 printf("您主动退出游戏\n");
 break;
 case KILL_BY_SELF: printf("您撞上⾃⼰了 ,游戏结束!\n");
 break;
 case KILL_BY_WALL:
printf("您撞墙了,游戏结束!\n"); } //释放蛇⾝的节点 
while (cur)
 {
 pSnakeNode del = cur;
 cur = cur->next;
 free(del);
 }
 }

源码

test.c

 #include "Snake.h"
 #include <locale.h>
 void test()
 {
 int ch = 0;
 srand((unsigned int)time(NULL));
 do
 {
 Snake snake = { 0 };
 GameStart(&snake);
 GameRun(&snake);
 GameEnd(&snake);
 SetPos(20, 15);
 printf("再来⼀局吗?(Y/N):");
 ch = getchar();
 getchar();//清理\n } while (ch == 'Y');
 SetPos(0, 27);
 }
 int main()
 {
 //修改当前地区为本地模式,为了⽀持中⽂宽字符的打印
 setlocale(LC_ALL, ""); 
test();
 return 0;
 }

snake.h

 #pragma once
 #include <windows.h>
 #include <time.h>
 #include <stdio.h>
 #define KEY_PRESS(VK)  ((GetAsyncKeyState(VK)&0x1) ? 1 : 0)
 //⽅向
enum DIRECTION
 {
 UP = 1,
 DOWN,
 LEFT,
 RIGHT
 };
 //游戏状态 
enum GAME_STATUS
 {
 OK,//正常运⾏ 
KILL_BY_WALL,//撞墙 
KILL_BY_SELF,//咬到⾃⼰ 
END_NOMAL//正常结束 
};
 #define WALL L'□' 
#define BODY L'●'  // ★ ○● ◇◆ □■ 
#define FOOD L' ★ '  // ★ ○● ◇◆ □■ //蛇的初始位置 
#define POS_X 24
 #define POS_Y 5 //蛇⾝节点
 typedef struct SnakeNode
 {
 int x;
 int y;
 struct SnakeNode* next;
 }SnakeNode, * pSnakeNode;
 typedef struct Snake
 {
 pSnakeNode _pSnake;//整条蛇的指针 
pSnakeNode _pFood;//维护⻝物的指针 
enum DIRECTION _Dir;//蛇头的⽅向默认是向右 
enum GAME_STATUS _Status;//游戏状态 
int _Socre;//当前获得分数 
int _Add;//默认每个⻝物 
int _SleepTime;//每⾛⼀步休眠时间 
}Snake, * pSnake;
 //游戏开始前的初始化 
void GameStart(pSnake ps); //游戏运⾏过程 
void GameRun(pSnake ps); //结束 
void GameEnd(pSnake ps); //设置光标的坐标 
void SetPos(short x, short y); //欢迎界⾯ 
void WelcomeToGame(); //打印帮助信息 
void PrintHelpInfo(); //创建地图 
void CreateMap();//初始化蛇 
void InitSnake(pSnake ps); //⻝物 
void CreateFood(pSnake ps);暂停响应 
void pause(); //下⼀个节点是⻝物
 int NextIsFood(pSnakeNode psn, pSnake ps); //吃⻝物 
void EatFood(pSnakeNode psn, pSnake ps); //不吃⻝物 
void NoFood(pSnakeNode psn, pSnake ps); //撞墙检测 
int KillByWall(pSnake ps); //撞⾃⾝检测 
int KillBySelf(pSnake ps); //蛇的移动 
void SnakeMove(pSnake ps); //游戏初始化 
void GameStart(pSnake ps); //游戏运⾏ 
void GameRun(pSnake ps); //游戏结束
 void GameEnd(pSnake ps);

snake.cpp

 #include "Snake.h"
 //设置光标的坐标 
void SetPos(short x, short y)
 {
 COORD pos = { x, y };
 HANDLE hOutput = NULL;//获取标准输出的句柄(⽤来标识不同设备的数值) 
hOutput = GetStdHandle(STD_OUTPUT_HANDLE);//设置标准输出上光标的位置为
pos SetConsoleCursorPosition(hOutput, pos);
 }
 void WelcomeToGame()
 {
 SetPos(40, 15);
 printf("欢迎来到贪吃蛇⼩游戏");
 SetPos(40, 25);//让按任意键继续的出现的位置好看点 
system("pause");
 system("cls");
 SetPos(25, 12);
 printf("⽤ ↑ . ↓ . ← . → 控制蛇的移动, F3为加速,F4为减速\n");
 SetPos(25, 13);
 printf("加速将能得到更⾼的分数。\n");
 SetPos(40, 25);//让按任意键继续的出现的位置好看点 
system("pause");
 system("cls"); } void CreateMap()
 {
 int i = 0;
 //上(0,0)-(56, 0) 
SetPos(0, 0);
 for (i = 0; i < 58; i += 2)
 {
 wprintf(L"%c", WALL);
 }
 //
下(0,26)-(56, 26) 
SetPos(0, 26);
 for (i = 0; i < 58; i += 2)
 {
 wprintf(L"%c", WALL);
 }
 //左 
//x0,y从1开始增⻓ 
for (i = 1; i < 26; i++)
 {
 SetPos(0, i);
 wprintf(L"%c", WALL);
 }
 //56,从开始增⻓ 
for (i = 1; i < 26; i++)
 {
 SetPos(56, i);
 wprintf(L"%c", WALL);
 }
 }
void InitSnake(pSnake ps)
 {
    pSnakeNode cur = NULL;
    int i = 0;
    //创建蛇⾝节点,并初始化坐标
     //头插法
 
    for (i = 0; i < 5; i++)
    {
        //创建蛇⾝的节点
 cur = (pSnakeNode)malloc(sizeof(SnakeNode));
        if (cur == NULL)
        {
            perror("InitSnake()::malloc()");
            return;
        }
        //设置坐标
        cur->next = NULL;
        cur->x = POS_X + i * 2;
        cur->y = POS_Y;
        //头插法
        if (ps->_pSnake == NULL)
        {
            ps->_pSnake = cur;
        }
        else
        {
            cur->next = ps->_pSnake;
            ps->_pSnake = cur;
        }
    }
    //打印蛇的⾝体 
    cur = ps->_pSnake;
    while (cur)
    {
        SetPos(cur->x, cur->y);
        wprintf(L"%c", BODY);
        cur = cur->next;
    }
    //初始化贪吃蛇数据
    ps->_SleepTime = 200;
    ps->_Socre = 0;
    ps->_Status = OK;
    ps->_Dir = RIGHT;
    ps->_Add = 10;
 }
 void CreateFood(pSnake ps)
 {
    int x = 0;
    int y = 0;
 again:
    //产⽣的x坐标应该是2的倍数,这样才可能和蛇头坐标对⻬。
    do
    {
        x = rand() % 53 + 2;
        y = rand() % 25 + 1;
    } while (x % 2 != 0);
    pSnakeNode cur = ps->_pSnake;//指向蛇头的指针     //⻝物不能和蛇⾝冲突
    while (cur)
    {
        if (cur->x == x && cur->y == y)
        {
            goto again;
        }
        cur = cur->next;
    }
    pSnakeNode pFood = (pSnakeNode)malloc(sizeof(SnakeNode)); //
创建⻝物
 
    if (pFood == NULL)
    {
        perror("CreateFood::malloc()");
        return;
    }
    else
    {
        pFood->x = x;
        pFood->y = y;
        SetPos(pFood->x, pFood->y);
        wprintf(L"%c", FOOD);
        ps->_pFood = pFood;
    }
 }
 void PrintHelpInfo()
 {
 }
 void pause()//暂停 
{打印提⽰信息 
SetPos(64, 15);
 printf("不能穿墙,不能咬到⾃⼰\n");
 SetPos(64, 16);
 printf("⽤↑.↓.←.→分别控制蛇的移动.");
 SetPos(64, 17);
 printf("F1 为加速,F2 为减速\n");
 SetPos(64, 18);
 printf("ESC :退出游戏.space:暂停游戏.");
 SetPos(64, 20);
 while (1)
 {
 Sleep(300);
 if (KEY_PRESS(VK_SPACE))
 {
 break;
 }
 }
 }
 //pSnakeNode psn 是下⼀个节点的地址 
//pSnake ps 维护蛇的指针 
int NextIsFood(pSnakeNode psn, pSnake ps)
 {
 return (psn->x == ps->_pFood->x) && (psn->y == ps->_pFood->y);
 }
 //pSnakeNode psn 是下⼀个节点的地址 
//pSnake ps 维护蛇的指针 
void EatFood(pSnakeNode psn, pSnake ps)
 {
 //头插法 
psn->next = ps->_pSnake;
 ps->_pSnake = psn;
 pSnakeNode cur = ps->_pSnake;
 //打印蛇 
while (cur)
 {
 SetPos(cur->x, cur->y);
 wprintf(L"%c", BODY);
 cur = cur->next;

 }
 ps->_Socre += ps->_Add;
 free(ps->_pFood);
 CreateFood(ps);
 }
 //pSnakeNode psn 
是下⼀个节点的地址
 
//pSnake ps 
维护蛇的指针
 
void NoFood(pSnakeNode psn, pSnake ps)
 {
 //头插法
 psn->next = ps->_pSnake;
 ps->_pSnake = psn;
 pSnakeNode cur = ps->_pSnake; //打印蛇 
while (cur->next->next)
 {
 SetPos(cur->x, cur->y);
 wprintf(L"%c", BODY);
 cur = cur->next;
 }
 //最后⼀个位置打印空格,然后释放节点 
SetPos(cur->next->x, cur->next->y);
 printf("  ");
 free(cur->next);
 cur->next = NULL;
 }
 //pSnake ps 
维护蛇的指针
int KillByWall(pSnake ps)
 {
 if ((ps->_pSnake->x == 0)
 || (ps->_pSnake->x == 56)
 || (ps->_pSnake->y == 0)
 || (ps->_pSnake->y == 26))
 {
 ps->_Status = KILL_BY_WALL;
 return 1;
 }
 return 0;
 }
 //pSnake ps 
维护蛇的指针 
int KillBySelf(pSnake ps)
 {
    pSnakeNode cur = ps->_pSnake->next;
    while (cur)
    {
        if ((ps->_pSnake->x == cur->x)
            && (ps->_pSnake->y == cur->y))
        {
            ps->_Status = KILL_BY_SELF;
            return 1;
        }
        cur = cur->next;
    }
    return 0;
 }
 void SnakeMove(pSnake ps)
 {
    //创建下⼀个节点 
    pSnakeNode pNextNode = (pSnakeNode)malloc(sizeof(SnakeNode));
    if (pNextNode == NULL)
    {
        perror("SnakeMove()::malloc()");
        return;
    }
    //
确定下⼀个节点的坐标,下⼀个节点的坐标根据,蛇头的坐标和⽅向确定
 
    switch (ps->_Dir)
    {
        case UP:
        {
            pNextNode->x = ps->_pSnake->x;
            pNextNode->y = ps->_pSnake->y - 1;
        }
        break;
        case DOWN:
        {
            pNextNode->x = ps->_pSnake->x;
            pNextNode->y = ps->_pSnake->y + 1;
        }
        break;
        case LEFT:
        {
            pNextNode->x = ps->_pSnake->x - 2;
            pNextNode->y = ps->_pSnake->y;
        }
        break;
        case RIGHT:
        {
            pNextNode->x = ps->_pSnake->x + 2;
            pNextNode->y = ps->_pSnake->y;
        }
        break;
    }
    //如果下⼀个位置就是⻝物
 
    if (NextIsFood(pNextNode, ps))
    {
        EatFood(pNextNode, ps);
    }
    else//如果没有⻝物

    {
        NoFood(pNextNode, ps);
    }
    KillByWall(ps);
    KillBySelf(ps);
 }
 void GameStart(pSnake ps)
 {
    //设置控制台窗⼝的⼤⼩,30⾏,100 
    //mode 为DOS命令 
    system("mode con cols=100 lines=30");
    //设置cmd窗⼝名称 
    system("title 贪吃蛇"); 
    //获取标准输出的句柄(来标识不同设备的数值) 
    HANDLE hOutput = GetStdHandle(STD_OUTPUT_HANDLE);  //影藏光标操作
    CONSOLE_CURSOR_INFO CursorInfo;
    GetConsoleCursorInfo(hOutput, &CursorInfo);//获取控制台光标信息
    CursorInfo.bVisible = false; //隐藏控制台光标 
    SetConsoleCursorInfo(hOutput, &CursorInfo);//设置控制台光标状态 //打印欢迎界⾯ 
    WelcomeToGame();   //打印地图 
   CreateMap();   //初始化蛇
    InitSnake(ps);  /创造第⼀个⻝物
    CreateFood(ps);
 
}
 void GameRun(pSnake ps)
 {    //打印右侧帮助信息
 
    PrintHelpInfo();
    do
    {
        SetPos(64, 10);
        printf("得分:%d ", ps->_Socre);        printf("每个⻝物得分:%d分", ps->_Add);
        if (KEY_PRESS(VK_UP) && ps->_Dir != DOWN)
        {
            ps->_Dir = UP;
        }
        else if (KEY_PRESS(VK_DOWN) && ps->_Dir != UP)
        {
            ps->_Dir = DOWN;
        }
        else if (KEY_PRESS(VK_LEFT) && ps->_Dir != RIGHT)
        {
            ps->_Dir = LEFT;
        }
        else if (KEY_PRESS(VK_RIGHT) && ps->_Dir != LEFT)
        {
            ps->_Dir = RIGHT;
        }
        else if (KEY_PRESS(VK_SPACE))
        {
            pause();
        }
        else if (KEY_PRESS(VK_ESCAPE))
        {
            ps->_Status = END_NOMAL;
            break;
        }
        else if (KEY_PRESS(VK_F3))
        {
            if (ps->_SleepTime >= 50)
            {
                ps->_SleepTime -= 30;
                ps->_Add += 2;
            }
        }
        else if (KEY_PRESS(VK_F4))
        {

            if (ps->_SleepTime < 350)
            {
                ps->_SleepTime += 30;
                ps->_Add -= 2;
                if (ps->_SleepTime == 350)
                {
                    ps->_Add = 1;
                }
            }
        }
        //蛇每次⼀定之间要休眠的时间,时间短,蛇移动速度就快
 
        Sleep(ps->_SleepTime);
        SnakeMove(ps);
    } while (ps->_Status == OK);
 }
 void GameEnd(pSnake ps)
 {
    pSnakeNode cur = ps->_pSnake;
    SetPos(24, 12);
    switch (ps->_Status)
    {
    case END_NOMAL:        printf("您主动退出游戏\n");
        break;
    case KILL_BY_SELF:
        printf("您撞上⾃⼰了 ,游戏结束!\n");        break;
    case KILL_BY_WALL:
        printf("您撞墙了,游戏结束!\n");
        break;
    }
    //释放蛇⾝的节点 
    while (cur)
    {
        pSnakeNode del = cur;
        cur = cur->next;
        free(del);
    }
 }

总结

贪吃蛇小游戏是一个有趣的小游戏,也让我学到了很多,希望大家多多支持!!!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1671439.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

whisper之初步使用记录

文章目录 前言 一、whisper是什么&#xff1f; 二、使用步骤 1.安装 2.python调用 3.识别效果评估 4.一点封装 5.参考链接 总结 前言 随着AI大模型的不断发展&#xff0c;语音识别等周边内容也再次引发关注&#xff0c;通过语音转文字再与大模型交互&#xff0c;从而…

ssm125四六级报名与成绩查询系统+jsp

四六级报名与成绩查询系统的设计与实现 摘 要 互联网发展至今&#xff0c;无论是其理论还是技术都已经成熟&#xff0c;而且它广泛参与在社会中的方方面面。它让信息都可以通过网络传播&#xff0c;搭配信息管理工具可以很好地为人们提供服务。针对四六级报名信息管理混乱&am…

外卖 点金推广实战课程,2024外卖 点金推广全流程(7节课+资料)

课程内容&#xff1a; 外卖点金推广实操课程 资料 01 1-了解外卖.mp4 02 第一节:点金推广的说明.mp4 03 第二节:如何降低点金推广的成本,mp4 04 第三节:如何计算点金推广的流速,mp4 05 第四节:如何提升点金的精准度,mp4 06 第五节:点金推广实操,mp4 07 点金推广高级教程…

UE4_照亮环境_不同雾效的动态切换

一、问题及思路&#xff1a; 我们在一个地图上&#xff0c;经常切换不同的区域&#xff0c;不同的区域可能需要不同的色调&#xff0c;例如暖色调的野外或者幽暗的山洞&#xff0c;这两种环境上&#xff0c;雾效的选用肯定不一样&#xff0c;夕阳西下的户外用的就是偏暖的色调&…

基于微信小程序+JAVA Springboot 实现的【马拉松报名系统】app+后台管理系统 (内附设计LW + PPT+ 源码+ 演示视频 下载)

项目名称 项目名称&#xff1a; 马拉松报名系统微信小程序 项目技术栈 该项目采用了以下核心技术栈&#xff1a; 后端框架/库&#xff1a; Java SSM框架数据库&#xff1a; MySQL前端技术&#xff1a; 微信开发者工具、uni-app其他技术&#xff1a; JSP开发技术 项目展示 …

CANopen总线_CANOpen开源协议栈

CANopen是自动化中使用的嵌入式系统的通信协议栈和设备配置文件规范。就OSI 模型而言&#xff0c;CANopen 实现了以上各层&#xff0c;包括网络层。 CANopen 标准由一个寻址方案、几个小型通信协议和一个由设备配置文件定义的应用层组成。通信协议支持网络管理、设备监控和节点…

防火墙远程桌面端口号修改,通过防火墙修改远程桌面的端口号详细操作步骤

使用防火墙修改远程桌面的端口号是一项涉及系统安全和网络配置的重要任务。 以下是详细的操作步骤&#xff0c;旨在确保您能够安全、有效地完成此操作&#xff1a; 一、准备阶段 1. 了解默认端口号&#xff1a;远程桌面端口号通常是3389&#xff0c;这是一个用于远程访问和控…

springboot+vue+mybatis生活废品回收系统+PPT+论文+讲解+售后

该生活废品回收系统采用B/S架构、前后端分离以及MVC模型进行设计&#xff0c;并采用java语言以及springboot框架进行开发。该系统主要设计并完成了管理过程中的用户登录、个人信息修改、义捐活动、在线咨询、订单评价、废品订单、废品、回收再利用技巧、废品回收员、用户等功能…

幻兽帕鲁(公益入库)教程

先安装“SteamtoolsSetup”&#xff0c; 安装好桌面会出来个steam图标的。然后打开“幻兽帕鲁文件夹” 把那2个脚本拖进去那个steam图标。只要显示“已编译了1个Lua脚本”“已更新了1个清单文件”将在Steam重启后生效。然后退出steam&#xff0c;然后重启steam就可以了&#xf…

霍金《时间简史 A Brief History of Time》书后索引(I--L)

A–D部分见&#xff1a;霍金《时间简史 A Brief History of Time》书后索引&#xff08;A–D&#xff09; E–H部分见&#xff1a;霍金《时间简史 A Brief History of Time》书后索引&#xff08;E–H&#xff09; 图源&#xff1a;Wikipedia INDEX I Imaginary numbers Ima…

新消息:2024中国(厦门)国际义齿加工产品展览会

DPE2024中国&#xff08;厦门&#xff09;国际义齿加工产品展览会暨学术研讨会 2024 China (Xiamen) International Denture Processing Products Exhibition 时 间&#xff1a;2024年11月1-3日 November 1-3, 2024 地 点&#xff1a;厦门国际会展中心 Xiamen Int…

强化训练:day7(字符串中找出连续最长的数字串、岛屿数量、拼三角)

文章目录 前言1. 字符串中找出连续最长的数字串1.1 题目描述1.2 解题思路1.3 代码实现 2. 岛屿数量2.1 题目描述2.2 题目描述2.3 代码实现 3. 拼三角3.1 题目描述3.2 解题思路3.3 代码实现 总结 前言 1. 字符串中找出连续最长的数字串   2. 岛屿数量   3. 拼三角 1. 字符串…

LVGL移植到ARM开发板(GEC6818)

源码下载&#xff1a;点击跳转 下载好三个文件后&#xff0c;将其解压缩&#xff0c;并合到一个文件夹里面—— 1、修改 Makefile 删除 -Wshift-negative-value 2、修改 main.c 3、修改 lv_drv_conf.h 在lv_drv_conf.h文件屏幕驱动文件刚好与开发板LCD驱动文件一致&#xff0c…

轻松掌握RAID级别

一、官方说明&#xff1a; RAID&#xff08;英文全称 Redundant Array of Independent Disks&#xff09;翻译成中文&#xff08;独立磁盘冗余阵列&#xff09;。 RAID 是一种将多块独立磁盘&#xff0c;组成一组逻辑磁盘的技术。RAID 级别分为 0、1、3、5、6等&#xff0c;可…

算法设计与分析(超详解!) 第三节 贪婪算法

1.贪心算法基础 1.贪心算法的基本思想 贪心算法是从问题的某一个初始解出发&#xff0c;向给定的目标推进。但它与普通递推求解过程不同的是&#xff0c;其推动的每一步不是依据某一固定的递推式&#xff0c;而是做一个当时看似最佳的贪心选择&#xff0c;不断地将问题实例归…

软件测试面试题100题

一、测试理论 3.1 你们原来项目的测试流程是怎么样的? 我们的测试流程主要有三个阶段&#xff1a;需求了解分析、测试准备、测试执行。 1、需求了解分析阶段 我们的 SE 会把需求文档给我们自己先去了解一到两天这样&#xff0c;之后我们会有一个需求澄清会议&#xff0c; …

VS2022 错误 LNK2001 无法解析的外部符号

错误 LNK2001 无法解析的外部符号 “private: static struct std::once_flag ThreadPool::flag_” (?flag_ThreadPool0Uonce_flagstdA) STL D:\VS2019\STL\源.obj 1 错误原因 &#xff1a;链接器无法解析 ThreadPool::flag_ 这个静态成员变量。这通常是因为静态成员变量在声明…

【linux-IMX6ULL-uboot初次编译及烧录

目录 1. uboot基本概念1. 1 uboot的编译 3. uboot的烧录2. uboot的烧录结果 第一次不进行原理性的探究&#xff0c;也不关注源码内容&#xff0c;只是进行一个直观的了解&#xff0c;对uboot进行初次编译并进烧录到IMX6ULL板卡中 1. uboot基本概念 U-Boot&#xff08;Universa…

计算机网络 3.3OSI参考模型

第三节 OSI参考模型 一、认识OSI/RM 1.描述&#xff1a;定义了一个连接异种计算机的标准主体结构&#xff0c;给网络设计者提供了一个参考规范。 2.组织&#xff1a;国际标准化组织. 3.发展&#xff1a;1979年研究并提出了该国际标准。 4.分层原则&#xff1a; ①层次的划…

通过任意文件读取获取weblogic账号密码

对于weblogic获取到账号密码的前提是有任意文件读取存在&#xff0c;当任意文件读取存在时是可以读取配置文件来对账号密码进行解密。weblogic密码使用AES&#xff08;老版本3DES&#xff09;加密&#xff0c;对称加密可解密&#xff0c;只需要找到用户的密文与加密时的密钥即可…