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

Posted 2020.7.30

tags:

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

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



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

#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
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聚合函数)