Закраска консоли в цвета фонов C++

Рейтинг: 1Ответов: 1Опубликовано: 25.05.2023

Есть такой код:

#include <iostream>
#include <sstream>
#include <iomanip>
#include <sys/ioctl.h>
#include <termios.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
#include <thread>
#include <chrono>

static int done = 0;

using namespace std;

namespace con {
    
    int comax() {
        struct winsize w;
        ioctl(0, TIOCGWINSZ, &w);
        return(w.ws_col);
    }
    
    int romax() {
        struct winsize w;
        ioctl(0, TIOCGWINSZ, &w);
        return(w.ws_row);
    }
    
    ostream& ED(ostream& s) {
        return s << string("\033[2J");
    }
    
    ostream& EL(ostream& s) {
        return s << string("\033[K");
    }
    
    class estream {
        private:
        string escape;
        public:
        estream(string e) : escape(e) {};
        friend ostream& operator<<(ostream&, estream);
    };
    
    ostream& operator<<(ostream& s, estream e) {
        s << e.escape << flush;
        return s;
    }
    
    estream CUP(int y, int x) {
        ostringstream sout;
        sout << "\033[" << y << ";" << x << "H";
        return estream(sout.str());
    }
    
    estream SGR(int r) {
        ostringstream sout;
        sout << "\033[" << r << "m";
        return estream(sout.str());
    }
    
}

using con::SGR;
using con::CUP;

void interruptor(int signo) {
    done = signo;
    return;
}

int kbin() {
    char buf[512];
    int n=0;
    int flags = fcntl(0, F_GETFL);
    usleep(1);
    fcntl(0, F_SETFL, flags | O_NONBLOCK);
    n = read(0, buf, 512);
    fcntl(0, F_SETFL, flags /* & ~O_NONBLOCK */);
    return(n);
}

int main(int argc, char** argv) {
    int m;
    
    cout << SGR(30+7);
    cout << SGR(40+4);
    cout << SGR(1);
    cout << con::CUP(24, 1);
    
    cout << con::ED << "^C or Enter to exit" << flush;
    
    cout << con::CUP(23, 1);
    cout << con::romax() << "x" << con::comax() << flush;
    
    int i;
    int t;
    int y = 0, x = 1;
    char a;
    int f, b;
    srand(getpid());
    signal(SIGINT, interruptor);
    a = 32; b = 40; f = (30 + 7);
    while(done < 1) {
        if ( y < 22 )
        y++;
        else
        {
            y = 1;
            if ( b < 47 )
            b++;
            else
            b = 40;
        }
        t = rand() % 10;
        for(i = 1; i <= 80; i++)
        {
            cout << SGR(b) << CUP(y, i);
            cout << SGR(f) << a << flush;
            this_thread::sleep_for(chrono::milliseconds(t));
        }
        if(kbin() > 0)
        break;
    }
    cout << CUP(24, 1) << SGR(0) << con::EL;
    system("clear");
    
    return(m);
    
}

он закрашивает терминал во все цвета фона в порядке увеличения их escape-кодов. На данный момент он закрашивает слева-направо и когда докрасит строку переходит на следующую. При закраске последней строки он возвращается на 1-ю и меняет цвет. Можно ли сделать так чтобы закраска происходила не слева-направо и переходила на следующую строку, а вся строка закрашивалась одновременно, и, после небольшой паузы, переходила на следующую строку?

Ответы

▲ 2

Да, можно. Для этого нужно заменить внутренний цикл на следующий код:

for (i = 1; i <= 80; i++) {
    cout << SGR(b) << CUP(y, i);
    cout << SGR(f) << a << flush;
    this_thread::sleep_for(chrono::milliseconds(t));
}
cout << flush; // добавлено
this_thread::sleep_for(chrono::milliseconds(100)); // добавлено