简体   繁体   中英

Getch() incompatible with display function in linux c++

I am making a 2D dungeon crawler type game for a class. I am trying to receive user input without requiring the enter key to be pressed. Specifically, I want to use wasd as directional keys to move around a 2D array.

I've tried using the ncurses library but it currently messes with my display function (I believe when using endl).

Normally my board displayed will look like:
xxx
xxx
xxx

But when using getch() from the ncurses library my board looks like:
xxx
......xxx
............xxx

Is there a way to use getch() from the curses library without it interfering with my print function?

void ParkBoard::print() {
displayMessage();
for (int i = 0; i < getSize(); i++) {
    cout << " ";
    for (int j = 0; j < getSize(); j++) {
        if (j == 0) {
            parkBoard[i][j]->display();
        }
        else {
            cout << " ";
            parkBoard[i][j]->display();
        }
    }
    cout << endl;
}

ncurses expects that it has full control over the display terminal. You are using ncurses for input, but still spewing output to std::cout .

This is not going to work. At least not without major hacking.

ncurses is an all or nothing deal. Either you use ncurses for input, and for terminal output, or use something else entirely.

But there's a much easier solution, since all you're trying to do is "receive user input without requiring the enter key to be pressed":

  1. Just put file descriptor 0 in non-blocking mode, and read from fd 0 using read() (since std::cin will require too much babysitting when it's reading from a non-blocking file descriptor).

See the fcntl(2) manual page, and search for O_NONBLOCK . Then:

  1. Put the terminal in non-canonical mode by turning off the ICANON flag. See the termios(3) manual page. This is what ncurses does, to get access to the raw keystrokes.

You will need to do a little bit of work to restore the terminal to canonical mode, if the program is aborted, in order to get back to the shell in "sane" terminal mode.

short: no

long:

curses writes (by default) to the standard output, like cout . But using the two in one program requires you to switch I/O modes and to keep in mind that the output-buffering for curses and cout are different .

When curses initializes, it changes the terminal's input and output modes to allow single characters to be read (input) and to allow it to use individual carriage-return and line-feed characters (output). cout assumes that a newline (line-feed) causes a carriage-return. That isn't true when you are using curses.

When curses initializes, it saves a copy of the terminal's input and output modes, which you can temporarily switch to/from using the curses calls reset_shell_mode and reset_prog_mode . Use these rather than ad hoc termios calls to avoid confusing curses.

Besides the terminal modes, there is output-buffering to address. If you have written something to the standard output using cout , do a flush of that stream before switching back to curses. When switching from curses to cout , do a refresh in curses to ensure that the screen is in a known state.

While you can use newterm for specifying the actual output streams for curses (and make them different from cout and cin ), you would still have to use the curses interface for reliable use of the library.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM