Ncurses таинственным образом использует весь мой процессор без всякой причины

#c #ncurses

Вопрос:

Я пытаюсь написать такую программу, как nethack, с помощью ncurses. Программа работает отлично, рисует мне коробку и все идеально, не съедая большую часть моего процессора. После того, как я добавил while(true) цикл, он не рисует мою коробку, и он съедает 100% моего процессора, когда я перемещаю своего «персонажа».

 #include <iostream>
#include <curses.h>
int main(){
    std::pair<int,int> csr_pos{1,1};
    initscr();
    cbreak();
    noecho();
    keypad(stdscr, TRUE);
    nodelay(stdscr, TRUE);
    curs_set(0);
    WINDOW *win = newwin(50,80,0,0);
    if(has_colors()){
        start_color();
        init_pair(1,COLOR_CYAN,COLOR_BLACK);
        init_pair(2,COLOR_RED,COLOR_BLACK);
        init_pair(3,COLOR_WHITE,COLOR_RED);
        init_pair(4,COLOR_YELLOW,COLOR_BLACK);
    }
    /*
    wattron(win,COLOR_PAIR(1));
    mvwaddch(win,25,41,'@');
    wattroff(win,COLOR_PAIR(1));
    */
    for(int i = 0; i<80; i  ){
        mvwaddch(win,0,i,'#');
        mvwaddch(win,49,i,'#');
        wrefresh(win);
    }
    for(int i = 1; i<49; i  ){
        mvwaddch(win,i,0,'#');
        mvwaddch(win,i,79,'#');
        wrefresh(win);
    }
    while(true){
        mvwaddch(win,csr_pos.first,csr_pos.second,'@');
        int ch = getch();
        if(ch==KEY_LEFT){
            mvwaddch(win,csr_pos.first,csr_pos.second,' ');
            csr_pos.second--;
            mvwaddch(win,csr_pos.first,csr_pos.second,'@');
        }
        if(ch==KEY_RIGHT){
            mvwaddch(win,csr_pos.first,csr_pos.second,' ');
            csr_pos.second  ;
            mvwaddch(win,csr_pos.first,csr_pos.second,'@');
        }
        wrefresh(win);
    }
}
 

Ответ №1:

 nodelay(stdscr, TRUE);
 

Давайте посмотрим, что говорится об этом на странице руководства по проклятиям:

  nodelay
   The nodelay option causes getch to be a non-blocking call.  If no input
   is  ready,  getch  returns ERR.  If disabled (bf is FALSE), getch waits
   until a key is pressed.
 

Если это не было ясно: в режиме getch nodelay не ждет нажатия клавиши. Он немедленно возвращается.

Давайте посмотрим, что будет дальше делать показанный код:

 while(true){
    mvwaddch(win,csr_pos.first,csr_pos.second,'@');
    int ch = getch();

// ...
 

Таким образом, теперь это становится бесконечным циклом, связанным с процессором на 100%. getch всегда возвращается немедленно. Если ни одна из двух клавиш, которые проверяет следующий код, не нажата, этот while цикл немедленно запускается снова, и вы возвращаетесь к тому, с чего начали, снова и снова.

И именно по этой причине показанный код «съедает 100%» процессора.

nodelay режим предназначен для использования с дополнительной логикой, которая poll() действует до тех пор, select() пока не будет нажата клавиша, и getch вызывается только тогда, когда есть фактический ключ для чтения.

Комментарии:

1. Итак, я прокомментировал это nodelay() , это решило мою проблему с процессором, но я все еще не понимаю, почему моя коробка не рисуется.

2. Это был бы еще один, не связанный с этим вопрос, который лучше рассмотреть в новом вопросе..

3. Ваше поле не нарисовано, потому что неявное обновление stdscr by getch() перезаписывается win . Измените его на wgetch(win) .