震惊!居然还有人不知道写控制台小游戏必备的函数!

Posted 2020.7.30

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了震惊!居然还有人不知道写控制台小游戏必备的函数!相关的知识,希望对你有一定的参考价值。

这些函数都是从其他作者那里学习,本人总结,在此十分感谢他们!



关闭快速编辑模式

在win 7及以后的系统中,当用户左击控制台,会使程序暂停,其目的是便于用户复制输出内容,右击默认粘贴内容。进行鼠标点击的前提是关闭快速编辑模式。方法如下:
参考文章

了解句柄

句柄是一种特殊指针(另一种说法为一种整型),用于标识应用程序中的对象(如窗口,按钮,图标等)。当前系统中每一个进程,每一个控件,都根据其虚拟内存地址拥有其对应的唯一句柄。于是,我们可以通过一个句柄找到对应的对象来指定操作。
数值上,是一个32位无符号整型值(32位系统下);逻辑上,相当于指针的指针;形象理解上,是Windows中各个对象的一个唯一的、固定不变的ID;作用上,Windows使用句柄来标识诸如窗口、位图、画笔等对象,并通过句柄找到这些对象。
下面,关于句柄,再交代一些关键性细节:
1.所谓“唯一”、“不变”是指在程序的一次运行中。如果本次运行完,关闭程序,再次启动程序运行,那么这次运行中,同一对象的句柄的值和上次运行时比较,一般是不一样的。
其实这理解起来也很自然,所谓“一把归一把,这把是这把,那把是那把,两者不相干”(“把”是形象的说法,就像打牌一样,这里指程序的一次运行)。
2.句柄是对象生成时系统指定的,属性是只读的,程序员不能修改句柄。
3.不同的系统中,句柄的大小(字节数)是不同的,可以使用sizeof()来计算句柄的大小。
4.通过句柄,程序员只能调用系统提供的服务(即API调用),不能像使用指针那样,做其它的事。
参考文章

一、在控制台指定位置输出

#include<stdio.h>
#include<windows.h>
int main(void)

	COORD pos=10,10;
	SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE),pos);
			printf("我爱你")

首先需要包含头文件windows.h,其次需要定义一个COORD类型的变量,什么是COORD类型的变量呢?

1、COORD类型

COORD是Windows API中定义的一种结构,表示一个字符在控制台屏幕上的坐标。其定义为:

typedef struct _COORD

SHORT X; // horizontal coordinate

SHORT Y; // vertical coordinate

COORD;

2.GetStdHandle()

简述
GetStdHandle是一个Windows API函数。它用于从一个特定的标准设备(标准输入、标准输出或标准错误)中取得一个句柄(用来标识不同设备的数值)。因为很多API函数都需要用到句柄,所以GetStdHandle是一个很重要的函数。
  
函数原型(包含在头文件windows.h中)
ANDLE WINAPI GetStdHandle( In DWORD nStdHandle);

参数
GetStdHandle函数的参数可以是下列之一

参数含义
STD_INPUT_HANDLE标准输入句柄
STD_OUTPUT_HANDLE标准输出句柄
STD_ERROR_HANDLE标准错误句柄

注:只有这三种参数哦。不同的参数用于获取不同标准设备的句柄。

返回值
都知道GetStdHandle()是用来获取句柄的啦,那它的返回值当然是个句柄喽。这一点从函数原型也能看出来。
参考文章

3、SetConsoleCursorPosition()

SetConsoleCursorPosition()来自于文件"windows.h",使用时记得引用此头文件。

这个函数的功能即是字面意思,即移动命令行中光标的位置。这里要注意的是,每次调用这个函数都是默认从左上角开始偏移,而与当前光标停留的位置无关。

我们查看定义发现,调用这个函数需要传入两个参数,都是自定义类型,分别为 HANDLE 和 COORD。

SetConsoleCursorPosition(In HANDLE hConsoleOutput,In COORD dwCursorPosition);
dwCursorPosition参数即示例程序中的pos结构,表示将光标移动到横坐标为pos.X,纵坐标pos.Y处,第一个参数是句柄,通过调用GetStdHandle()从标准输出中获取。
参考文章

二、鼠标操作

我们知道,Windows.h头文件给我们提供了获取鼠标相对屏幕位置的方法,和窗口相对屏幕位置的方法,但是我们需要获得是鼠标相对窗口的坐标。
根据数学关系:鼠标相对窗口的横坐标=鼠标相对屏幕的横坐标-窗口左边相对屏幕的坐标

1、获取鼠标相对屏幕坐标

用到的类型:POINT
POINT结构体类存储鼠标横纵坐标(mouse.x,mouse.y)

BOOL GetCursorPos(LPPOINT lpPoint)

函数原型:BOOL GetCursorPos(LPPOINT lpPoint)
参数:IpPoint:POINT结构指针,该结构接收光标的屏幕坐标。
作用:获取鼠标相对屏幕坐标,并存入POINT类型的变量中。

#include<stdio.h>
#include<windows.h>
#include<stdbool.h>
#include<stdlib.h>
int main(void)

	COORD pos=0,0;
	POINT *mouse;
	mouse=(POINT*)malloc(sizeof(POINT)+64);//为什么要加64我也不清楚
	while(true)
	
 		GetCursorPos(mouse);//返回鼠标对应的坐标并存储在ptrpos中
 		SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE),pos);
			printf("鼠标相对屏幕;\\nmouse->x=%d mouse->y=%d    \\n",mouse->x,mouse->y);
		Sleep(100);
		

2、获取控制台相对屏幕坐标

大家可以直接看程序,这些函数具体信息可以不掌握,会用就行。
用到的类型:LPRECT
typedef struct tagRECT

LONG left;
LONG top;
LONG right;
LONG bottom;
RECT, *PRECT, NEAR *NPRECT, FAR *LPRECT;

RECT, PRECT, NPRECT, LPRECT;它们之间有什么区别?
RECT是结构体类型,其余三个都是指向RECT的指针类型。
RECT是一个表示矩形的结构
PRECT表示指向矩形结构的指针
NPRECT表示指向矩形结构的近指针(NEAR)
LPRECT表示指向矩形结构的长指针(FAR)

LPRECT结构体类存储某一指定窗口(比如控制台窗口)相对屏幕的位置(top、bottom、left、right)
用到的函数:

1、BOOL WINAPI SetConsoleTitle(__in LPCTSTR lpConsoleTitle)

函数原型:BOOL WINAPI SetConsoleTitle(__in LPCTSTR lpConsoleTitle);
参数:字符串地址
作用:设置控制台窗口的标题

2、HWND FindWindow(LPCSTR lpClassName,LPCSTR lpWindowName);

函数原型
HWND FindWindow(LPCSTR lpClassName,LPCSTR lpWindowName);
参数
lpClassName
指向一个以NULL字符结尾的、用来指定类名的字符串或一个可以确定类名字符串的原子。如果这个参数是一个原子,那么它必须是一个在调用此函数前已经通过GlobalAddAtom函数创建好的全局原子。这个原子(一个16bit的值),必须被放置在lpClassName的低位字节中,lpClassName的高位字节置零。
如果该参数为null时,将会寻找任何与lpWindowName参数匹配的窗口。
lpWindowName
指向一个以NULL字符结尾的、用来指定窗口名(即窗口标题)的字符串。如果此参数为NULL,则匹配所有窗口名。
返回值
如果函数执行成功,则返回值是拥有指定窗口类名或窗口名的窗口的句柄。
如果函数执行失败,则返回值为 NULL 。可以通过调用GetLastError函数获得更加详细的错误信息。

3、BOOL GetWindowRect(HWND hWnd,LPRECT lpRect)

函数原型
BOOL GetWindowRect(HWND hWnd,LPRECT lpRect);
在Visual Studio 2005中,函数原型为void GetWindowRect(LPRECT lpRect) const;是属于CWnd类的函数.
参数
HWND:窗口句柄。
lpRect:指向一个RECT结构的指针,该结构接收窗口的左上角和右下角的屏幕坐标。
变量:
left ;top; right;bottom;
分别表示该窗口的/左侧/顶部/右侧/底部坐标
返回值:
如果函数成功,返回值为非零:如果函数失败,返回值为零。若想获得更多错误信息,请调用GetLastError函数。

#include<stdio.h>
#include<windows.h>
#include<stdbool.h>
#include<stdlib.h>
int main(void)

	COORD pos=0,0;
	SetConsoleTitle("点赞关注不迷路");//设定窗口标题
	LPRECT console;//LPRECT结构体类存储某一指定窗口(比如控制台窗口)相对屏幕的位置(top、bottom、left、right)
	console=(LPRECT)malloc(sizeof(LPRECT)+64);//为结构体指针分配内存空间
	while(true)
	
		HWND hwnd=FindWindow(NULL,"点赞关注不迷路");//根据上述设定的标题查找句柄,第一个形参设为NULL意味着查找系统中所有句柄,因为需要动态获取窗口位置所以它需要写在循环体中
		GetWindowRect(hwnd,console);//根据查找标题"贪吃蛇"得到的句柄返回对于窗口的坐标并存储在console中
 		SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE),pos);
			printf("窗口相对屏幕;\\nconsole->left=%d console->top=%d    \\n",console->left,console->top);
		Sleep(100);
		

拖动窗口就可以看见坐标变化,大家可能会发现,在左边输出了一串莫名奇妙的数字,我也不知道是什么东西
结合以上两个程序,便可得到获取鼠标相对控制台的坐标:

#include<stdio.h>
#include<windows.h>
#include<time.h>
#include<stdbool.h>
#define length 10
#define wide 5
void Eage(void);
int main(void)

	Eage();
	
	SetConsoleTitle("点赞关注不迷路");//设定窗口标题
	int x,y;
	POINT *mouse;//POINT结构体类存储数标横纵坐标(mouse.x,mouse.y)
	LPRECT console;//LPRECT结构体类存储某一指定窗口(比如控制台窗口)相对屏幕的位置(top、bottom、left、right)
  	mouse=(POINT*)malloc(sizeof(POINT)+64);
 	console=(LPRECT)malloc(sizeof(LPRECT)+64);//为结构体指针分配内存空间

   while(true)
   
		HWND hwnd=FindWindow(NULL,"点赞关注不迷路");//根据上述设定的标题查找句柄,第一个形参设为NULL意味着查找系统中所有句柄
	   	
		 /*动态获取鼠标位置*/
		GetWindowRect(hwnd,console);//根据查找标题"贪吃蛇"得到的句柄返回对于窗口的坐标并存储在console中
		GetCursorPos(mouse);//返回鼠标对应的坐标并存储在ptrpos中
  	 	x=mouse->x-console->left;//鼠标横坐标-控制台窗口左端横坐标得到鼠标相对控制台窗口的横坐标
	    y=mouse->y-console->top;//同理得到鼠标相对的纵坐标
  	    COORD pos=0,wide+1;
   	    SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE),pos);
			printf("相对坐标:x=%d y=%d    \\n",x,y);
		if(GetAsyncKeyState(VK_RBUTTON))//左键应该是默认暂停
		
			//如果鼠标左键按下,其中VK_LBUTTON是windows.h库中定义的宏,对应鼠标左键对应的ASCII值
   	     	if((7<=x&&x<96)&&(y>=37&&y<123))//根据动态获取的坐标确定的边界
   	     	
   	     		puts("成功退出");
        		break;
   	     	
		
		Sleep(100);
	


void Eage(void)

	COORD pos;
	for(int i=0;i<length;i++)
	
		pos=i,0;
		SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE),pos);
			printf(".");
		pos=i,wide;
		SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE),pos);
			printf(".");
	
	pos=1,wide/2;
	SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE),pos);
			printf("右键退出");
	for(int i=0;i<wide;i++)
	
		pos=0,i;
		SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE),pos);
			printf(".");
		pos=length,i;
		SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE),pos);
			printf(".");
	

以上程序涉及函数:GetAsyncKeyState()判断某一个按键是否按下
参考文章

三、键盘操作

kbhit()

#include<stdio.h>
#include<conio.h>
#include<windows.h>
#include<time.h>
int main(void)

	COORD pos=10,5;
	char ch;
	SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE),pos);
		printf("#");
	while(true)
	
		
		if(kbhit())
		
			switch(ch=getch())
			
				case 'w':pos.Y--;break;
				case 'a':pos.X--;break;	
				case 's':pos.Y++;break;
				case 'd':pos.X++;break;
			
		
		SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE),pos);
			printf("#");
		Sleep(100);
	

kbhit()是一个C和C++函数,用于非阻塞地响应键盘输入事件。
原型:int kbhit(void)
头文件:conio.h
功能及返回值: 检查当前是否有键盘输入,若有则返回一个非0值,否则返回0。

注:如果想要删除输出的字符,可以在该字符的坐标处输出一个空格。

以上是关于震惊!居然还有人不知道写控制台小游戏必备的函数!的主要内容,如果未能解决你的问题,请参考以下文章

震惊!居然还有人不知道写控制台小游戏必备的函数!

震惊!居然还有人不知道写控制台小游戏必备的函数!

不是吧不是吧居然还有人不知道系统架构的演变过程?

震惊,长沙一男子居然!!!(MySQL聚合函数)

震惊,长沙一男子居然!!!(MySQL聚合函数)

震惊,长沙一男子居然!!!(MySQL聚合函数)