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

初学者就爱开发点小游戏,比如贪吃蛇、俄罗斯方块等,开发这种小游戏就必须有按键控制,一般情况下我们是直接用getch()函数接收按键,然后转换成对应的ASCII码,再通过与ASCII码比较判断用户到底是按了什么键,然后根据按键去执行相应的操作,比如移动、旋转。

但是最近实践我发现这其实没那么简单,举个例子:比如贪吃蛇,当用户按下“向上的方向键”时,要控制蛇往上走,为了说明问题,简化一点,如果按了向上的方向键则输出“up”,其他方向键类似。一般我们会去查ASCII码表(下面有),
键盘、游戏、ASCII码引出的一系列问题

 

 如图,向上的方向键是38,然后我们就会写出这么一个小程序:

 

键盘、游戏、ASCII码引出的一系列问题
#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");    
    }
}
键盘、游戏、ASCII码引出的一系列问题

 

 感兴趣的朋友可以试试编译运行一下,你就会发现问题:如果按“ESC”键,则输出“ESC”,但是无论怎么按向上的方向键,始终不输出“up”!这是问什么呢?我也不知道。当然通过查ASCII码表,我们会发现,其实ASCII38对应的是'&',如果输入'&',就会输出‘up’!晕.........哪位大神知道为什么?回复一下,小弟不胜感激。

但问题还是要解决的,键盘上的向上方向键到底怎么接收呢?后来查了很多资料,看了很多实例,我发现,如果将38改为72就能输出‘up’!太神奇了,我们查ASCII码72对应的字符,就会发现那其实是‘H’,也就是说,如果我们输入‘H’,也能输出‘up’,事实确实如此!太奇怪了!键盘上的‘H’和向上方向键终归是不一样吧,一样的话不久麻烦了吗,平常打字的时候按向上方向键也没见输出‘H’,哈,开个玩笑。这个问题看着小,如果仅仅在贪吃蛇这种小游戏里还没什么,用户一般不会想到去按‘H’的,但是如果在大型软件或大型游戏中呢?说不定这个小bug会让整个系统崩溃!说不定黑客通过这个bug就入侵了!

  一个问题刚解决,又一个问题来了,那么我们到底怎样才能避免上面的问题呢?冥思苦想了良久,坐立不安,心神恍惚,茶饭不思,精神萎靡,头晕脑胀..........终于,在今天,突发灵感,想到方案啦!哈哈,下面让我慢慢道来:

  我是这样想的,既然查ASCII码表那么麻烦,查出来还不能用,那么为什么不自己开发一个小程序呢,用户按一个键,然后输出对应的ASCII码,代码很简单,学过C的都会写,我把代码贴出来:

键盘、游戏、ASCII码引出的一系列问题
#include<stdio.h>
#include<conio.h>
int main()
{
    char c;
    while(1)
    {
        c=getch();
        printf("%d %x %c\n",c,c,c);
    }

}  

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

代码就是这么个意思:接收一个键盘按键,然后输出对应的十进制ASCII码,然后输出对应的16进制的ASCII码,最后输出按键对应的字符(如果能显示就会在屏幕上显示)。运行一下,你就会发现问题,一个惊天动地的问题,一个难以置信的问题,当按下向上的方向键后,竟然出现这个(檫亮眼,看截图)

键盘、游戏、ASCII码引出的一系列问题 
怎么回事?看清楚了吗?再擦擦眼,仔细看,没错,就是这样,下面那一行还好理解,就是72嘛,刚才我们已经做过实验了,但是,上面一行怎么回事?我们不是就按了一个键吗,怎么会显示两行?再看源代码,不对啊,应该只输出一行才对,我们预期的应该是只输出下面以后那个的,上面一行到底是什么?输出的-32又对应着什么?为什么会有上面一行?小弟我是真晕了,还是请教各位大仙大神大牛,Orz.........

  我是这样想的,也不知到对不对,或许,当你按下向上的方向键后,实际按的是两个键,啊!?不懂,我也不懂,只是猜测,然后第一个键就是上面显示的-32,第二个键才是真正得到的ASCII码。我也不知道对不对,反正如果按我的想法的话,那个相同按键的问题就能解决了,看代码:

键盘、游戏、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");    
    }

} 

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

这样的话,只有在按下向上的方向键后才输出‘up’输入‘H’就不会输出‘up’,当然,在开发中,我们就可以这样做了,最起码能保证不会出问题,但是到底为什么是这样,我也不明白,还请高人指点。

 

 

 

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

 

 

 

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

 

ASCII值 控制字符 ASCII值 控制字符 ASCII值 控制字符 ASCII值 控制字符
0 NUT 32 (space) 64 @ 96
1 SOH 33 65 A 97 a
2 STX 34 66 B 98 b
3 ETX 35 # 67 C 99 c
4 EOT 36 $ 68 D 100 d
5 ENQ 37 % 69 E 101 e
6 ACK 38 & 70 F 102 f
7 BEL 39 , 71 G 103 g
8 BS 40 ( 72 H 104 h
9 HT 41 ) 73 I 105 i
10 LF 42 * 74 J 106 j
11 VT 43 + 75 K 107 k
12 FF 44 , 76 L 108 l
13 CR 45 - 77 M 109 m
14 SO 46 . 78 N 110 n
15 SI 47 / 79 O 111 o
16 DLE 48 0 80 P 112 p
17 DCI 49 1 81 Q 113 q
18 DC2 50 2 82 R 114 r
19 DC3 51 3 83 X 115 s
20 DC4 52 4 84 T 116 t
21 NAK 53 5 85 U 117 u
22 SYN 54 6 86 V 118 v
23 TB 55 7 87 W 119 w
24 CAN 56 8 88 X 120 x
25 EM 57 9 89 Y 121 y
26 SUB 58 : 90 Z 122 z
27 ESC 59 ; 91 [ 123 {
28 FS 60 < 92 \ 124 |
29 GS 61 = 93 ] 125 }
30 RS 62 > 94 ^ 126 ~
31 US 63 ? 95 127 DEL

 
NUL VT 垂直制表 SYN 空转同步
SOH  标题开始 FF   走纸控制 ETB  信息组传送结束
STX  正文开始 CR   回车 CAN  作废
ETX  正文结束 SO   移位输出 EM   纸尽
EOY  传输结束 SI    移位输入 SUB  换置
ENQ  询问字符 DLE  空格 ESC  换码
ACK  承认 DC1  设备控制1 FS   文字分隔符
BEL  报警 DC2  设备控制2 GS   组分隔符
BS   退一格 DC3  设备控制3 RS   记录分隔符
HT   横向列表 DC4  设备控制4 US   单元分隔符
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)

 

 


博主ma6174对本博客文章(除转载的)享有版权,未经许可不得用于商业用途。转载请注明出处http://www.cnblogs.com/ma6174/

对文章有啥看法或建议,可以评论或发电子邮件到ma6174@163.com


本文转自ma6174博客园博客,原文链接:http://www.cnblogs.com/ma6174/archive/2011/12/18/2291759.html,如需转载请自行联系原作者
上一篇:阿里雷卷:Reactive 基金会的成立将对开发方式带来哪些影响?


下一篇:自己写的一个delphi正整数快速排序