сделай так чтобы линия не мерцала 


#include <iostream>
#include <vector>
#include <thread>
#include <chrono>
#include <random>
#include <conio.h> // Для работы с _kbhit() и _getch()
#include <windows.h> // Для получения размеров консоли и скрытия курсора

class Symbol {
public:
    Symbol(char character = ' ', int color = 10) // Зеленый цвет по умолчанию
            : character(character), color(color) {}

    char getCharacter() const { return character; }
    void setCharacter(char character) { this->character = character; }
    int getColor() const { return color; } // Получаем цвет символа
    void setColor(int color) { this->color = color; } // Устанавливаем цвет символа

private:
    char character; // Символ, который будет отображаться
    int color;      // Цвет символа
};

class Line {
public:
    Line(int length, bool epilepsyMode) : length(length), epilepsyMode(epilepsyMode) {
        // Устанавливаем единый случайный цвет для всей линии в режиме эпилепсии
        lineColor = epilepsyMode ? getRandomColor() : 10; // Зеленый цвет для обычного режима

        // Генерируем случайные символы для линии
        for (int i = 0; i < length; ++i) {
            char randomChar = getRandomCharacter();
            int color = (epilepsyMode ? lineColor : 10); // Используем единый цвет для режима эпилепсии
            symbols.push_back(Symbol(randomChar, color));
        }
        // Устанавливаем цвет последнего символа (справа) в белый
        symbols[length - 1].setColor(15);
    }

    void move() {
        // Сдвигаем все символы влево
        for (int i = 0; i < length - 1; ++i) {
            symbols[i] = symbols[i + 1]; // Перемещаем символы влево
        }
        // Генерируем новый случайный символ в конце
        generateNewSymbol();
    }

    char getCharacter(int index) const {
        if (index >= 0 && index < symbols.size()) {
            return symbols[index].getCharacter();
        }
        return ' ';
    }

    int getColor(int index) const {
        if (index >= 0 && index < symbols.size()) {
            return symbols[index].getColor(); // Получаем цвет символа
        }
        return 7; // Цвет по умолчанию (белый)
    }

    void draw(int position, int consoleWidth, int startPosition) const {
        // Рисуем пустые строки перед линией для вертикального смещения
        for (int j = 0; j < startPosition; ++j) {
            std::cout << std::endl;
        }

        // Если позиция больше нуля, добавляем пробелы, чтобы сдвинуть линию вправо
        if (position >= 0) {
            std::cout << std::string(position, ' '); // Добавляем пробелы для смещения линии вправо
        }

        // Рисуем видимую часть линии
        int startIndex = std::max(0, -position); // Начальный индекс для рисования, если линия еще выползает
        int visibleLength = std::min(length - startIndex, consoleWidth - position); // Длина видимой части
        for (int i = startIndex; i < startIndex + visibleLength; ++i) {
            setColor(getColor(i)); // Устанавливаем цвет символа перед выводом
            std::cout << getCharacter(i);
        }
        std::cout << std::endl;
    }

private:
    int length; // Длина линии
    std::vector<Symbol> symbols; // Вектор символов, составляющих линию
    bool epilepsyMode; // Режим эпилепсии
    int lineColor; // Единый цвет для всей линии в режиме эпилепсии

    void generateNewSymbol() {
        char newChar = getRandomCharacter();
        int color = epilepsyMode ? lineColor : 10; // Используем единый цвет в режиме эпилепсии
        symbols[length - 1] = Symbol(newChar, 15); // Последний символ белый
        symbols[length - 2].setColor(color); // Задаем единый цвет предпоследнему символу
    }

    static char getRandomCharacter() {
        // Массив символов, включая буквы и специальные символы
        const char characters[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*()_+[]{}|;':\",.<>?`~";
        return characters[rand() % (sizeof(characters) - 1)]; // Генерируем случайный символ
    }

    static int getRandomColor() {
        return 1 + rand() % 15; // Возвращаем случайный цвет (1 - 15)
    }

    // Функция для установки цвета текста в консоли
    static void setColor(int color) {
        SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), color);
    }
};

class AppManager {
public:
    AppManager() : speed(1), length(10), epilepsyMode(false), running(true) {
        srand(static_cast<unsigned int>(time(nullptr))); // Инициализация генератора случайных чисел
        getConsoleSize(); // Получаем размеры консоли
    }

    // Метод для запуска приложения
    void start() {
        configureSettings(); // Запрос настроек у пользователя

        // Скрываем курсор перед началом симуляции
        HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE); // Получаем дескриптор консоли
        CONSOLE_CURSOR_INFO cursorInfo; // Структура для хранения информации о курсоре
        GetConsoleCursorInfo(hConsole, &cursorInfo); // Получаем информацию о курсоре
        cursorInfo.bVisible = FALSE; // Скрыть курсор
        SetConsoleCursorInfo(hConsole, &cursorInfo); // Устанавливаем обновленные параметры курсора

        std::cout << "Matrix Simulation is starting..." << std::endl; // Сообщение о начале симуляции

        while (running) { // Пока программа работает
            int startPosition = rand() % (consoleHeight - 1); // Случайная вертикальная позиция

            Line line(length, epilepsyMode); // Создаем линию заданной длины с учетом режима эпилепсии
            int position = -length; // Начальная горизонтальная позиция линии (начинает за левым краем)

            // Пока линия полностью не исчезнет за правым краем экрана
            while (position < consoleWidth) {
                system("cls"); // Очищаем консоль (специфично для Windows)

                line.draw(position, consoleWidth, startPosition); // Рисуем линию

                std::this_thread::sleep_for(std::chrono::milliseconds(1000 / speed)); // Управляем скоростью
                line.move(); // Сдвигаем символы линии

                // Увеличиваем позицию, чтобы линия двигалась вправо
                ++position;

                // Проверяем, нажата ли клавиша 'q' для выхода
                if (_kbhit() && _getch() == 'q') {
                    running = false; // Завершаем работу программы
                    break; // Выходим из цикла
                }
            }

            // Если режим эпилепсии активен, добавляем задержку для эффекта
            if (epilepsyMode) {
                std::this_thread::sleep_for(std::chrono::milliseconds(500)); // Добавляем задержку для эффекта
            }
        }
    }

private:
    int speed; // Скорость падения линий
    int length; // Длина линий
    bool epilepsyMode; // Режим эпилепсии
    bool running; // Флаг работы программы
    int consoleWidth; // Ширина консоли
    int consoleHeight; // Высота консоли

    void configureSettings() {
        std::cout << "Welcome to the Matrix Simulation!" << std::endl; // Приветственное сообщение

        // Ввод скорости
        while (true) {
            std::cout << "Enter speed (1 - 30): "; // Запрос скорости
            if (std::cin >> speed && speed >= 1 && speed <= 30) break; // Чтение значения скорости и проверка
            std::cin.clear(); // Сброс флага ошибки
            std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); // Очистка буфера ввода
            std::cout << "Invalid input. Please enter a number between 1 and 30." << std::endl;
        }

        // Ввод длины
        while (true) {
            std::cout << "Enter line length (1 - 30): "; // Запрос длины
            if (std::cin >> length && length >= 1 && length <= 30) break; // Чтение значения длины и проверка
            std::cin.clear(); // Сброс флага ошибки
            std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); // Очистка буфера ввода
            std::cout << "Invalid input. Please enter a number between 1 and 30." << std::endl;
        }

        // Ввод режима эпилепсии
        char epilepsyInput;
        while (true) {
            std::cout << "Epilepsy mode (Y/N)? "; // Запрос режима эпилепсии
            if (std::cin >> epilepsyInput && (epilepsyInput == 'Y' || epilepsyInput == 'y' || epilepsyInput == 'N' || epilepsyInput == 'n')) break;
            std::cin.clear(); // Сброс флага ошибки
            std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); // Очистка буфера ввода
            std::cout << "Invalid input. Please enter 'Y' or 'N'." << std::endl;
        }

        // Устанавливаем режим эпилепсии на основе ввода пользователя
        epilepsyMode = (epilepsyInput == 'Y' || epilepsyInput == 'y');
    }

    void getConsoleSize() {
        // Получаем размеры окна консоли
        CONSOLE_SCREEN_BUFFER_INFO csbi; // Структура для хранения информации о консоли
        GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi); // Получаем информацию о буфере
        consoleWidth = csbi.srWindow.Right - csbi.srWindow.Left + 1; // Ширина консоли
        consoleHeight = csbi.srWindow.Bottom - csbi.srWindow.Top + 1; // Высота консоли
    }
};

// Главная функция
int main() {
    AppManager appManager; // Создаем объект управления
    appManager.start(); // Запускаем симуляцию

    return 0; // Завершаем программу
}