【问题标题】:How do I use kbhit in C?如何在 C 中使用 kbhit?
【发布时间】:2018-04-14 16:46:34
【问题描述】:
#include<stdio.h>
#include<Windows.h>
#include<conio.h>
#define Ukey 87
#define ukey 119
#define Dkey 115
#define dkey 83
#define Lkey 97
#define lkey 65
#define Rkey 100
#define rkey 68

int main(){
    int x=0;
    int y=0;
    int prev=rkey;
    while(true){
        Sleep(50);
        system("cls");
        printf("x : %d\ny : %d",x,y);

        if(!kbhit()){
            if(prev==ukey){
                y--;
            }else if(prev==dkey){
                y++;
            }else if(prev==lkey){
                x--;
            }else if(prev==rkey){
                x++;
            }
        }else if(getch()==ukey||getch()==Ukey){
            y--;
            prev=ukey;
        }else if(getch()==dkey||getch()==Dkey){
            y++;
            prev=dkey;
        }else if(getch()==lkey||getch()==Lkey){
            x--;
            prev=lkey;
        }else if(getch()==rkey||getch()==Rkey){
            x++;
            prev=rkey;
        }
    }
}

所以基本上我的程序会检测键盘键(我定义为 Ukey、Dkey、Lkey 和 Rkey 的 w、a、s 或 d)。该程序旨在通过按键检测方向,更改 x 和 y 值并保持它直到按下另一个键。

我的问题是,当程序运行并初始化默认方向(右)时,当我按下另一个键时,while 函数就会停止。如果我按下键几秒钟,它只会不断改变 x 和 y 值。

我的代码有什么问题?这是我第一次使用 kbhit,所以您的回答对我来说将是一个巨大的帮助。谢谢。

【问题讨论】:

  • while 不是函数,是控制循环。 Sleep 中的 50 是多少?秒,毫秒?当程序仍在执行Sleep时,您可能正在按下该键。
  • 只调用一次 getch()。
  • 您不要在标准 C11 或 C99 程序中使用 kbhit,因为它不符合标准。您可以选择专门为一个操作系统及其 API 编写代码(在您的情况下,可能是 winapi),在这种情况下,您需要花费数周时间研究该 API。您还可以选择使用一些现有的(可能是跨平台的)库(可能查看ncursesGTK....)
  • 光标控制和功能键通过getch返回两个键码。我建议你编写一个像while(1) { while(!kbhit()) ; printf("%d\n", getch()); } 这样的小测试程序来检查会发生什么。

标签: c conio kbhit


【解决方案1】:

我认为问题出在else if(getch()==ukey||getch()==Ukey) 结构中,它会多次调用getch。如果kbhit 返回true,那么对getch 的第一次调用将是非阻塞的。但是,在按下新键之前,每个额外的调用都会阻塞。

解决方案:重组您的程序,以便只调用一次getch

while (true) {

  if (kbhit()) {
    // A key was pressed. Find out which one.
    prev = getch()
  }

  switch (prev) {
    case ukey: y--; break;
    case UKey: ...
    ...
  }

}

此外,专门检测箭头键的两个字符响应可能是有利的。我不记得它是如何工作的,但逻辑是这样的:

if (kbhit()) {
 c = getch()
 if (c indicates a control character) {
   c = getch();
   switch c: {
     case up arrow: command = up;
     ...
   }
 }
}

您可能希望创建一个枚举来存储当前的“模式”或最后一个命令。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-03-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-02
    • 2012-11-16
    • 1970-01-01
    相关资源
    最近更新 更多