5

我正在尝试在 C 中使用 ncurses 实现游戏。我必须显示当前时间(时间必须每秒更新),而我的 while 循环看起来像这样

while(1)
{
    clk = time(NULL);
    cur_time = localtime(&clk);
    mvprintw(0,1,"%d %d %d",cur_time->tm_hour,cur_time->tm_min,cur_time->tm_sec);
    int key = getch()
    //other stuff
}

我的问题是只有当我按下一个键时时间才会刷新。这是一种无需按键即可刷新时间(并同时实现此功能)的方法吗?

4

3 回答 3

5

您可以使用几个功能:

  1. 节点层
  2. 暂停

int nodelay(WINDOW *win, bool bf);

设置 bf true 使 getch() 非阻塞

无效超时(int延迟);

延迟以毫秒为单位,因此如果将其设置为 1000,则 getch 将在一秒钟后超时。

在这两种情况下,如果没有输入,getch 将返回 ERR。

于 2013-01-02T22:01:14.370 回答
1

这里的解决方案是使用非阻塞 IO 或使用线程。然而,使用线程会给你带来一个新问题,那就是在任何给定时间只有一个线程可以使用curses,所以你需要使用锁或类似的东西来防止其他线程在那个时候使用curses时间。当然,一种解决方案是让一个线程负责更新屏幕内容,而其他线程只需向该线程发送“我想在 X,Y 屏幕上显示”的消息

于 2012-12-29T15:32:10.870 回答
0

这是一个非常丑陋的 hack,它只支持一个 stdio 函数:fgetc()。其他可以添加,顺便说一句。它通过设置计时器来工作,如果在读取单个字符之前警报响起,则返回 -2 值(请记住:-1 表示 EOF)

不适用于任何其他 curses 的 wgetXXX() 函数,这些函数可能会直接调用 fgetc() (等)。YMMV。

但是,在一般情况下,我认为您应该调查 wgetch_events()。

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <signal.h>
#include <setjmp.h>

sigjmp_buf the_jump;

int my_fgetc(FILE *fp, unsigned timeout);
void sig_handler(int signr);

void sig_handler(int signr) {
        switch (signr) {
        case SIGALRM:
              siglongjmp(the_jump,1);
              break;
        default:
              break;
        }
}

int my_fgetc(FILE *fp, unsigned timeout)
{
alarm( timeout);

switch (sigsetjmp(the_jump, -1)) {
case 0:
        alarm(0);
        return fgetc (fp);
case 1:
        return -2;
default:
        return -3;
        }
}

int main()
{
int rc;
signal(SIGALRM, sig_handler);

rc = setvbuf(stdin, NULL, _IONBF, 0);
printf("setvbuf(_IONBF) = %d\n", rc);
while (1) {
        rc = my_fgetc(stdin, 1);
        printf("my_fgetc(NULL) = %d\n", rc);
        }

return 0;
}
于 2012-12-29T18:59:57.293 回答