简体   繁体   English

Getch()与Linux C ++中的显示功能不兼容

[英]Getch() incompatible with display function in linux c++

I am making a 2D dungeon crawler type game for a class. 我正在为一个班级制作2D地牢爬虫类游戏。 I am trying to receive user input without requiring the enter key to be pressed. 我正在尝试接收用户输入,而不需要按下Enter键。 Specifically, I want to use wasd as directional keys to move around a 2D array. 具体来说,我想使用wasd作为方向键在2D数组中移动。

I've tried using the ncurses library but it currently messes with my display function (I believe when using endl). 我试过使用ncurses库,但当前它与我的显示功能混淆了(我相信在使用endl时)。

Normally my board displayed will look like: 通常我显示的板看起来像:
xxx xxx
xxx xxx
xxx xxx

But when using getch() from the ncurses library my board looks like: 但是,当使用ncurses库中的getch()时,我的面板看起来像:
xxx xxx
......xxx ...... xxx
............xxx ............ xxx

Is there a way to use getch() from the curses library without it interfering with my print function? 有没有办法使用curses库中的getch()而不干扰我的打印功能?

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. ncurses希望它可以完全控制显示终端。 You are using ncurses for input, but still spewing output to std::cout . 您正在使用ncurses进行输入,但仍将输出喷出到std::cout

This is not going to work. 这是行不通的。 At least not without major hacking. 至少并非没有重大黑客攻击。

ncurses is an all or nothing deal. ncurses是一项全有或全无的交易。 Either you use ncurses for input, and for terminal output, or use something else entirely. 您可以使用ncurses进行输入和终端输出,也可以完全使用其他方法。

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). 只需将文件描述符0置于非阻塞模式,并使用read()从fd 0进行read() (因为从非阻塞文件描述符读取std::cin会需要太多保姆)。

See the fcntl(2) manual page, and search for O_NONBLOCK . 请参见fcntl(2)手册页,并搜索O_NONBLOCK Then: 然后:

  1. Put the terminal in non-canonical mode by turning off the ICANON flag. 通过关闭ICANON标志将终端置于非规范模式。 See the termios(3) manual page. 请参见termios(3)手册页。 This is what ncurses does, to get access to the raw keystrokes. ncurses就是这样做的,以访问原始的击键。

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 . curses(默认情况下)写入标准输出,例如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 . 但是使用二合一程序需要您切换I / O模式,并要记住curses和cout的输出缓冲是不同的

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). 当curses初始化时,它将更改终端的输入和输出模式,以允许读取(输入)单个字符,并允许其使用单个回车和换行字符(输出)。 cout assumes that a newline (line-feed) causes a carriage-return. cout假定换行符(换行)引起回车。 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 . 当curses初始化时,它将保存终端的输入和输出模式的副本,您可以使用curses调用reset_shell_modereset_prog_mode临时切换到该模式或从该模式切换到该reset_prog_mode Use these rather than ad hoc termios calls to avoid confusing curses. 使用这些而不是临时的termios调用来避免混淆诅咒。

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. 如果您使用的东西写在标准输出cout ,切换回之前的诅咒流的冲刷。 When switching from curses to cout , do a refresh in curses to ensure that the screen is in a known state. 从curses切换到cout 刷新 curses以确保屏幕处于已知状态。

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. 尽管您可以使用newterm为curses指定实际的输出流(并使它们不同于coutcin ),但仍然必须使用curses接口来可靠地使用库。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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