贪吃蛇游戏C语言破解:成为编程高手的必修课!

这篇具有很好参考价值的文章主要介绍了贪吃蛇游戏C语言破解:成为编程高手的必修课!。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

贪吃蛇游戏C语言破解:成为编程高手的必修课!,C语言实战项目,机器学习

                                                                                个人主页:秋风起,再归来~

                                                                                文章专栏:C语言实战项目                              

                                                                        个人格言:悟已往之不谏,知来者犹可追

                                                                                        克心守己,律己则安!

1、游戏效果演示

贪吃蛇游戏效果演示

2、win32 API介绍

这里实现贪吃蛇会使⽤到的⼀些Win32 API知识,接下来我介绍一下。

2.1 Win32 API

Windows 这个多作业系统除了协调应⽤程序的执⾏、分配内存、管理资源之外, 它同时也是⼀个很⼤ 的服务中⼼,调⽤这个服务中⼼的各种服务(每⼀种服务就是⼀个函数),可以帮应⽤程序达到开启 视窗、描绘图形、使⽤周边设备等⽬的,由于这些函数服务的对象是应⽤程序(Application),所以便 称之为Application Programming Interface,简称 API 函数。WIN32 API也就是Microsoft Windows  32位平台的应⽤程序编程接⼝。

2.2 控制台程序

平常我们运⾏起来的⿊框程序其实就是控制台程序 我们可以使⽤cmd命令来设置控制台窗⼝的⻓宽:

设置控制台窗⼝的⼤⼩,30⾏,100列

mode con cols=100 lines=30

也可以通过命令设置控制台窗⼝的名字:

title 贪吃蛇

 这些能在控制台窗⼝执⾏的命令,也可以调⽤C语⾔函数system来执⾏。例如

#include<stdlib.h>
int main()
{
	//设置控制台相关属性
	//要包含头文件<stdlib.h>
	system("mode con cols=100 lines=25");
	system("title 贪吃蛇");
	//getchar();
	system("pause");
	return 0;
}

贪吃蛇游戏C语言破解:成为编程高手的必修课!,C语言实战项目,机器学习

2.3 控制台屏幕上的坐标COORD

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

贪吃蛇游戏C语言破解:成为编程高手的必修课!,C语言实战项目,机器学习

COORD类型的声明:
typedef struct _COORD {
 SHORT X;
 SHORT Y;
} COORD, *PCOORD;

 默认光标的位置~贪吃蛇游戏C语言破解:成为编程高手的必修课!,C语言实战项目,机器学习

//修改光标位置:COORD是win32自定义的关于光标在控制台的位置的结构体类型
COORD pos = { 10,20 };

2.4 GetStdHandle

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

HANDLE GetStdHandle(DWORD nStdHandle);
//获得标准输出设备的句柄
HANDLE houtput = GetStdHandle(STD_OUTPUT_HANDLE);

2.5 GetConsoleCursorInfo

GetConsoleCursorInfo检索有关指定控制台屏幕缓冲区的光标⼤⼩可⻅性的信息

BOOL WINAPI GetConsoleCursorInfo(
 HANDLE hConsoleOutput,
 PCONSOLE_CURSOR_INFO lpConsoleCursorInfo
);
PCONSOLE_CURSOR_INFO 是指向 CONSOLE_CURSOR_INFO 结构的指针,该结构接收有关主机游标
HANDLE hOutput = NULL;
//获取标准输出的句柄(⽤来标识不同设备的数值) 
hOutput = GetStdHandle(STD_OUTPUT_HANDLE);
CONSOLE_CURSOR_INFO CursorInfo;
GetConsoleCursorInfo(hOutput, &CursorInfo);//获取控制台光标信息 

2.5.1 CONSOLE_CURSOR_INFO

  CONSOLE_CURSOR_INFO是win32自定义的一个结构体类型,里面包含了光标的比例和可见度

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

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

• bVisible,游标的可⻅性。如果光标可⻅,则此成员为TRUE。 

贪吃蛇游戏C语言破解:成为编程高手的必修课!,C语言实战项目,机器学习

2.6 SetConsoleCursorInfo

设置指定控制台屏幕缓冲区的光标的⼤⼩和可⻅性。

BOOL WINAPI SetConsoleCursorInfo(
 HANDLE hConsoleOutput,
 const CONSOLE_CURSOR_INFO *lpConsoleCursorInfo
);

示例:

#include<stdio.h>
#include<Windows.h>
#include<stdlib.h>
#include<stdbool.h>
int main()
{
	//获得标准输出设备的句柄
	HANDLE houtput = GetStdHandle(STD_OUTPUT_HANDLE);

	//CONSOLE_CURSOR_INFO是win32自定义的一个结构体类型,里面包含了光标的比例和可见度
	CONSOLE_CURSOR_INFO cursorInfo = { 0 };
	//获得光标信息
	GetConsoleCursorInfo(houtput, &cursorInfo);


	//获得光标信息
	GetConsoleCursorInfo(houtput, &cursorInfo);
	
	//修改控制台的光标信息
	cursorInfo.dwSize = 100;//比例
	cursorInfo.bVisible = false;//可见度

	//设置光标的信息
	SetConsoleCursorInfo(houtput, &cursorInfo);

	system("pause");
	return 0;
}

光标被隐藏啦!   贪吃蛇游戏C语言破解:成为编程高手的必修课!,C语言实战项目,机器学习

2.7 SetConsoleCursorPosition

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

BOOL WINAPI SetConsoleCursorPosition(
 HANDLE hConsoleOutput,
 COORD pos
);

示例: 

int main()
{
	//获得标准输出设备的句柄
	HANDLE houtput = GetStdHandle(STD_OUTPUT_HANDLE);

	//修改光标位置:COORD是win32自定义的关于光标在控制台的位置的结构体类型
	COORD pos = { 10,20 };

	//设置光标位置
	SetConsoleCursorPosition(houtput, pos);

	getchar();
	//system("pause");
	return 0;
}

贪吃蛇游戏C语言破解:成为编程高手的必修课!,C语言实战项目,机器学习

SetPos:封装⼀个设置光标位置的函数

//把设置光标位置的操作封装成为一个函数
void _SetPos(short x, short y)
{
	//获得标准输出设备的句柄
	HANDLE houtput = GetStdHandle(STD_OUTPUT_HANDLE);

	//修改光标位置:COORD是win32自定义的关于光标在控制台的位置的结构体类型
	COORD pos = { x,y };

	//设置光标位置
	SetConsoleCursorPosition(houtput, pos);
}

2.8 GetAsyncKeyState

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

SHORT GetAsyncKeyState(
 int vKey
);

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

GetAsyncKeyState 的返回值是short类型,在上⼀次调⽤ GetAsyncKeyState 函数后,如果 返回的16位的short数据中,最⾼位是1,说明按键的状态是按下,如果最⾼是0,说明按键的状态是抬 起;如果最低位被置为1则说明,该按键被按过,否则为0。 如果我们要判断⼀个键是否被按过,可以检测GetAsyncKeyState返回值的最低值是否为1.

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

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

3、<locale.h>本地化

贪吃蛇游戏C语言破解:成为编程高手的必修课!,C语言实战项目,机器学习

如上图游戏效果演示所示:

在游戏地图上,我们打印墙体使⽤宽字符:□,打印蛇使⽤宽字符●,打印⻝物使⽤宽字符★ 普通的字符是占⼀个字节的,这类宽字符是占⽤2个字节。

这⾥再简单的讲⼀下C语⾔的国际化特性相关的知识,过去C语⾔并不适合⾮英语国家(地区)使⽤。 C语⾔最初假定字符都是单字节的。但是这些假定并不是在世界的任何地⽅都适⽤。

C语⾔字符默认是采⽤ASCII编码的,ASCII字符集采⽤的是单字节编码,且只使⽤了单字节中的低7 位,最⾼位是没有使⽤的,可表⽰为0xxxxxxxx;可以看到,ASCII字符集共包含128个字符,在英语 国家中,128个字符是基本够⽤的,但是,在其他国家语⾔中,⽐如,在法语中,字⺟上⽅有注⾳符 号,它就⽆法⽤ASCII码表⽰。于是,⼀些欧洲国家就决定,利⽤字节中闲置的最⾼位编⼊新的符 号。⽐如,法语中的é的编码为130(⼆进制10000010)。这样⼀来,这些欧洲国家使⽤的编码体 系,可以表⽰最多256个符号。但是,这⾥⼜出现了新的问题。不同的国家有不同的字⺟,因此,哪 怕它们都使⽤256个符号的编码⽅式,代表的字⺟却不⼀样。⽐如,130在法语编码中代表了é,在希 伯来语编码中却代表了字⺟Gimel,在俄语编码中⼜会代表另⼀个符号。但是不管怎样,所有这 些编码⽅式中,0--127表⽰的符号是⼀样的,不⼀样的只是128--255的这⼀段。 ⾄于亚洲国家的⽂字,使⽤的符号就更多了,汉字就多达10万左右。⼀个字节只能表⽰256种符号, 肯定是不够的,就必须使⽤多个字节表达⼀个符号。⽐如,简体中⽂常⻅的编码⽅式是GB2312,使 ⽤两个字节表⽰⼀个汉字,所以理论上最多可以表⽰256x256=65536个符号。 

后来为了使C语⾔适应国际化,C语⾔的标准中不断加⼊了国际化的⽀持。⽐如:加⼊了宽字符的类型 wchar_t 和宽字符的输⼊和输出函数,加⼊了头⽂件,其中提供了允许程序员针对特定 地区(通常是国家或者说某种特定语⾔的地理区域)调整程序⾏为的函数。

提供的函数⽤于控制C标准库中对于不同的地区会产⽣不⼀样⾏为的部分。在标准中,依赖地区的部分有以下⼏项:

• 数字量的格式

• 货币量的格式

• 字符集

• ⽇期和时间的表⽰形式

3.1 类项

通过修改地区,程序可以改变它的⾏为来适应世界的不同区域。但地区的改变可能会影响库的许多部 分,其中⼀部分可能是我们不希望修改的。所以C语⾔⽀持针对不同的类项进⾏修改,下⾯的⼀个宏, 指定⼀个类项:

• LC_COLLATE:影响字符串⽐较函数 strcoll() 和 strxfrm() 。

• LC_CTYPE:影响字符处理函数的⾏为。

• LC_MONETARY:影响货币格式。

• LC_NUMERIC:影响 printf() 的数字格式。

• LC_TIME:影响时间格式 strftime() 和 wcsftime() 。

• LC_ALL-针对所有类项修改,将以上所有类别设置为给定的语⾔环境

3.2 setlocale函数

char* setlocale (int category, const char* locale);

setlocale函数⽤于修改当前地区,可以针对⼀个类项修改,也可以针对所有类项。

setlocale的第⼀个参数可以是前⾯说明的类项中的⼀个,那么每次只会影响⼀个类项,如果第⼀个参 数是LC_ALL,就会影响所有的类项。

C标准给第⼆个参数仅定义了2种可能取值:"C"(正常模式)和" "(本地模式)

在任意程序执⾏开始,都会隐藏式执⾏调⽤:

setlocale(LC_ALL, "C");

当地区设置为"C"时,库函数按正常⽅式执⾏,⼩数点是⼀个点。

当程序运⾏起来后想改变地区,就只能显⽰调⽤setlocale函数。⽤" "作为第2个参数,调⽤setlocale 函数就可以切换到本地模式,这种模式下程序会适应本地环境。

⽐如:切换到我们的本地模式后就⽀持宽字符(汉字)的输出等。 

setlocale(LC_ALL, " ");//切换到本地环境 
#include<locale.h>
int main()
{
	//C语言标准模式
	char* ret = setlocale(LC_ALL, NULL);
	printf("%s\n", ret);

	//本地化之后的模式
	ret = setlocale(LC_ALL, "");
	printf("%s\n", ret);
	return 0;
}

贪吃蛇游戏C语言破解:成为编程高手的必修课!,C语言实战项目,机器学习

3.3宽字符的打印

那如果想在屏幕上打印宽字符,怎么打印呢?

宽字符的字⾯量必须加上前缀“L”,否则C语⾔会把字⾯量当作窄字符类型处理。

前缀“L”在单引 号前⾯,表⽰宽字符,对应 wprintf() 的占位符为 %lc ;在双引号前⾯,表⽰宽字符串,对应 wprintf() 的占位符为 %ls 。

#include<locale.h>
int main()
{
	//本地化
	setlocale(LC_ALL, "");
	//打印宽字符
	wchar_t ch1 = L'●';
	wchar_t ch2 = L'□';
	wchar_t ch3 = L'★';
	wprintf(L"%lc\n", ch1);
	wprintf(L"%lc\n", ch2);
	wprintf(L"%lc\n", ch3);
	return 0;
}

贪吃蛇游戏C语言破解:成为编程高手的必修课!,C语言实战项目,机器学习

从输出的结果来看,我们发现⼀个普通字符占⼀个字符的位置 但是打印⼀个汉字字符,占⽤2个字符的位置,那么我们如果 要在贪吃蛇中使⽤宽字符,就得处理好地图上坐标的计算。

贪吃蛇游戏C语言破解:成为编程高手的必修课!,C语言实战项目,机器学习

 4、游戏实现的整体思路

贪吃蛇游戏C语言破解:成为编程高手的必修课!,C语言实战项目,机器学习

1. (第一界面)通过贪吃蛇游戏的视频演示我们可以知道我们首先要在屏幕上打印欢迎界面

2. (第二界面)然后再在屏幕上打印帮助手册

3. (第三界面)接着在屏幕上打印游戏运行时的界面

4. (第四界面)游戏结束后再在屏幕上打印结束原因和最后得分

5. (第五界面)打印玩家是否想在来一局

 4.1 我们要用到的数据结构

实现这些步骤前,我们先要思考并完成我们要用到的数据结构

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

所以蛇节点结构如下:

//蛇身的节点类型
typedef struct SnakeNode
{
	//蛇的身体的每个节点的坐标
	int x;
	int y;
	//指向下一个节点的指针
	struct SnakeNode* next;
}SnakeNode,*pSnakeNode;

要管理整条贪吃蛇,我们再封装⼀个Snake的结构来维护整条贪吃蛇:

//创建一个结构体类型来维护蛇的各种信息
typedef struct Snake
{
	pSnakeNode _pSnakeHead;//维护蛇头的指针
	pSnakeNode _pFood;//维护食物的指针
	enum DIRECTION _dri;//维护蛇的方向
	enum GAME_STATE _state;//维护蛇的状态
	int _score;//维护当前游戏的总分
	int _foodWeight;//维护一个食物默认的分数
	int _sleepTime;//维护蛇的速度
}Snake,*pSnake;

 蛇的⽅向,可以⼀⼀列举,使⽤枚举:

//枚举蛇的四种方向
enum DIRECTION
{
	UP = 1,
	DOWN,
	LEFT,
	RIGHT
};

游戏状态,可以⼀⼀列举,使⽤枚举:

//枚举四种游戏状态
enum GAME_STATE
{
	OK,//正常运行
	END_NORMAL,//正常退出
	KILL_BY_WALL,//撞到墙了
	KILL_BY_SELF//撞到自己了
};

 4.2 封装三个文件

1.test.h(游戏测试逻辑)

2. snake.h(所有头文件的包含和函数的声明)

3 snake.c(函数的具体实现)

4.3 test.c

这里是游戏的整体逻辑,具体实现在snake.c中

#define _CRT_SECURE_NO_WARNINGS
#include"snake.h"

//完成游戏的测试逻辑
void test()
{
	int ch = 0;
	do
	{
		//创建贪吃蛇
		Snake snake = { 0 };
		pSnake ps = &snake;
		//初始化游戏
		//0. 光标隐藏
		//1. 打印欢迎界面
		//2. 绘制地图
		//3. 蛇身初始化
		//4. 食物初始化
		GameStart(&snake);
		//运行游戏
		GameRun(&snake);
		//结束游戏(善后工作)
		GameEnd(&snake);
		/*SetPos(62, 18);
		printf("您要再来一局吗?(Y/N):");*/
		ch = getchar();
		//清理缓冲区里面的内容
		getchar(); 
		system("cls");
	} while (ch == 'Y' || ch == 'y');
}

int main()
{
	//设置适配本地环境
	setlocale(LC_ALL, "");
	srand((unsigned int)time(NULL));
	test();
	return 0;
}

4.4 snake.h

我先把会用到的头文件,结构类型和函数声明放到这里(看完这些之后后面的代码就更容易看懂)

下面有很详细的注释,先不需要知道函数具体怎么实现,这里只需要知道它们的功能即可。

当然,还有一些函数并没在这里声明(这些函数大多都是为实现某个功能为具体的另一个函数(被这个函数调用)服务却没有在整体上都用到)

#pragma once
//包含所需要的头文件
#include<stdio.h>
#include<stdlib.h>
#include<Windows.h>
#include<locale.h>
#include<stdbool.h>
#include<time.h>
#include<conio.h>

#define WALL L'□'
#define POS_X 24
#define POS_Y 5
#define BODY L'●'
#define FOOD L'★'
//定义宏判断键盘上的按键是否被按过
#define KEY_PRESS(vk) ((GetAsyncKeyState(vk)&0x1)?1:0)

//类型的声明

//枚举蛇的四种方向
enum DIRECTION
{
	UP = 1,
	DOWN,
	LEFT,
	RIGHT
};

//枚举四种游戏状态
enum GAME_STATE
{
	OK,//正常运行
	END_NORMAL,//正常退出
	KILL_BY_WALL,//撞到墙了
	KILL_BY_SELF//撞到自己了
};

//蛇身的节点类型
typedef struct SnakeNode
{
	//蛇的身体的每个节点的坐标
	int x;
	int y;
	//指向下一个节点的指针
	struct SnakeNode* next;
}SnakeNode,*pSnakeNode;
//typedef struct SnakeNode* pSnakeNode;

//创建一个结构体类型来维护蛇的各种信息
typedef struct Snake
{
	pSnakeNode _pSnakeHead;//维护蛇头的指针
	pSnakeNode _pFood;//维护食物的指针
	enum DIRECTION _dri;//维护蛇的方向
	enum GAME_STATE _state;//维护蛇的状态
	int _score;//维护当前游戏的总分
	int _foodWeight;//维护一个食物默认的分数
	int _sleepTime;//维护蛇的速度
}Snake,*pSnake;


//函数的声明

//游戏初始化
void GameStart(pSnake ps);

//定位光标位置
void SetPos(int x, int y);

//打印地图
void CreatMap();

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

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

//游戏运行
void GameRun(pSnake ps);

//游戏结束(善后工作)
void GameEnd(pSnake ps);

//蛇走一步
void SnakeMove(pSnake ps);

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

//下一个位置不是食物
void NoFood(pSnake ps,pSnakeNode pn);

//检查是否撞墙
void KillByWall(pSnake ps);

//检查是否撞到自己
void KillBySelf(pSnake ps);

//检测是否有按键被按下
void KeyFun();

 4.5 GameStart(游戏初始化)

1.SetPos(定位光标位置)

//把设置光标位置的操作封装成为一个函数
void SetPos(int x, int y)
{
	//获得标准输出设备的句柄
	HANDLE houtput = GetStdHandle(STD_OUTPUT_HANDLE);

	//修改光标位置:COORD是win32自定义的关于光标在控制台的位置的结构体类型
	COORD pos = { x,y };

	//设置光标位置
	SetConsoleCursorPosition(houtput, pos);
}

2.游戏初始化逻辑 

//游戏初始化
void GameStart(pSnake ps)
{
	//0. 先设置窗口的大小再隐藏光标
	system("mode con cols=150 lines=40");
	system("title 贪吃蛇");
	//获得标准输出设备的句柄
	HANDLE houtput = GetStdHandle(STD_OUTPUT_HANDLE);
	//CONSOLE_CURSOR_INFO是win32自定义的一个结构体类型,里面包含了光标的比例和可见度
	CONSOLE_CURSOR_INFO cursorInfo = { 0 };
	//获得光标信息
	GetConsoleCursorInfo(houtput, &cursorInfo);
	//修改控制台的光标信息
	cursorInfo.dwSize = 100;//比例
	cursorInfo.bVisible = false;//可见度
	//设置光标的信息
	SetConsoleCursorInfo(houtput, &cursorInfo);

	//1. 打印欢迎界面和游戏功能介绍
	WelcomeToGame();
	//2. 绘制地图
	CreatMap();
	//3. 蛇身初始化
	InitSnake(ps);
	//4. 食物初始化
	CreateFood(ps);
}

 4.5.1 WelcomeToGame(打印欢迎界面)

//打印欢迎界面
void WelcomeToGame()
{
	//第一界面(欢迎界面)
	SetPos(62, 14);
	printf("欢迎来到贪吃蛇小游戏!");
	SetPos(64, 16);
	system("pause");
	system("cls");//清理屏幕
	//第二界面(游戏功能介绍)
	SetPos(50, 12);
	printf("1、用 ↑ . ↓ . ← . → 分别控制蛇的移动, F3为加速,F4为减速!");
	SetPos(50, 13);
	printf("2、加速将可以得到更高的分数!");
	SetPos(65, 15);
	system("pause");
	system("cls");//清理屏幕
}

4.5.2 CreatMap(绘制地图)

//打印地图
void CreatMap()
{
	int i = 0;
	for (int i = 0; i <= 100; i += 2)
	{
		wprintf(L"%lc", WALL);
	}
	SetPos(0, 36);
	for (int i = 0; i <= 100; i += 2)
	{
		wprintf(L"%lc", WALL);
	}
	for (int i = 1; i <= 36; i ++)
	{
		SetPos(0, i);
		wprintf(L"%lc", WALL);
	}
	for (int i = 1; i <= 36; i++)
	{
		SetPos(100, i);
		wprintf(L"%lc", WALL);
	}
}

4.5.3 InitSnake(蛇身初始化)

//初始化蛇身
void InitSnake(pSnake ps)
{
	pSnakeNode cur = NULL;
	//创建5个蛇身的节点
	for (int i = 1; i <= 5; i++)
	{
		cur = CreatSnakeNode();
		cur->next = NULL;
		cur->x = POS_X + i * 2;
		cur->y = POS_Y;
		//将5个蛇身节点串起来
		if (ps->_pSnakeHead == NULL)
		{//蛇头为空就直接插入
			ps->_pSnakeHead = cur;
		}
		else//头插
		{
			cur->next = ps->_pSnakeHead;
			ps->_pSnakeHead = cur;
		}
	}
	cur = ps->_pSnakeHead;
	while (cur)
	{
		SetPos(cur->x,cur->y);
		wprintf(L"%lc", BODY);
		cur = cur->next;
	}
	ps->_dri = RIGHT;//方向默认向右
	ps->_foodWeight = 10;
	ps->_score = 0;
	ps->_sleepTime = 200;
	ps->_state = OK;
}

4.5.4 CreateFood(食物初始化)

//初始化食物
void CreateFood(pSnake ps)
{
	//先随机生成食物的坐标
	int x = 0;
	int y = 0;
again:
	//生成的位置必须在地图内部
	do
	{
		x = rand() % 97 + 2;
		y = rand() % 35 + 1;
	} while (x % 2 != 0);
	pSnakeNode cur = ps->_pSnakeHead;
	//判断食物位置是否与蛇身重叠
	while (cur)
	{
		if (cur->x == x && cur->y == y)
		{
			goto again;
		}
		cur = cur->next;
	}
	//打印食物
	SetPos(x, y);
	wprintf(L"%lc", FOOD);
	pSnakeNode food = CreatSnakeNode();
	food->x = x;
	food->y = y;
	food->next = NULL;
	//将食物节点放到ps中维护起来
	ps->_pFood = food;
}

4.6 GameRun(游戏运行)

1.检测按键是否被按过

//定义宏判断键盘上的按键是否被按过
#define KEY_PRESS(vk) ((GetAsyncKeyState(vk)&0x1)?1:0)

2.检测是否有按键被按下

//检测是否有按键被按下
void KeyFun()
{
	while (_kbhit())
	{
		//使用_getch()获取按下的键,不阻塞程序
		int key = _getch();
	}
}

3.游戏暂停 

//游戏暂停
void Pause()
{
	while(1)
	{
		if (KEY_PRESS(VK_SPACE))
		{
			break;
		}
		Sleep(200);
		KeyFun();
	}
}

游戏运行逻辑 

//游戏运行
void GameRun(pSnake ps)
{
	PrintHelpInfo();
	do 
	{
		SetPos(104, 12);
		printf("按空格键开始游戏!");
		SetPos(104, 13);
		printf("您当前的总分是%3d", ps->_score);
		SetPos(104, 14);
		printf("当前每个食物的总分是%3d", ps->_foodWeight);
		if (KEY_PRESS(VK_UP) && ps->_dri != DOWN)
		{
			ps->_dri = UP;//上
		}
		else if (KEY_PRESS(VK_DOWN) && ps->_dri != UP)
		{
			ps->_dri = DOWN;//下
		}	
		else if(KEY_PRESS(VK_LEFT) && ps->_dri != RIGHT)
		{
			ps->_dri = LEFT;//左
		}
		else if(KEY_PRESS(VK_RIGHT) && ps->_dri != LEFT)
		{
			ps->_dri = RIGHT;//右
		}
		else if (KEY_PRESS(VK_SPACE) )
		{
			Pause();//暂停
		}
		else if (KEY_PRESS(VK_ESCAPE))
		{
			ps->_state = END_NORMAL;//正常退出
		}
		else if (KEY_PRESS(VK_F3))
		{
			//加速
			if (ps->_sleepTime>80)
			{
				ps->_sleepTime -= 30;
				ps->_foodWeight += 2;
			}
		}
		else if (KEY_PRESS(VK_F4))
		{
			//减速
			if (ps->_foodWeight>2)
			{
				ps->_sleepTime += 30;
				ps->_foodWeight -= 2;
			}
		}
		//走一步
		SnakeMove(ps);
		//每走一步休息一下
		Sleep(ps->_sleepTime);
		KeyFun();
	} while (ps->_state == OK);
}

 4.6.1 PrintHelpInfo(右侧打印帮助手册)

//打印帮助手册
void PrintHelpInfo()
{
	SetPos(104, 16);
	printf("--------------------------------------------");
	SetPos(104, 17);
	printf("|1、不能撞墙,不能咬到自己!               |");
	SetPos(104, 18);
	printf("|2、用 ↑ . ↓ . ← . → 分别控制蛇的移动! |");
	SetPos(104, 19);
	printf("|3、F3为加速,F4为减速!                   |");
	SetPos(104, 20);
	printf("|4、按Esc退出游戏,按空格暂停游戏 !        |");
	SetPos(104, 21);
	printf("--------------------------------------------");
	SetPos(60, 17);
}

  4.6.2 SnakeMove(蛇走一步)

1.蛇走一步逻辑

//蛇走一步
void SnakeMove(pSnake ps)
{
	//创建一个节点来记录蛇头的下一个位置
	pSnakeNode nextHead = CreatSnakeNode();
	nextHead->next = NULL;
	switch (ps->_dri)
	{
	case UP:
		nextHead->x = ps->_pSnakeHead->x;
		nextHead->y = ps->_pSnakeHead->y - 1;
		break;
	case DOWN:
		nextHead->x = ps->_pSnakeHead->x;
		nextHead->y = ps->_pSnakeHead->y +1;
		break;
	case LEFT:
		nextHead->y = ps->_pSnakeHead->y;
		nextHead->x = ps->_pSnakeHead->x - 2;
		break;
	case RIGHT:
		nextHead->y = ps->_pSnakeHead->y;
		nextHead->x = ps->_pSnakeHead->x + 2;
		break;
	default:
		break;
	}
	//判断下一个节点是不是食物
	if((ps->_pFood->x == nextHead->x) && (ps->_pFood->y == nextHead->y))
	{
		//下一个是食物那就吃掉食物
		EatFood(nextHead, ps);
	}
	else
	{
		//下一个位置不是食物
		NoFood(ps, nextHead);
	}
	//
	KillByWall(ps);
	KillBySelf(ps);
}

 2. EatFood(吃掉食物)

//吃掉食物
void EatFood(pSnakeNode pn, pSnake ps)
{
	//头插吃掉食物
	ps->_pFood->next = ps->_pSnakeHead;
	ps->_pSnakeHead = ps->_pFood;
	ps->_score += ps->_foodWeight;//分数增加
	//打印蛇身
	pSnakeNode cur = ps->_pSnakeHead;
	while (cur)
	{
		SetPos(cur->x, cur->y);
		wprintf(L"%lc", BODY);
		cur = cur->next;
	}
	//释放刚刚malloc的位置
	free(pn);
	pn = NULL;
	//食物被吃掉了,那就再创建一个食物
	CreateFood(ps);
}

3. NoFood往前走一步(不是食物)

//下一个位置不是食物
void NoFood(pSnake ps,pSnakeNode pn)
{
	//头插
	pn->next = ps->_pSnakeHead;
	ps->_pSnakeHead = pn;
	pSnakeNode cur = ps->_pSnakeHead;
	while (cur->next->next!=NULL)
	{
		SetPos(cur->x, cur->y);
		wprintf(L"%lc",BODY);
		cur = cur->next;
	}
	//把最后一个节点打印成两个空格
	SetPos(cur->next->x, cur->next->y);
	printf("  ");
	//释放最后一个节点
	free(cur->next);
	cur->next = NULL;
}

 4. KillByWall(检测是否撞墙)

//检查是否撞墙
void KillByWall(pSnake ps)
{
	if (ps->_pSnakeHead->x == 0
		|| ps->_pSnakeHead->x == 98
		|| ps->_pSnakeHead->y == 0
		|| ps->_pSnakeHead->y == 36)
	{
		ps->_state = KILL_BY_WALL;
		return;
	}
	return;
}

5.  KillBySelf(检测是否撞到自己)

//检查是否撞到自己
void KillBySelf(pSnake ps)
{
	pSnakeNode cur = ps->_pSnakeHead->next;
	while (cur)
	{
		if ((cur->x == ps->_pSnakeHead->x) &&
			(cur->y == ps->_pSnakeHead->y))
		{
			ps->_state = KILL_BY_SELF;
			return;
		}
		cur = cur->next;
	}
	return;
}

4.7 GameEnd(游戏善后)

//游戏善后
void GameEnd(pSnake ps)
{
	pSnakeNode cur = ps->_pSnakeHead;
	while (cur)
	{
		pSnakeNode del = cur;
		cur = cur->next;
		free(del);
	}
	system("cls");
	SetPos(62, 16);
	switch (ps->_state)
	{
	case END_NORMAL:
		printf("您主动退出游戏!\n");
		break;
	case KILL_BY_WALL:
		printf("您撞墙了!\n");
		break;
	case KILL_BY_SELF:
		printf("您撞到自己了!\n");
		break;
	}
	SetPos(62, 17);
	printf("您最终的成绩是:%d", ps->_score);
	Sleep(2000);
	KeyFun();
	system("cls");
	SetPos(62, 18);
	printf("您要再来一局吗?(Y/N):");
}

 4.8 snake.c(完整代码)

#define _CRT_SECURE_NO_WARNINGS
#include"snake.h"

//检测是否有按键被按下
void KeyFun()
{
	while (_kbhit())
	{
		//使用_getch()获取按下的键,不阻塞程序
		int key = _getch();
	}
}

//把设置光标位置的操作封装成为一个函数
void SetPos(int x, int y)
{
	//获得标准输出设备的句柄
	HANDLE houtput = GetStdHandle(STD_OUTPUT_HANDLE);

	//修改光标位置:COORD是win32自定义的关于光标在控制台的位置的结构体类型
	COORD pos = { x,y };

	//设置光标位置
	SetConsoleCursorPosition(houtput, pos);
}

//打印地图
void CreatMap()
{
	int i = 0;
	for (int i = 0; i <= 100; i += 2)
	{
		wprintf(L"%lc", WALL);
	}
	SetPos(0, 36);
	for (int i = 0; i <= 100; i += 2)
	{
		wprintf(L"%lc", WALL);
	}
	for (int i = 1; i <= 36; i ++)
	{
		SetPos(0, i);
		wprintf(L"%lc", WALL);
	}
	for (int i = 1; i <= 36; i++)
	{
		SetPos(100, i);
		wprintf(L"%lc", WALL);
	}
}

//打印欢迎界面
void WelcomeToGame()
{
	//第一界面(欢迎界面)
	SetPos(62, 14);
	printf("欢迎来到贪吃蛇小游戏!");
	SetPos(64, 16);
	system("pause");
	system("cls");//清理屏幕
	//第二界面(游戏功能介绍)
	SetPos(50, 12);
	printf("1、用 ↑ . ↓ . ← . → 分别控制蛇的移动, F3为加速,F4为减速!");
	SetPos(50, 13);
	printf("2、加速将可以得到更高的分数!");
	SetPos(65, 15);
	system("pause");
	system("cls");//清理屏幕
}

//创建1个蛇身的节点
pSnakeNode CreatSnakeNode()
{
	pSnakeNode ret = (pSnakeNode)malloc(sizeof(SnakeNode));
	if (ret == NULL)
	{
		perror("CreatSnakeNode::fail\n");
		return NULL;
	}
	return ret;
}

//初始化蛇身
void InitSnake(pSnake ps)
{
	pSnakeNode cur = NULL;
	//创建5个蛇身的节点
	for (int i = 1; i <= 5; i++)
	{
		cur = CreatSnakeNode();
		cur->next = NULL;
		cur->x = POS_X + i * 2;
		cur->y = POS_Y;
		//将5个蛇身节点串起来
		if (ps->_pSnakeHead == NULL)
		{//蛇头为空就直接插入
			ps->_pSnakeHead = cur;
		}
		else//头插
		{
			cur->next = ps->_pSnakeHead;
			ps->_pSnakeHead = cur;
		}
	}
	cur = ps->_pSnakeHead;
	while (cur)
	{
		SetPos(cur->x,cur->y);
		wprintf(L"%lc", BODY);
		cur = cur->next;
	}
	ps->_dri = RIGHT;//方向默认向右
	ps->_foodWeight = 10;
	ps->_score = 0;
	ps->_sleepTime = 200;
	ps->_state = OK;
}

//初始化食物
void CreateFood(pSnake ps)
{
	//先随机生成食物的坐标
	int x = 0;
	int y = 0;
again:
	//生成的位置必须在地图内部
	do
	{
		x = rand() % 97 + 2;
		y = rand() % 35 + 1;
	} while (x % 2 != 0);
	pSnakeNode cur = ps->_pSnakeHead;
	//判断食物位置是否与蛇身重叠
	while (cur)
	{
		if (cur->x == x && cur->y == y)
		{
			goto again;
		}
		cur = cur->next;
	}
	//打印食物
	SetPos(x, y);
	wprintf(L"%lc", FOOD);
	pSnakeNode food = CreatSnakeNode();
	food->x = x;
	food->y = y;
	food->next = NULL;
	//将食物节点放到ps中维护起来
	ps->_pFood = food;
}

//打印帮助手册
void PrintHelpInfo()
{
	SetPos(104, 16);
	printf("--------------------------------------------");
	SetPos(104, 17);
	printf("|1、不能撞墙,不能咬到自己!               |");
	SetPos(104, 18);
	printf("|2、用 ↑ . ↓ . ← . → 分别控制蛇的移动! |");
	SetPos(104, 19);
	printf("|3、F3为加速,F4为减速!                   |");
	SetPos(104, 20);
	printf("|4、按Esc退出游戏,按空格暂停游戏 !        |");
	SetPos(104, 21);
	printf("--------------------------------------------");
	SetPos(60, 17);
}

//游戏暂停
void Pause()
{
	while(1)
	{
		if (KEY_PRESS(VK_SPACE))
		{
			break;
		}
		Sleep(200);
		KeyFun();
	}
}

//吃掉食物
void EatFood(pSnakeNode pn, pSnake ps)
{
	//头插吃掉食物
	ps->_pFood->next = ps->_pSnakeHead;
	ps->_pSnakeHead = ps->_pFood;
	ps->_score += ps->_foodWeight;//分数增加
	//打印蛇身
	pSnakeNode cur = ps->_pSnakeHead;
	while (cur)
	{
		SetPos(cur->x, cur->y);
		wprintf(L"%lc", BODY);
		cur = cur->next;
	}
	//释放刚刚malloc的位置
	free(pn);
	pn = NULL;
	//食物被吃掉了,那就再创建一个食物
	CreateFood(ps);
}

//下一个位置不是食物
void NoFood(pSnake ps,pSnakeNode pn)
{
	//头插
	pn->next = ps->_pSnakeHead;
	ps->_pSnakeHead = pn;
	pSnakeNode cur = ps->_pSnakeHead;
	while (cur->next->next!=NULL)
	{
		SetPos(cur->x, cur->y);
		wprintf(L"%lc",BODY);
		cur = cur->next;
	}
	//把最后一个节点打印成两个空格
	SetPos(cur->next->x, cur->next->y);
	printf("  ");
	//释放最后一个节点
	free(cur->next);
	cur->next = NULL;
}

//蛇走一步
void SnakeMove(pSnake ps)
{
	//创建一个节点来记录蛇头的下一个位置
	pSnakeNode nextHead = CreatSnakeNode();
	nextHead->next = NULL;
	switch (ps->_dri)
	{
	case UP:
		nextHead->x = ps->_pSnakeHead->x;
		nextHead->y = ps->_pSnakeHead->y - 1;
		break;
	case DOWN:
		nextHead->x = ps->_pSnakeHead->x;
		nextHead->y = ps->_pSnakeHead->y +1;
		break;
	case LEFT:
		nextHead->y = ps->_pSnakeHead->y;
		nextHead->x = ps->_pSnakeHead->x - 2;
		break;
	case RIGHT:
		nextHead->y = ps->_pSnakeHead->y;
		nextHead->x = ps->_pSnakeHead->x + 2;
		break;
	default:
		break;
	}
	//判断下一个节点是不是食物
	if((ps->_pFood->x == nextHead->x) && (ps->_pFood->y == nextHead->y))
	{
		//下一个是食物那就吃掉食物
		EatFood(nextHead, ps);
	}
	else
	{
		//下一个位置不是食物
		NoFood(ps, nextHead);
	}
	//
	KillByWall(ps);
	KillBySelf(ps);
}

//检查是否撞墙
void KillByWall(pSnake ps)
{
	if (ps->_pSnakeHead->x == 0
		|| ps->_pSnakeHead->x == 98
		|| ps->_pSnakeHead->y == 0
		|| ps->_pSnakeHead->y == 36)
	{
		ps->_state = KILL_BY_WALL;
		return;
	}
	return;
}

//检查是否撞到自己
void KillBySelf(pSnake ps)
{
	pSnakeNode cur = ps->_pSnakeHead->next;
	while (cur)
	{
		if ((cur->x == ps->_pSnakeHead->x) &&
			(cur->y == ps->_pSnakeHead->y))
		{
			ps->_state = KILL_BY_SELF;
			return;
		}
		cur = cur->next;
	}
	return;
}

//游戏初始化
void GameStart(pSnake ps)
{
	//0. 先设置窗口的大小再隐藏光标
	system("mode con cols=150 lines=40");
	system("title 贪吃蛇");
	//获得标准输出设备的句柄
	HANDLE houtput = GetStdHandle(STD_OUTPUT_HANDLE);
	//CONSOLE_CURSOR_INFO是win32自定义的一个结构体类型,里面包含了光标的比例和可见度
	CONSOLE_CURSOR_INFO cursorInfo = { 0 };
	//获得光标信息
	GetConsoleCursorInfo(houtput, &cursorInfo);
	//修改控制台的光标信息
	cursorInfo.dwSize = 100;//比例
	cursorInfo.bVisible = false;//可见度
	//设置光标的信息
	SetConsoleCursorInfo(houtput, &cursorInfo);

	//1. 打印欢迎界面和游戏功能介绍
	WelcomeToGame();
	//2. 绘制地图
	CreatMap();
	//3. 蛇身初始化
	InitSnake(ps);
	//4. 食物初始化
	CreateFood(ps);
}

//游戏运行
void GameRun(pSnake ps)
{
	PrintHelpInfo();
	do 
	{
		SetPos(104, 12);
		printf("按空格键开始游戏!");
		SetPos(104, 13);
		printf("您当前的总分是%3d", ps->_score);
		SetPos(104, 14);
		printf("当前每个食物的总分是%3d", ps->_foodWeight);
		if (KEY_PRESS(VK_UP) && ps->_dri != DOWN)
		{
			ps->_dri = UP;//上
		}
		else if (KEY_PRESS(VK_DOWN) && ps->_dri != UP)
		{
			ps->_dri = DOWN;//下
		}	
		else if(KEY_PRESS(VK_LEFT) && ps->_dri != RIGHT)
		{
			ps->_dri = LEFT;//左
		}
		else if(KEY_PRESS(VK_RIGHT) && ps->_dri != LEFT)
		{
			ps->_dri = RIGHT;//右
		}
		else if (KEY_PRESS(VK_SPACE) )
		{
			Pause();//暂停
		}
		else if (KEY_PRESS(VK_ESCAPE))
		{
			ps->_state = END_NORMAL;//正常退出
		}
		else if (KEY_PRESS(VK_F3))
		{
			//加速
			if (ps->_sleepTime>80)
			{
				ps->_sleepTime -= 30;
				ps->_foodWeight += 2;
			}
		}
		else if (KEY_PRESS(VK_F4))
		{
			//减速
			if (ps->_foodWeight>2)
			{
				ps->_sleepTime += 30;
				ps->_foodWeight -= 2;
			}
		}
		//走一步
		SnakeMove(ps);
		//每走一步休息一下
		Sleep(ps->_sleepTime);
		KeyFun();
	} while (ps->_state == OK);
}

//游戏善后
void GameEnd(pSnake ps)
{
	pSnakeNode cur = ps->_pSnakeHead;
	while (cur)
	{
		pSnakeNode del = cur;
		cur = cur->next;
		free(del);
	}
	system("cls");
	SetPos(62, 16);
	switch (ps->_state)
	{
	case END_NORMAL:
		printf("您主动退出游戏!\n");
		break;
	case KILL_BY_WALL:
		printf("您撞墙了!\n");
		break;
	case KILL_BY_SELF:
		printf("您撞到自己了!\n");
		break;
	}
	SetPos(62, 17);
	printf("您最终的成绩是:%d", ps->_score);
	Sleep(2000);
	KeyFun();
	system("cls");
	SetPos(62, 18);
	printf("您要再来一局吗?(Y/N):");
}

5、 完结散花

好了,这期的分享到这里就结束了~

如果这篇博客对你有帮助的话,可以用你们的小手指点一个免费的赞并收藏起来哟~

如果期待博主下期内容的话,可以点点关注,避免找不到我了呢~

我们下期不见不散~~

贪吃蛇游戏C语言破解:成为编程高手的必修课!,C语言实战项目,机器学习​​贪吃蛇游戏C语言破解:成为编程高手的必修课!,C语言实战项目,机器学习​​文章来源地址https://www.toymoban.com/news/detail-857321.html

到了这里,关于贪吃蛇游戏C语言破解:成为编程高手的必修课!的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【C语言高阶篇】成为编程高手必学内容,程序中的动态内存分配我不允许还有人不会!

    🎬 鸽芷咕 :个人主页  🔥 个人专栏 :《C语言初阶篇》 《C语言进阶篇》 ⛺️生活的理想,就是为了理想的生活!    🌈 hello! 各位宝子们大家好啊,又是新的一天开始了,今天给大家带来的是动态内存规划这一章节!    ⛳️ 我们在创建变量的时候大家都知道大小是固

    2024年02月16日
    浏览(20)
  • [人工智能] 程序员超级进化ai必修课+AIGC全栈项目实战课

    课程内容: ├10_02【Java项目】基于ChatGPT的瑞吉外卖系统开发-01.ChatGPT在Java中的应用 .mp4 ├11_02【Java项目】基于ChatGPT的瑞吉外卖系统开发-02.多轮对话和编写文档 .mp4 ├12_02【Java项目】基于ChatGPT的瑞吉外卖系统开发-03.项目介绍和环境搭建 .mp4 ├13_02【Java项目】基于ChatGPT的瑞吉

    2024年02月03日
    浏览(18)
  • 掌握区块链浏览器的使用,应该是每一个币圈人的必修课。

    掌握区块链浏览器 http://etherscan.io 的使用,应该是每一个币圈人的必修课。 etherscan 其实并不简单,除了查询交易状态、钱包余额,它能干的事还非常多! 【下面介绍关于 etherscan 的10个实用功能】 包括查看GAS、解除授权、NFT合约mint、聊天、大户追踪、防欺诈钓鱼、多链搜索

    2024年01月16日
    浏览(27)
  • 实用!SD人物表情提示词合辑;秒变大神的Python速查表;开源LLM微调训练指南;LLM开发必修课 | ShowMeAI日报

    👀 日报周刊合集 | 🎡 生产力工具与行业应用大全 | 🧡 点赞关注评论拜托啦! Pensive 沉思 Smiling 微笑 Disgusted 厌恶 Laughing 大笑 Shocked 震惊 Frowning 皱眉 Crying 哭泣 Biting lip 咬唇 Pouting 掀嘴 Rolling eyes 翻白眼 winking 眨眼 Blushing 脸红 Yawning 打哈欠 Nervous 紧张 Worried 担忧 Staring 凝视

    2024年04月17日
    浏览(21)
  • 从代码生成到问题解答,InsCode AI助你成为编程及写作高手

    随着ChatGPT的火爆,AIGC技术正在成为全球关注的焦点。在中国,CSDN作为国内顶流技术博客,也加紧了研发相关AIGC的实用应用。最近,CSDN上线了CSDN AI写作助手InsCode AI,这是一款能够帮助用户高效创作文章,同时也可以作为对话式AI回答用户问题的工具。 InsCode AI 是CSDN推出的一

    2024年02月09日
    浏览(26)
  • 学生学python编程---实现贪吃蛇小游戏+源码

    前言 这几年人工智能技术大发展,Python因此几乎成了第一位的语言。实际上,多年来,它不仅在软件工程师中得到广泛使用,也是各行业通用的专家语言,就是说,不管孩子以后做什么,都可能用得着。准备针对我自己上小学的孩子,每周抽出些时间,通过学习他们感兴趣的

    2023年04月09日
    浏览(20)
  • 【C语言】实现贪吃蛇游戏

    我们要用C语言来实现贪吃蛇游戏之前,得了解C语言函数、枚举、结构体、动态内存管理、预处理指令、链表和Win32 API等等的一些相关知识。 关于链表和函数,在之前的文章中都有写过了,友友们可以自行查看。剩下知识会在之后的博客中所提及,请大家多多关注。 这里主要

    2024年02月03日
    浏览(14)
  • Python “贪吃蛇”游戏,在不断改进中学习pygame编程

    目录 前言 改进过程一 增加提示信息 原版帮助摘要 pygame.draw pygame.font class Rect class Surface 改进过程二 增加显示得分 改进过程三 增加背景景乐 增加提示音效 音乐切换 静音切换 mixer.music.play 注意事项 原版帮助摘要 pygame.mixer pygame.mixer.Sound 改进过程四 增加WASD方向键 增加退出事

    2024年02月12日
    浏览(24)
  • C语言——贪吃蛇小游戏

    目录 一、ncurse 1.1 为什么需要用ncurse: 1.2 ncurse的输入输出: 1.2.1 如何使用ncurse: 1.2.2 编译ncurse的程序: 1.2.3 测试输入一个按键ncurse的响应速度: 1.3 ncurse上下左右键获取: 1.3.1 如何查看宏定义的.h文件: 1.3.2 ncurse上下左右键获取: 二、地图规划 2.1 地图规划算法显示第一

    2024年02月07日
    浏览(19)
  • 【C语言小游戏】贪吃蛇

      使⽤C语⾔在Windows环境的控制台中模拟实现经典⼩游戏贪吃蛇 实现基本的功能: 贪吃蛇地图绘制 蛇吃⻝物的功能 (上、下、左、右⽅向键控制蛇的动作) 蛇撞墙死亡 蛇撞⾃⾝死亡 计算得分 蛇⾝加速、减速 暂停游戏 游戏指引页面 游戏页面 指针; 动态内存; 结构体;

    2024年01月19日
    浏览(18)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包