贪吃蛇游戏(讲解part1)

1.贪吃蛇游戏

那么在实现贪吃蛇游戏之前,我们先了解一下贪吃蛇的玩法:

相信很多人都玩过贪吃蛇游戏,没有玩过的举手一下。

游戏规则:

1)蛇不能穿墙

2)蛇不能咬自己

3)使用键盘上的↑,↓,←,→来控制蛇的移动

4)F1为蛇加速

5)F2为蛇减速

6)ESC退出游戏

7)space 空格键,暂停游戏

接下来,我们先需要绘制一个地图

2.实现要求

使用C语言在windows环境的控制台中模拟实现贪吃蛇游戏

3.会涉及到那些技术要点 

C语言函数,枚举,结构体,动态内存管理,预处理指令,链表,win32 API

4.win32 API 控制台的知识讲解

4.1 windows是多作业系统用于协调应用程序的执行、分配内存、管理资源之外,他同时也是一个很大的服务中心。

调用这个服务中心的各种服务(每一种服务就是一个可执行的函数),可以帮助应用程序达到开启视窗、描绘图形、使用周边设备。

由于这些函数服务的对象是应用程序(Application),所以称之为Application programming interface  简称为API 函数,也就是WIN32 API ,32位平台应用程序编程接口。 

总结:每一种操作系统在完成正常的操作系统该有的功能,例如文件管理,内存管理等。

还提供了一些API接口,而这些接口就是函数,将这些函数提供给程序员调用,从而实现自己想要的功能,而这个接口也叫做API。 

以windows环境为例:这些接口统称为win32 API

5.cmd的程序-终端,也叫控制台

可以使用cmd命令来设置控制台窗口的长宽,设置控制台窗口大小,30行,100列

控制台:console

windows键+R 可以快速进入CMD

然后设置控制台的大小:

mode con cols=100 lines=100 

然后回车enter

6.接下来我们创建一个空项目,来进行贪吃蛇游戏的编写

写一个test.c文件

接下来开始代码编写:

7.如何在代码上面调整控制窗口的大小?

#include <stdio.h>
#include <stdlib.h>  //包含系统函数的头文件
int main()
{
	system("mode con cols=50 lines=50");  //使用系统函数设置控制台的大小,行50,列50
	printf("hehe\n");
	return 0;
}

编译执行,很显然控制台窗口已被设置成了cols=50,lines=50,只使用于window 平台的操作dos

第二种调整方法:点击窗口上面右键,然后点击属性

从布局这边设置长宽,也就是设置cols,lines

如果我们想要了解更多关于mode指令

我们可以去微软网站,下面链接直接抵达:

mode | Microsoft Learn

而我们刚才运用到的mode的显示功能就在这里: 

修改title ,可以修改控制台的名字:

那么现在就可以看到贪吃蛇游戏在控制台显示。

那么如果在程序代码里面怎么设置:

#include <stdio.h>
#include <stdlib.h>  //包含系统函数的头文件
int main()
{
	system("mode con cols=50 lines=50");  //使用系统函数设置控制台的大小,行50,列50
	system("title 贪吃蛇");               //改变控制台名字
	printf("hehe\n");
	return 0;
}

8.控制台屏幕上的坐标COORD

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

观察一个数据:在控制台打印的时候,hehe数据都是默认从左上角开始打印:

我们要知道,这个窗口是有坐标系的:

如果(0,0)坐标要移动那么则是往X++,Y++的方向移动响应的坐标

COORD 类型的声明:

#include <windows.h> //需要包含这样的一个头文件
typedef struct _COORD{
	SHORT X;
	SHORT Y;
}COORD,*PCOORD;

COORD POS = {10,12};

9.GetStdHandle 

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

HANDLE WINAPI GetStdHandle(
  _In_ DWORD nStdHandle
);

HANDLE 是一个指针

因此可以先定义一个空指针来接收:

HANDLE handle = NULL;   //定义一个空指针来接收输出
handle = GetstdHandle(STD_OUTPUT_HANDLE);

 或者也可也这么写:

HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE); //定义一个指针handle句柄,用来获取输出设备

10.GetConsoleCursorInfo 检索有关指定控制台屏幕缓冲区的光标大小和可见性的信息

 hConsoleOutput是控制台屏幕缓冲区的句柄,该句柄具有GENERIC_READ的访问权限。

lpConsoleCursorInfo是指向GetConsoleCursorInfo 是一个结构的指针,并用于接收有关主机光标的信息。

BOOL
WINAPI
GetConsoleCursorInfo(
    _In_ HANDLE hConsoleOutput,
    _Out_ PCONSOLE_CURSOR_INFO lpConsoleCursorInfo
    );

10.1  CONSOLE_CURSOR_INFO 这是一个结构体变量,该结构变量存放了有关控制台光标的信息

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

bVisible 光标的可见性,如果光标可见,则该成员位TRUE,否则位false

//这个结构体,存放了有关控制台光标的信息
typedef struct _CONSOLE_CURSOR_INFO {
	DWORD  dwSize;
	BOOL   bVisible;
} CONSOLE_CURSOR_INFO, * PCONSOLE_CURSOR_INFO;

    cursor_info.bVisible = false; //当光标不可见是设置为false;

10.2 当我们设置cursor_info.dwSize=100; //也就是光标的刻度是满的,最大就是100

#include <stdio.h>
#include <stdlib.h>  //包含系统函数的头文件
#include <windows.h>

int main()
{
	HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);  //定义一个指针handle句柄,用来获取输出设备
	CONSOLE_CURSOR_INFO cursor_info;//cursor_info 用来存放控制台光标信息
	GetConsoleCursorInfo(handle, &cursor_info);  //把句柄传进来,获取的信息放哪里,控制台光标信息会放到cursor_info里面
	cursor_info.dwSize = 100;   //百分之百  范围只能是从1~100之间
	//cursor_info.bVisible = true;  //光标可见 默认就是为真1 
	//cursor_info.bVisible = false; //光标隐藏
	SetConsoleCursorInfo(handle, &cursor_info);

	return 0;
}

10.3 如果我们要隐藏光标,那么设置cursor_info.bVisible = false

此时,我们需要包含头文件 #include <stdbool.h>这个头文件之后就可以使用true和false了

#include <stdio.h>
#include <stdlib.h>  //包含系统函数的头文件
#include <windows.h>
#include <stdbool.h>

int main()
{
	HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);  //定义一个指针handle句柄,用来获取输出设备
	CONSOLE_CURSOR_INFO cursor_info;//cursor_info 用来存放控制台光标信息
	GetConsoleCursorInfo(handle, &cursor_info);  //把句柄传进来,获取的信息放哪里,控制台光标信息会放到cursor_info里面
	cursor_info.dwSize = 100;   //百分之百  范围只能是从1~100之间
	//cursor_info.bVisible = true;  //光标可见 默认就是为真1 
	cursor_info.bVisible = false; //光标隐藏
	SetConsoleCursorInfo(handle, &cursor_info);

	return 0;
}

那么如果我们有没有办法知道光标是不是真的隐藏了呢?

不妨可以使用getchar()来输入字符,并获取字符后观察光标是否还在?

10.4 SetConsoleCursorPostion 设置指定光标的位置

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

BOOL
WINAPI
SetConsoleCursorPosition(
    _In_ HANDLE hConsoleOutput,
    _In_ COORD dwCursorPosition
    );

当我们设置

	COORD POS = { 10,20 };
	SetConsoleCursorPosition(handle, POS);

如果我输出的值要在别的坐标打印呢?

只需要在ch=getchar();的后面加上指定的位置即可:

    COORD POS1 = { 20,10 }; //设置字符输出光标的坐标
    SetConsoleCursorPosition(handle, POS1); 

int main()
{
	HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);  //定义一个指针handle句柄,用来获取输出设备
	//CONSOLE_CURSOR_INFO cursor_info;//cursor_info 用来存放控制台光标信息
	//GetConsoleCursorInfo(handle, &cursor_info);  //把句柄传进来,获取的信息放哪里,控制台光标信息会放到cursor_info里面
	//cursor_info.dwSize = 100;   //百分之百  范围只能是从1~100之间
	//cursor_info.bVisible = true;  //光标可见 默认就是为真1 
	//cursor_info.bVisible = false; //光标隐藏
	COORD POS = { 10,20 };
	SetConsoleCursorPosition(handle, POS);
	//SetConsoleCursorInfo(handle, &cursor_info);
	int ch = getchar();
	COORD POS1 = { 20,10 };
	SetConsoleCursorPosition(handle, POS1);
	putchar(ch);
	return 0;
}

通过打印可以看到,我们输入的字符r在坐标(20,10)的位置打印出来了。 

但是这里还有个问题,如果每次想要在不同的位置打印字符,那每一次都要对这个COORD pos={10,20}的坐标进行设置,设置到指定的位置上,这样好像很麻烦。

有没有更好的办法?

10.5  SetPos(int x,int y) 编写一个函数专门用于存放光标的坐标.

作用:设置某个控制台的坐标

编写好函数之后,我们在SetPos(5,5)这个坐标打印xixi!

那么我们后续想要设置其他控制台的光标,就可以使用这个函数了。

void SetPos(int x, int y)
{
	HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
	COORD pos = { x,y };
	SetConsoleCursorPosition(handle, pos);
}

int main()
{
	SetPos(5, 5);
	printf("xixi!\n");
	return 0;
}

  • 5
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值