震惊!居然还有人不知道写控制台小游戏必备的函数!
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。
注:如果想要删除输出的字符,可以在该字符的坐标处输出一个空格。
以上是关于震惊!居然还有人不知道写控制台小游戏必备的函数!的主要内容,如果未能解决你的问题,请参考以下文章