首页 > 代码库 > 键盘、游戏、ASCII码引出的一系列问题

键盘、游戏、ASCII码引出的一系列问题

初学者就爱开发点小游戏,比如贪吃蛇、俄罗斯方块等,开发这种小游戏就必须有按键控制,一般情况下我们是直接用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’,当然,在开发中,我们就可以这样做了,最起码能保证不会出问题,但是到底为什么是这样,我也不明白,还请高人指点。

 

 

 

 

另外,关于按键转换成ASCII码的小程序我感觉还是比较有用的,最起码能快速得到你想要的按键或字符的ASCII,不用整天抱着个ASCII码表查,我已经做成一个小软件,在我网盘里,如果需要的话可以到我的网盘下载:http://ma6174.ys168.com/

 

 

 

另,附上ASCII码表,虽然查了也不会用,看看吧,或许能用着

 

 

ASCII值控制字符ASCII值控制字符ASCII值控制字符ASCII值控制字符
0NUT32(space)64@96
1SOH3365A97a
2STX3466B98b
3ETX35#67C99c
4EOT36$68D100d
5ENQ37%69E101e
6ACK38&70F102f
7BEL39,71G103g
8BS40(72H104h
9HT41)73I105i
10LF42*74J106j
11VT43+75K107k
12FF44,76L108l
13CR45-77M109m
14SO46.78N110n
15SI47/79O111o
16DLE48080P112p
17DCI49181Q113q
18DC250282R114r
19DC351383X115s
20DC452484T116t
21NAK53585U117u
22SYN54686V118v
23TB55787W119w
24CAN56888X120x
25EM57989Y121y
26SUB58:90Z122z
27ESC59;91[123{
28FS60<92\124|
29GS61=93]125}
30RS62>94^126~
31US63?95127DEL
 
NULVT 垂直制表SYN 空转同步
SOH  标题开始FF   走纸控制ETB  信息组传送结束
STX  正文开始CR   回车CAN  作废
ETX  正文结束SO   移位输出EM   纸尽
EOY  传输结束SI    移位输入SUB  换置
ENQ  询问字符DLE  空格ESC  换码
ACK  承认DC1  设备控制1FS   文字分隔符
BEL  报警DC2  设备控制2GS   组分隔符
BS   退一格DC3  设备控制3RS   记录分隔符
HT   横向列表DC4  设备控制4US   单元分隔符
LF   换行NAK  否定DEL  删除
 

键盘常用ASCII码
ESC键 VK_ESCAPE (27)
回车键: VK_RETURN (13)
TAB键: VK_TAB (9)
Caps Lock键: VK_CAPITAL (20)
Shift键: VK_SHIFT ($10)
Ctrl键: VK_CONTROL (17)
Alt键: VK_MENU (18)
空格键: VK_SPACE ($20/32)
退格键: VK_BACK (8)
左徽标键: VK_LWIN (91)
右徽标键: VK_LWIN (92)
鼠标右键快捷键:VK_APPS (93)

Insert键: VK_INSERT (45)
Home键: VK_HOME (36)
Page Up: VK_PRIOR (33)
PageDown: VK_NEXT (34)
End键: VK_END (35)
Delete键: VK_DELETE (46)

方向键(←): VK_LEFT (37)
方向键(↑): VK_UP (38)
方向键(→): VK_RIGHT (39)
方向键(↓): VK_DOWN (40)

F1键: VK_F1 (112)
F2键: VK_F2 (113)
F3键: VK_F3 (114)
F4键: VK_F4 (115)
F5键: VK_F5 (116)
F6键: VK_F6 (117)
F7键: VK_F7 (118)
F8键: VK_F8 (119)
F9键: VK_F9 (120)
F10键: VK_F10 (121)
F11键: VK_F11 (122)
F12键: VK_F12 (123)

Num Lock键: VK_NUMLOCK (144)
小键盘0: VK_NUMPAD0 (96)
小键盘1: VK_NUMPAD0 (97)
小键盘2: VK_NUMPAD0 (98)
小键盘3: VK_NUMPAD0 (99)
小键盘4: VK_NUMPAD0 (100)
小键盘5: VK_NUMPAD0 (101)
小键盘6: VK_NUMPAD0 (102)
小键盘7: VK_NUMPAD0 (103)
小键盘8: VK_NUMPAD0 (104)
小键盘9: VK_NUMPAD0 (105)
小键盘.: VK_DECIMAL (110)
小键盘*: VK_MULTIPLY (106)
小键盘+: VK_MULTIPLY (107)
小键盘-: VK_SUBTRACT (109)
小键盘/: VK_DIVIDE (111)

Pause Break键: VK_PAUSE (19)
Scroll Lock键: VK_SCROLL (145)

 

键盘、游戏、ASCII码引出的一系列问题