初学者就爱开发点小游戏,比如贪吃蛇、俄罗斯方块等,开发这种小游戏就必须有按键控制,一般情况下我们是直接用getch()函数接收按键,然后转换成对应的ASCII码,再通过与ASCII码比较判断用户到底是按了什么键,然后根据按键去执行相应的操作,比如移动、旋转。
但是最近实践我发现这其实没那么简单,举个例子:比如贪吃蛇,当用户按下“向上的方向键”时,要控制蛇往上走,为了说明问题,简化一点,如果按了向上的方向键则输出“up”,其他方向键类似。一般我们会去查ASCII码表(下面有),
如图,向上的方向键是38,然后我们就会写出这么一个小程序:
#include<stdio.h>
#include<conio.h>
int main()
{
char ch;
while(true)
{
ch=getch();
if(ch == 38)//向上键
printf("up");
if(ch == 27)//ESC键
printf("ESC");
}
}
感兴趣的朋友可以试试编译运行一下,你就会发现问题:如果按“ESC”键,则输出“ESC”,但是无论怎么按向上的方向键,始终不输出“up”!这是问什么呢?我也不知道。当然通过查ASCII码表,我们会发现,其实ASCII38对应的是’&’,如果输入’&’,就会输出‘up’!晕…哪位大神知道为什么?回复一下,小弟不胜感激。
但问题还是要解决的,键盘上的向上方向键到底怎么接收呢?后来查了很多资料,看了很多实例,我发现,如果将38改为72就能输出‘up’!太神奇了,我们查ASCII码72对应的字符,就会发现那其实是‘H’,也就是说,如果我们输入‘H’,也能输出‘up’,事实确实如此!太奇怪了!键盘上的‘H’和向上方向键终归是不一样吧,一样的话不久麻烦了吗,平常打字的时候按向上方向键也没见输出‘H’,哈,开个玩笑。这个问题看着小,如果仅仅在贪吃蛇这种小游戏里还没什么,用户一般不会想到去按‘H’的,但是如果在大型软件或大型游戏中呢?说不定这个小bug会让整个系统崩溃!说不定黑客通过这个bug就入侵了!
一个问题刚解决,又一个问题来了,那么我们到底怎样才能避免上面的问题呢?冥思苦想了良久,坐立不安,心神恍惚,茶饭不思,精神萎靡,头晕脑胀…终于,在今天,突发灵感,想到方案啦!哈哈,下面让我慢慢道来:
我是这样想的,既然查ASCII码表那么麻烦,查出来还不能用,那么为什么不自己开发一个小程序呢,用户按一个键,然后输出对应的ASCII码,代码很简单,学过C的都会写,我把代码贴出来:
#include<stdio.h>
#include<conio.h>
int main()
{
char c;
while(1)
{
c=getch();
printf("%d %x %c\n",c,c,c);
}
}
代码就是这么个意思:接收一个键盘按键,然后输出对应的十进制ASCII码,然后输出对应的16进制的ASCII码,最后输出按键对应的字符(如果能显示就会在屏幕上显示)。运行一下,你就会发现问题,一个惊天动地的问题,一个难以置信的问题,当按下向上的方向键后,竟然出现这个(檫亮眼,看截图)怎么回事?看清楚了吗?再擦擦眼,仔细看,没错,就是这样,下面那一行还好理解,就是72嘛,刚才我们已经做过实验了,但是,上面一行怎么回事?我们不是就按了一个键吗,怎么会显示两行?再看源代码,不对啊,应该只输出一行才对,我们预期的应该是只输出下面以后那个的,上面一行到底是什么?输出的-32又对应着什么?为什么会有上面一行?小弟我是真晕了,还是请教各位大仙大神大牛,Orz…
我是这样想的,也不知到对不对,或许,当你按下向上的方向键后,实际按的是两个键,啊!?不懂,我也不懂,只是猜测,然后第一个键就是上面显示的-32,第二个键才是真正得到的ASCII码。我也不知道对不对,反正如果按我的想法的话,那个相同按键的问题就能解决了,看代码:
#include<stdio.h>
#include<conio.h>
int main()
{
char ch;
while(true)
{
ch=getch();
if(ch == -32)
{
ch=getch();
if(ch==72)//向上键
printf("up");
}
if(ch==27)//ESC键
printf("ESC");
}
}
这样的话,只有在按下向上的方向键后才输出‘up’输入‘H’就不会输出‘up’,当然,在开发中,我们就可以这样做了,最起码能保证不会出问题,但是到底为什么是这样,我也不明白,还请高人指点。