ncurses clear() 导致闪烁

ncurses clear() causes flickering

我正在将 ncurses 用于我正在制作的打字游戏。字母从屏幕上掉下来,您必须在它们到达底部之前输入它们。它工作得很好,省去了一个问题。清除 window(使用 clear())会使输出闪烁。我将 clear() 放在循环的最开始,将 wrefresh() 放在最后。难道它不应该等待'til wrefresh 来显示任何东西,从而不闪烁吗?

#include <iostream>
#include <string>
#include <cstdlib>
#include <ctime>
#include <curses.h>
#include <fstream>

using namespace std;

int main(){

  initscr();
  cbreak();
  noecho();
  keypad(stdscr, TRUE);
  nodelay(stdscr, TRUE);

  srand(time(NULL));

  //input character integer (ASCII)
  int ch = 1;
  //int to store the last time the character positions were updated
  int lastupdate = time(NULL);

  //x,y,char arrays for falling characters and initialization
  int chars[10], x[10], y[10];
  for(int i = 0; i < 10; i++){
    chars[i] = rand()%25 + 97;
    x[i] = rand()%30;
    y[i] = 0;
    //y[i] = -(rand()%4);
  }

  while (true){
    clear();
    ch = wgetch(stdscr);

    for (int i = 0; i < 10; i++){
      mvwdelch(stdscr,y[i]-1,x[i]);//delete char's prev. position
      mvwaddch(stdscr, y[i], x[i], chars[i]);//add char's current position
      if (ch == chars[i]){
        mvwdelch(stdscr, y[i], x[i]);
        chars[i] = rand()%25 + 97;
        x[i] = rand()%30;
        y[i] = 0;
      }
    }

    if(time(0) >= (lastupdate + 1)){
      for (int i = 0; i < 10; i++){
        y[i]++;
      }
      lastupdate = time(NULL);
    }

    wmove(stdscr, 20, 0);
    printw("your score is NULL. press ESC to exit");

    scrollok(stdscr, TRUE);
    wrefresh(stdscr);
  }
  endwin();
  return 0;
}

编辑:添加代码

edit2: 删除了一些不相关的调试代码

紧接在 clear() 之后的 wgetch() 执行隐含的 wrefresh()。来自 wgetch() 手册页:

If the window is not a pad, and it has been moved or modified
since the last call to wrefresh, wrefresh will be called before
another character is read.

clear 手册页是起点:

The clear and wclear routines are like erase and werase, but they also call clearok, so that the screen is cleared completely on the next call to wrefresh for that window and repainted from scratch.

wgetch 调用执行 wrefresh,这会导致重新绘制:

If the window is not a pad, and it has been moved or modified since the last call to wrefresh, wrefresh will be called before another character is read.

wrefresh的描述没有那么简洁,但是"repainting from scratch"会导致闪烁,因为屏幕有一段时间是空的,然后是非空的。由于这个电话,那些迅速交替:

nodelay(stdscr, TRUE);

我建议只使用 erase() 而不是 clear() clear 也会自动调用 clearok()。