Странное поведение вывода при использовании системы ("/ bin / stty raw") - PullRequest
0 голосов
/ 02 января 2019

В моей программе отображается поле точек 5х20.Игрок с символом «#» также находится на поле.Вы можете перемещать игрока с помощью кнопок w, a, s и d.Если я использую буферизованный ввод, все в порядке.Но пользователь не хочет нажимать ввод каждый раз.Поэтому я использовал команду

system("/bin/stty raw")

Проблема сейчас в том, что поведение вывода очень странное.Строки поля теперь не отображаются должным образом.Я потратил много времени, пытаясь найти ошибку самостоятельно.Также у Google, похоже, нет подходящего объяснения этому поведению.

Можете ли вы сказать мне, почему программа ведет себя так странно, и как это исправить?

#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);
    }
}

1 Ответ

0 голосов
/ 02 января 2019

Терминалы были очень сложными устройствами (и современные терминальные эмуляторы пытаются имитировать их, что-то вроде VT100 ; конечно, эти эмуляторы операционная система специфическая).Прочитайте страницу TTY с демистификацией и termios (3) .Знайте также, что коды выхода ANSI .

И stty raw не делает то, о чем вы мечтаете (это связано с дисциплиной line ).Смотрите также stty (1) и pty (7) .

Если вы хотите написать текстовое ориентированное приложение терминала, используйте некоторую библиотеку, такую ​​как ncurses.Так что выбросьте свой код , потратьте несколько дней на чтение документации и снова напишите свой код с нуля.

Возможно, вы могли бы рассмотреть возможность сделать вместо своей игры какое-то графическое приложение, например, с помощью некоторого набора инструментовтакие как GTK или libSDL .

PS.Вы не упоминаете об этом, но я полагаю, вы используете какую-то систему Linux.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...