【C语言实现贪吃蛇】(内含源码)

前言:首先在实现贪吃蛇小游戏之前,我们要先了解Win32 API的有关知识

1.Win32 API

Windows这个多作业系统除了协调应用程序的执行、分配内存、管理资源之外,它同时也是一个很大的服务中心,调佣这个中心的各种服务(每一种服务就是一个函数),它可以帮助应用程序达到开启视窗、秒回图形、使用周边设备等目的,由于这些函数的服务对象是应用程序,所以便称之为Application Pragramming Interface,简称API函数Win32 API也就是Microsoft Windows32位平台的程序应用编程接口。

2.控制台程序

平常我们运用起来的黑框程序就是控制台程序

我们可以通过执行命令来改变控制台的长宽

在我们执行cmd命令之前,我们首先要先做以下事情

点开设置,然后将windows决定改为windows控制台主机,然后点击保存,我们就可以执行有关命令了,(如果控制台主机不可以,可以将其改为windows决定

下面我介绍两个控制台窗口执行命令,可以用C语言函数的system来实现。

1.改变控制台窗口大小(mode命令)

#include<stdio.h>
#include<windows.h>
int main()
{system("mode con cols=50 lines=20");//控制台列改为50列,行就改为20行return 0;
}

可以发现控制台行为20行,列为50行,但看起来却像个正方形,这是为什么呢?其实是因为控制台窗口行和列的比例并不是1:1的。

其坐标位置如下

2.改变控制台的窗口名字(title命令)

#include<stdio.h>
#include<windows.h>
int main()
{system("title 贪吃蛇");return 0;
}

3.控制台屏幕上的坐标

COORDWindows API中定义的一个结构体,表示一个字符在控制台屏幕缓冲区上得坐标,坐标系(0,0)的原点位于缓冲区的顶部左侧单元格。

其中COORD的类型的声明为:

    typedef struct _COORD
    {
        short x;
        short y;
    };

给坐标赋值为:

COORD pos={ 10, 15 };

4.GetStdHandle

GetStdHandle 是一个Windows API函数。它用于从一个特定的标准设备(标准输入、标准输出或标准错误)中取得一个句柄(用来标识不同设备的数值),使用这个句柄可以操作设备。

HANDLE GetStdHandle(DWORD nStdHandle);

HANDLE hOutput = NULL;
//获取标准输出的句柄(⽤来标识不同设备的数值)
hOutput = GetStdHandle(STD_OUTPUT_HANDLE);

5.GetConsoleCursorInfo

其函数原型为:

BOOL WINAPI GetConsoleCursorInfo(
  _In_  HANDLE               hConsoleOutput,
  _Out_ PCONSOLE_CURSOR_INFO lpConsoleCursorInfo

);

HANDLE为获得的标准输出句柄
PCONSOLE_CURSOR_INFO 是指向 CONSOLE_CURSOR_INFO 结构的指针,该结构接收有关主机游标

6.CONSOLE_CURSOR_INFO

这个结构体包含有关控制台光标的信息

typedef struct _ CONSOLE_CURSOR_INFO {
DWORD dwSize;
BOOL bVisible;
} CONSOLE_CURSOR_INFO, *PCONSOLE_CURSOR_INFO;

其中dwSize为由光标填充的字符单元格的百分比。此值介于1到100之间。光标外观会变化,范围从完全填充单元格但单元底部的水平线条。

这里的黑色长方型为光标。

那么其占完全填充单元格的百分之多少呢?这里我们就可以通过一个代码来演示

#include<stdio.h>
#include<windows.h>
int main()
{HANDLE houtput = NULL;//返回void*的指针houtput = GetStdHandle(STD_OUTPUT_HANDLE);//定义一个光标信息的结构体CONSOLE_CURSOR_INFO cursor_info = { 0 };//获取与houtput句柄相关的控制台上的光标信息,并存放在cursor_info中GetConsoleCursorInfo(houtput, &cursor_info);printf("%d", cursor_info.dwSize);return 0;
}

可以观察到其占完全填充光标的25%。

完全填充光标:

那如果我们想要将光标信息隐藏该怎么办呢?

bVisible表示游标的可见性。如果光标可见,则此成员为true.

#include<stdio.h>
#include<windows.h>
#include<stdbool.h>
int main()
{HANDLE houtput = NULL;//返回void*的指针houtput = GetStdHandle(STD_OUTPUT_HANDLE);//定义一个光标信息的结构体CONSOLE_CURSOR_INFO cursor_info = { 0 };//获取与houtput句柄相关的控制台上的光标信息,并存放在cursor_info中GetConsoleCursorInfo(houtput, &cursor_info);cursor_info.bVisible = false;//隐藏光标return 0;
}

但这样并不能隐藏光标信息,还需要借助一个函数SetConsoleCursorInfo来设置控制台屏幕缓冲区的光标大小和可见性。

7.SetConsoleCursorInfo

其函数原型为:

BOOL WINAPI SetConsoleCursorInfo (
HANDLE hConsoleOutput,
const CONSOLE_CURSOR_INFO *lpConsoleCursorInfo
);
#include<stdio.h>
#include<windows.h>
#include<stdbool.h>
int main()
{HANDLE houtput = NULL;//返回void*的指针houtput = GetStdHandle(STD_OUTPUT_HANDLE);//定义一个光标信息的结构体CONSOLE_CURSOR_INFO cursor_info = { 0 };//获取与houtput句柄相关的控制台上的光标信息,并存放在cursor_info中GetConsoleCursorInfo(houtput, &cursor_info);cursor_info.bVisible = false;//隐藏光标SetConsoleCursorInfo(houtput, &cursor_info);return 0;
}

我们就可以观察到光标被隐藏了。

8.SetConsoleCursorPosition

作用:设置指定控制台屏幕缓冲区中的光标位置,我们将想要设置的坐标信息放在COORD类型的pos中,调用SetConsolePostion函数将光标位置设定到指定的位置。

函数原型:

BOOL WINAPI SetConsoleCursorPosition (
HANDLE hConsoleOutput,
COORD pos
);

 这里我们就用Set_Pos分装一个设置光标的函数

void Set_Pos(short x,short y)
{//获取标准输出设备的句柄HANDLE houtput = NULL;houtput=GetStdHandle(STD_OUTPUT_HANDLE);//定位光标的位置COORD pos = { x,y };SetConsoleCursorPosition(houtput, pos);
}

9.GetAsyncKeyState

获取按键情况,GetAsynKeyState的函数原型如下:

SHORT GetAsyncKeyState (
int vKey
);

将键盘上的每一个键的虚拟键值传递给函数,函数通过返回值来分辨键值的状态。

GetAsyncKeyState的返回值是short类型,在上一次调用GetAsyncKeyState函数后,如果返回的16为的short数据中,最高位是1,说明按键的状态时按下,如果最高位是0,说明按键的转台是抬起;如果最低位被置为1则说明,该按键被按过,否则为0。

这里为了方便判断按键是否被按过,我们可以定义一个宏,来判断GetAsynKeyState返回值最低为是否为1.

#define KEY_PRESS(VK) (( GetAsyncKeyState(VK) & 0x1 )? 1 : 0)

 参考:虚拟键码 (Winuser.h) - Win32 apps

这里虚拟键码就可以参照上面的链接。

讲完了上面的有关知识我们就可以开始实现贪吃蛇了

首先先展示贪吃蛇的大致画面

QQ202453-133347

这里为了实现游戏地图的打印,我们就需要讲解一下控制台有关知识,控制台窗口的坐标如下所示,横向的是x轴,纵向的是y轴,从上到下依次增长。

在游戏地图上,我们打印墙体使用的是宽字符:■,打印蛇使用宽字符●,打印食物使用的宽字符是★

那什么是宽字符呢?

普通字符是占一个字节的,宽字符是占两个字节的。

过去C语言并不适用于非英语国家使用,C语言最初假定字符都是单字节的。但是这些假定并不是在世界的任何地方都适用。后来为了适应C语言国际化·,C语言的标准不断加入了国际化的支持。比如:加入宽字符的类型wchar_t和宽字符的输入和输出函数。加入了<locale.h>头文件,提供了允许程序员针对特定地区调整程序行为的函数。

10.setlocale

函数原型:char*setlocale(int category,const char*locale);

setlocale函数用于修改当前地区,可以针对一个类项,也可以所有类项,如果第一个参数是LC_ALL,就是影响所有的类项。

C标准给出了第二个参数定义了两种可能取值:“C”(正常模式)和“ ”(本地模式)。

从任意程序开始,都会隐藏执行调用:

setlocale(LC_ALL,"C");

如果想切换到本地模式就支持宽字符(汉字)的输出:

setlocale(LC_ALL," ");

11.宽字符的打印

宽字符的字面量必须加上前缀“L”,否则C语言会把字面量当做窄字符类型处理,前缀“L”在单引号面前,表示宽字符,对应wprintf()的占位付为%lc;在双引号面前,表示宽字符串,对应占位付就为%ls.

#include <stdio.h>
#include<locale.h>
int main() {setlocale(LC_ALL, "");wchar_t ch = L'●';printf("%c%c\n", 'a', 'b');wprintf(L"%lc\n", ch);return 0;
}

注:这个宽字符的实现要在Windows控制台主机上实现。

这里我们就实现棋盘27行,58列的棋盘,在围绕地图画出墙

这里我们蛇身的初始长度为5,在固定的一个坐标处开始,比如我们在(24,5)处开始打印,连续5个节点。

注:蛇的每个节点的x坐标必须是2个倍数,否则可能会出现蛇的⼀个节点有一半出现在墙体。

关于食物,就是在墙体内随机生成一个坐标(x的坐标必须是2的倍数),坐标不能和蛇的身体重合,然后打印★。

下面我们开始实现贪吃蛇(代码内含注释)

snake.h

#define  _CRT_SECURE_NO_WARNINGS 1#define KEY_PRESS(VK) (( GetAsyncKeyState(VK) & 0x1 )? 1 : 0)
#define POS_X 24
#define POS_Y 5
#define WALL L'■'
#define BODY L'●'
#define FOOD L'★'
#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
#include<windows.h>
#include<locale.h>
#include<time.h>
#include<conio.h>int choice;//选择穿墙还是不穿墙//蛇的方向
enum DIRECTION
{UP = 1,DOWN,LEFT,RIGHT
};//蛇的状态
//正常、撞墙、撞到自己、正常退出
enum GAME_STATUS
{OK,KILL_BY_WALL,KILL_BY_SELF,END_NORMAL 
};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 _food_weight;//一个食物的分数int _score;//总分数int _sleep_time;//休息时间,时间越短,速度越快
}Snake,*pSnake;//设置颜色
void color(int c); //(每次置为其他颜色时都要将其再置为白色,方便设置其他颜色,(也可以根据自己需求设置))//定义光标
void Set_Pos(short x, short y);//游戏初始化void GameStart(pSnake ps);//欢迎界面的打印
void WelcomeToGame();//创建地图
void CreateMap();//初始化蛇身
void InitSnake(pSnake ps);//创建食物
void CreateFood(pSnake ps);//游戏运行的逻辑
void GameRun(pSnake ps);//蛇的移动-走一步
void SnakeMove(pSnake ps);
//判断下一个坐标是否为食物
int NextIsFood(pSnakeNode pNextNode, pSnake ps);
//吃掉食物
void EatFood(pSnakeNode pNextNode, pSnake ps);
//不是食物
void NoFood(pSnakeNode pNextNode, pSnake ps);
//蛇是否撞墙
bool KillByWall(pSnake ps);
//蛇撞墙不会死
void WallSnakeMove(pSnake ps);
//穿墙
int NoKillByWall(pSnake ps, pSnakeNode pn);
//蛇是否撞到自己
bool KillBySelf(pSnake ps);
//游戏结束
void GameEnd(pSnake ps);

snake.c

#define  _CRT_SECURE_NO_WARNINGS 1
#include"snake.h"void color(int c)
{SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), c); //颜色设置//注:SetConsoleTextAttribute是一个API(应用程序编程接口)
}void Set_Pos(short x,short y)
{//获取标准输出设备的句柄HANDLE houtput = NULL;houtput=GetStdHandle(STD_OUTPUT_HANDLE);//定位光标的位置COORD pos = { x,y };SetConsoleCursorPosition(houtput, pos);
}void WelcomeToGame()
{Set_Pos(38, 14);wprintf(L"欢迎来到贪吃蛇小游戏\n");Set_Pos(42, 20);system("pause");system("cls");Set_Pos(25, 14);wprintf(L"用↑,↓,←,→来控制蛇的移动,按F3加速,F4减速\n");Set_Pos(25,15);wprintf(L"加速能够得到更高的分数\n");Set_Pos(42, 20);system("pause");system("cls");
}void CreateMap()
{color(3);//UPfor (int i = 1; i <= 29; i++){wprintf(L"%lc",WALL);}//DOWNSet_Pos(0, 26);for (int i = 1; i <= 29; i++){wprintf(L"%lc", WALL);}//LEFTfor (int i = 1; i < 26; i++){Set_Pos(0, i);wprintf(L"%lc", WALL);}//RIGHTfor (int i = 1; i < 26; i++){Set_Pos(56, i);wprintf(L"%lc", WALL);}color(7);
}void InitSnake(pSnake ps)
{ pSnakeNode cur=NULL;for (int i = 0; i < 5; i++){cur = (pSnakeNode)malloc(sizeof(SnakeNode));if (cur == NULL){perror("InitSnake()::malloc()");return;}cur->next = NULL;cur->x = POS_X + 2 * i;cur->y = POS_Y;//头插if (ps->_pSnake == NULL){ps->_pSnake = cur;}else{cur->next = ps->_pSnake;ps->_pSnake = cur;}}cur = ps->_pSnake;while (cur){Set_Pos(cur->x, cur->y);wprintf(L"%lc",BODY);cur = cur->next;}//设置贪吃蛇的属性ps->_dir = RIGHT;//默认向右走ps->_score = 0;ps->_food_weight = 10;ps->_sleep_time = 200;ps->_status = OK;
}void CreateFood(pSnake ps)
{int x = 0;int y = 0;again:do{x = rand() % 53 + 2;y = rand() % 25 + 1;} while (x % 2 != 0);//x和y的坐标不能和蛇的身体坐标冲突pSnakeNode cur = ps->_pSnake;while (cur){if (x == cur->x && cur->y == y){goto again;}cur = cur->next;}//创建食物的节点pSnakeNode pFood = (pSnakeNode)malloc(sizeof(SnakeNode));if (pFood == NULL){perror("CreateFood()::malloc()");return;}pFood->x = x;pFood->y = y;pFood->next = NULL;Set_Pos(x, y);color(12); //颜色设置为红色wprintf(L"%lc", FOOD);color(7); //颜色设置为白色ps->_pFood = pFood;
}void GameStart(pSnake ps)
{	//0.设置窗口大小,光标隐藏ps->_pSnake = NULL;system("mode con cols=100 lines=30");system("title 贪吃蛇");HANDLE houtput = GetStdHandle(STD_OUTPUT_HANDLE);CONSOLE_CURSOR_INFO CursorInfo = { 0 };GetConsoleCursorInfo(houtput, &CursorInfo);CursorInfo.bVisible = false;SetConsoleCursorInfo(houtput, &CursorInfo);//1.打印欢迎界面WelcomeToGame();//2.绘制地图CreateMap();//3.创建蛇InitSnake(ps);//4.创建食物CreateFood(ps);//5.设置游戏的相关信息
}void PrintHelpInfo()
{color(6);Set_Pos(64, 10);wprintf(L"%ls", L"不能穿墙,不能咬到自己\n");Set_Pos(64, 11);wprintf(L"%ls", L"用↑,↓,←,→来控制蛇的移动\n"); Set_Pos(64, 12);wprintf(L"%ls", L"按F3加速,F4减速\n");Set_Pos(64, 13);wprintf(L"%ls", L"按ESC退出游戏,按空格暂停游戏\n");Set_Pos(64, 15);wprintf(L"%ls", L"贪吃蛇小游戏");color(7);
}void Pause()
{while (1){Sleep(200);if (KEY_PRESS(VK_SPACE))break;}
}int NextIsFood(pSnakeNode pNextNode, pSnake ps)
{return (ps->_pFood->x == pNextNode->x && ps->_pFood->y == pNextNode->y);
}void EatFood(pSnakeNode pNextNode, pSnake ps)
{//头插ps->_pFood->next = ps->_pSnake;ps->_pSnake = ps->_pFood;//释放旧的节点free(pNextNode);pNextNode = NULL;pSnakeNode cur = ps->_pSnake;//将头置为红色color(12); //颜色设置为红色Set_Pos(cur->x, cur->y);wprintf(L"%lc", BODY);cur = cur->next;color(7); //颜色设置为白色while (cur){Set_Pos(cur->x, cur->y);wprintf(L"%lc", BODY);cur = cur->next;}ps->_score += ps->_food_weight;Set_Pos(76, 8);//定位光标到分数旁边printf("+%2d", ps->_food_weight);Sleep(100);Set_Pos(76, 8);printf("   ");//重新创建食物CreateFood(ps);
}bool 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 false;}return true;
}bool KillBySelf(pSnake ps)
{pSnakeNode cur = ps->_pSnake->next;while (cur){if (cur->x == ps->_pSnake->x && cur->y == ps->_pSnake->y){ps->_status = KILL_BY_SELF;return false;}cur = cur->next;}return true;
}void NoFood(pSnakeNode pNextNode, pSnake ps)
{//头插pNextNode->next = ps->_pSnake;ps->_pSnake = pNextNode;//撞墙if (!KillByWall(ps)){return;}//撞到自己if (!KillBySelf(ps)){return;}pSnakeNode cur = ps->_pSnake;//将头置为红色color(12); //颜色设置为红色Set_Pos(cur->x, cur->y);wprintf(L"%lc", BODY);cur = cur->next;color(7); //颜色设置为白色(每次置为其他颜色时都要将其再置为白色,以便下一次置色)while (cur->next->next != NULL){Set_Pos(cur->x, cur->y);wprintf(L"%lc", BODY);cur = cur->next;}//把最后一个节点打印空格Set_Pos(cur->next->x, cur->next->y);printf("  ");//要两个空格//释放最后一个节点free(cur->next);//把倒数第二个节点的next置为空cur->next = NULL;
}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);
}int NoKillByWall(pSnake ps, pSnakeNode pn)
{pSnakeNode pNextNode = (pSnakeNode)malloc(sizeof(SnakeNode));if (pNextNode == NULL){perror("SnakeMove()::malloc()");exit(1);}if (pn->x == 0){//将头节点穿墙pNextNode->x = 54;pNextNode->y = ps->_pSnake->y;pNextNode->next = NULL;//判断下一个节点是否为食物if (NextIsFood(pNextNode, ps)){EatFood(pNextNode, ps);}else{NoFood(pNextNode, ps);}free(pn);return 0;}else if (pn->x == 56){//将头节点穿墙pNextNode->x = 2;pNextNode->y = ps->_pSnake->y;pNextNode->next = NULL;//判断下一个节点是否为食物if (NextIsFood(pNextNode, ps)){EatFood(pNextNode, ps);}else{NoFood(pNextNode, ps);}free(pn);pn = NULL;return 0;}else if (pn->y == 0){//将头节点穿墙pNextNode->y = 25;pNextNode->x = ps->_pSnake->x;pNextNode->next = NULL;//判断下一个节点是否为食物if (NextIsFood(pNextNode, ps)){EatFood(pNextNode, ps);}else{NoFood(pNextNode, ps);}free(pn);pn = NULL;return 0;}else if (pn->y == 26){//将头节点穿墙pNextNode->y = 1;pNextNode->x = ps->_pSnake->x;pNextNode->next = NULL;//判断下一个节点是否为食物if (NextIsFood(pNextNode, ps)){EatFood(pNextNode, ps);}else{NoFood(pNextNode, ps);}free(pn); pn = NULL;return 0;}return 1;
}void WallSnakeMove(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 (NoKillByWall(ps, pNextNode)){if (NextIsFood(pNextNode, ps)){EatFood(pNextNode, ps);}else{NoFood(pNextNode, ps);}}//检测下一个坐标是否为食物//撞到自己KillBySelf(ps);
}void GameRun(pSnake ps)
{PrintHelpInfo();do{color(6);//打印总分数和食物的分值Set_Pos(64, 8);printf("总分数:%d\n", ps->_score);Set_Pos(64, 9);printf("当前食物的分数:%2d\n", ps->_food_weight);color(7);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_NORMAL;//退出}else if (KEY_PRESS(VK_F3)){//加速if (ps->_sleep_time > 80){ps->_sleep_time -= 30;ps->_food_weight += 2;}}else if (KEY_PRESS(VK_F4)){//减速if (ps->_food_weight >= 2){ps->_sleep_time += 30;ps->_food_weight -= 2; }}if (choice == '1'){WallSnakeMove(ps);//蛇可以穿墙}else{SnakeMove(ps);//蛇走一步的过程}Sleep(ps->_sleep_time);} while (ps->_status == OK);
}void GameEnd(pSnake ps)
{Set_Pos(24, 12);color(6);switch (ps->_status){case END_NORMAL:printf("你主动结束游戏\n");break;case KILL_BY_WALL:printf("你寄了\n");break;case KILL_BY_SELF:printf("一不小心撞到自己了\n");break;}color(7);pSnakeNode cur = ps->_pSnake;while (cur){pSnakeNode del = cur;cur = cur->next;free(del);}
}

test.c

#define  _CRT_SECURE_NO_WARNINGS 1#include"snake.h"
#include<locale.h>void test()
{int ch = 0;do{color(6); //颜色设置为土黄色system("cls");//创建贪吃蛇Snake snake = { 0 };//初始化游戏//1.打印欢迎界面//2.功能介绍//3.绘制地图//4.创建蛇//5.创建食物//6.设置游戏的相关信息Set_Pos(38, 15);printf("1.穿墙");Set_Pos(38, 16);printf("2.不穿墙");Set_Pos(38, 18);printf("请选择模式:>");choice = getchar();while (getchar() != '\n');system("cls");GameStart(&snake);//运行游戏GameRun(&snake);//结束游戏GameEnd(&snake);while (_kbhit()){// 使用 _getch() 获取按下的键,不阻塞程序_getch();// 处理按键事件,可以根据需要进行相应的操作}Set_Pos(20, 15);color(6);printf("再来一句不老铁?>(Y/N):");ch = getchar();color(7);while (getchar() != '\n');} while (ch=='Y'||ch=='y');Set_Pos(0, 27);
}int main()
{setlocale(LC_ALL, "");srand((unsigned int)time(NULL));test();return 0;
}

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

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

相关文章

电话号码的字母组合 【C++】【力扣刷题】

解题思路&#xff1a; 以第一个为例,digits “23”&#xff0c;表明从电话号码的按键中选取2和3这两个字符&#xff0c;然后去寻找它们各自所对应的字母&#xff0c;这里每一个数字字符所对应的字母的不同&#xff0c;0对应的是空字符&#xff0c;而1的话题目中讲到是不对应任…

【webrtc】MessageHandler 6: 基于线程的消息处理:StunRequest实现包发送和超时重传

G:\CDN\rtcCli\m98\src\p2p\base\stun_request.cc使用OnMessage 实现包的发送和包的超时重传StunRequest 一个StunRequest 代表是一个独立的请求的发送STUN消息 要不是发送前构造好的,要不就是按照需要构建的使用StunRequestManager: 每一个STUNRequest 携带一个交互id 写入m…

CUDA和显卡驱动

1.安装显卡驱动 https://www.nvidia.com/download/index.aspx?langen-us 由于我的显卡是RTX4060&#xff0c;因此先选择RTX40系列&#xff0c;然后选择RTX4060&#xff0c;进行安装 2.查看显卡对应的CUDA CUDA安装地址&#xff1a;https://developer.nvidia.com/cuda-toolk…

一文带你了解MySQL的索引分类

文章目录 ☃️分类☃️演示图☃️思考☃️总结 欢迎来到 请回答1024 的博客 &#x1f353;&#x1f353;&#x1f353;欢迎来到 请回答1024的博客 关于博主&#xff1a; 我是 请回答1024&#xff0c;一个追求数学与计算的边界、时间与空间的平衡&#xff0c;0与1的延伸的后端开…

【YOLO 系列】基于YOLO V8的27类蔬菜水果检测识别系统【python源码+Pyqt5界面+数据集+训练代码】

前言&#xff1a; 蔬菜水果的种类繁多&#xff0c;是人们日常生活中不可或缺的一部分。然而&#xff0c;在蔬菜水果的生产、销售和储存过程中&#xff0c;往往面临着诸多挑战&#xff0c;如品质检测、分类等问题。为了提高蔬菜水果行业的生产效率和产品质量&#xff0c;我们提…

【redis】redix在Linux下的环境配置和redis的全局命令

˃͈꒵˂͈꒱ write in front ꒰˃͈꒵˂͈꒱ ʕ̯•͡˔•̯᷅ʔ大家好&#xff0c;我是xiaoxie.希望你看完之后,有不足之处请多多谅解&#xff0c;让我们一起共同进步૮₍❀ᴗ͈ . ᴗ͈ აxiaoxieʕ̯•͡˔•̯᷅ʔ—CSDN博客 本文由xiaoxieʕ̯•͡˔•̯᷅ʔ 原创 CSDN 如…

学习Rust的第25天:Rust中的mkdir

为了实现重建 GNU 核心实用程序的崇高目标&#xff0c;今天的工具是 mkdir 我们用来在 Linux 上创建目录的工具。让我们开始吧。 Pseudo Code 伪代码 args command_line_arguments remove the first element of the args vector if args.length 0 {print error_message } els…

STM32学习和实践笔记(24):PWM输出实验:呼吸灯

本实验所要实现的功能是&#xff1a;通过TIM3的CH1输出一个PWM信号&#xff0c;控制D7指示 灯由暗变亮&#xff0c;再由亮变暗&#xff0c;类似于人的呼吸。程序框架如下&#xff1a; &#xff08;1&#xff09;初始化PC6管脚为PWM输出功能 &#xff08;2&#xff09;PWM输出…

RAG应用全流程

RAG全流程 前提训练一个语义模型&#xff08;高精度&#xff0c;低精度&#xff09;训练一个大模型一个知识库一个精度高知识向量库&#xff08;知识分割后输入高精度语义模型得到&#xff09;一个精度低知识向量库&#xff08;知识分割后输入低精度语义模型得到&#xff09; 应…

基于寄存器的STM32操作流程

寄存器点灯 寄存器操作STM32的好处是不需要依靠外部文件&#xff0c;自由度更高&#xff0c;更为底层&#xff0c;但也更加繁杂。 通过寄存器点灯&#xff0c;需要按照电路结构与手册配置寄存器&#xff1a; 电路结构如下&#xff1a;可知需配置的GPIO为GPIOB5与GPIOE5。 在…

TLV61070A具有0.5V超低输入电压的2.5A同步整流升压转换器适合超级电容供电

前言 最大特点是输入电压可低至0.5V&#xff08;启动时的最小输入电压为 1.3V&#xff09;&#xff0c;适合作为超级电容的升压转换 特性 输入电压范围&#xff1a;0.5V 至 5.5V 启动时的最小输入电压为 1.3V 输出电压设置范围&#xff1a;2.2V 至 5.5V 两个 69mΩ (LS)/89m…

gitlab设置保护分支

gitlab设置保护分支方法 进入代码仓库首页&#xff0c;找到settings下的repository并点击进入 找到Protected Branches 下的Exoand按钮&#xff0c;并点击展开 可以看到已经存在默认的保护分支&#xff0c;通常是master/main分支&#xff0c;也可以添加新的保护分支 新建保护分…

Debian操作系统的常用指令介绍

Debian是一个流行的Linux操作系统&#xff0c;以其稳定性和安全性而闻名。对于Debian用户来说&#xff0c;掌握一些基本的命令行指令是非常重要的&#xff0c;因为它们可以帮助你更高效地管理系统。在这篇博客中&#xff0c;我们将介绍一些在Debian系统中常用的指令及其功能。 …

13.1 QQ邮箱

1. 邮箱发送 2. 准备工作 3. 整合SpringBoot 3.1 配置 依赖引入 <!-- 邮件服务--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-mail</artifactId></dependency>application.…

不讲武德,能怼哭你的Chatgpt

这几天逛网站的时候突然发现个新玩意儿&#xff0c;叫做Chatgpt Onima&#xff0c;乍一看&#xff0c;哦原来是Chatgpt 但是&#xff0c;Onima是什么东东&#xff1f;它是我见过最狂的AI Onima 我礼貌的问了一句&#xff1a;你在干嘛&#xff1f; 结果它回复 不知这个攻击性…

通义灵码:智能编码的革命性助手

通义灵码是由阿里云推出的一款基于通义大模型的智能编码辅助工具&#xff0c;它通过先进的人工智能技术&#xff0c;为开发者提供了一系列的智能编码功能&#xff0c;极大地提升了编码效率和质量。以下是通义灵码的一些核心功能和应用案例。 核心功能 代码智能生成 通义灵码…

你知道JSON.stringify()实现拷贝有什么问题吗?

在说 JSON.stringify() 深拷贝之前&#xff0c;我们先说一说深拷贝和浅拷贝的事情吧。 目录 1 为什么要做深拷贝&#xff1f; 2 哪些做法算浅拷贝&#xff1f; 2.1 直接变量赋值 2.2 Object.assign 浅拷贝 3 哪些做法算深拷贝 &#xff1f; 3.1 JSON.stringify() 3.2 …

SpringBoot实现图片上传(个人头像的修改)

SpringBootlayui实现个人信息头像的更改 该文章适合对SpringBoot&#xff0c;Thymeleaf&#xff0c;layui入门的小伙伴 废话不多说&#xff0c;直接上干货 Springbootlayui实现头像更换 前端公共部分代码 HTML页面代码 <div class"layui-card-header" style&quo…

20240502解决ARM32编译器编译quectel-CM时for循环出错的解决

20240502解决ARM32编译器编译quectel-CM时for循环出错的解决 2024/5/2 17:17 缘起&#xff1a;QMIThread.c:2100:9: error: ‘for’ loop initial declarations are only allowed in C99 or C11 mode 1、修改Makefile为ARM32架构&#xff1a; Z:\quectel-CM\Makefile ifneq ($…

基于SpringBoot+Vue的旅游网站系统

初衷 在后台收到很多私信是咨询毕业设计怎么做的&#xff1f;有没有好的毕业设计参考?能感觉到现在的毕业生和当时的我有着同样的问题&#xff0c;但是当时的我没有被骗&#xff0c;因为现在很多人是被骗的&#xff0c;还没有出学校还是社会经验少&#xff0c;容易相信别人。…