简体   繁体   中英

Strange output behaviour when using system("/bin/stty raw")

In my program, a 5x20 field of points is displayed. A player which has the symbol "#" is also on the field. You can move the player around with w, a, s and d. If I use buffered input everything is fine. But the user dont want hit enter every time. So I used the command

system("/bin/stty raw")

The problem now is that the output behavior is very strange. The lines of the field are not displayed properly now. I wasted much time by trying to find the error by myself. Also Google seems not to have an appropriate explanation to this behavior.

Can you tell me why the program behaves that strange, and how to fix that?

#include <stdio.h>

#define FIELD_VERTIKAL 5
#define FIELD_HORIZONTAL 20
#define PLAYER_SYMBOL '#'

void print_field(char field[FIELD_VERTIKAL][FIELD_HORIZONTAL])
{
    // reset display
    for (int i = 0; i < 20; i++)
        putchar('\n');

    // display field
    for (int i = 0; i < FIELD_VERTIKAL; i++)
    {
        for (int j = 0; j < FIELD_HORIZONTAL; j++)
            putchar(field[i][j]);
        putchar('\n');  
    }
}

void draw_field(char field[FIELD_VERTIKAL][FIELD_HORIZONTAL], 
  int pos_vertikal, int pos_horizontal)
{
    for (int i = 0; i < FIELD_VERTIKAL; i++)
        for (int j = 0; j < FIELD_HORIZONTAL; j++)
            field[i][j] = '.';
    field[pos_vertikal][pos_horizontal] = '#';
}

int main() 
{
    // create field and initialize it
    char field[FIELD_VERTIKAL][FIELD_HORIZONTAL];   

    // position of player
    int pos_vertikal = 0;
    int pos_horizontal = 0;

    // initialize field
    draw_field(field, pos_vertikal, pos_horizontal);

    system("/bin/stty raw");
    print_field(field);
    char input;
    while ((input = getchar()) != EOF) 
    {
        // move player
        if (input == 'w')
        {
            pos_vertikal--;
        }
        else if (input == 'a')
        {
            pos_horizontal--;
        }
        else if (input == 's')
        {
            pos_vertikal++;
        }
        else if (input == 'd')
        {
            pos_horizontal++;
        }

        // place player and display field
        draw_field(field, pos_vertikal, pos_horizontal);
        print_field(field);
    }
}

Terminals were very complex devices (and today's terminal emulators are trying to mimic them, something like the VT100 ; of course these emulators are operating-system specific). Read the TTY demystified page and termios(3) . Be also aware of ANSI escape codes .

And stty raw is not doing what you dream of (it is related to the line discipline ). See also stty(1) and pty(7) .

If you want to write a terminal text oriented application, use some library such as ncurses . So throw your code away , spend a few days reading documentation, and write your code again from scratch.

Maybe you could consider making instead your game some graphical application, eg by using some toolkit such as GTK or libSDL .

PS. You don't mention it, but I guess you are using some Linux system.

You may use putchar('\\r'); putchar('\\n') putchar('\\r'); putchar('\\n') I know someone will say that's windows' new line char but it just because unix terminals replace '\\r' or '\\n' to '\\r\\n' when it's cooked mode

\\r => return cursor to this line's head
\\n => move the cursor to next line needn't be the head

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