for (uint worm = I-------------I; worm >= II; worm -= I-I ) { cout << '*'; } uint monsterHP = I-----------------------I; // 12 HP uint monBossHP = (I-----------------------I) * 10; // 120 HP cout <<( I-------I | ! ! ! I-------I ).area();To nie jest mój pomysł - kiedyś natrafiłem na blogu Paczesiowej ciekawy wpis gdzie znalazłem link opisujący w C++ literały analogowe - czyli zamiast podawać wartości naturalne można było narysować sobie linie, prostokąt albo sześcian w ASCII, co następnie było zamieniane na wartość liczbową.
Niestety - strona przestała działać a w cache znalazłem jedynie podgląd jak to wyglądało... więc nie miałem innego wyjścia jak spróbować zaimplementować to samemu ;)
Na razie odpuściłem sobie implementację literałów 3D - zaimplementowałem tylko linie oraz prostokąty co okazało się zaskakująco proste, przy czym nie nakładałem zbyt wysokich wymagań co do poprawności i obsługi sytuacji brzegowych :)
Cała sztuczka polega na odpowiednim przeładowaniu operatorów. Zauważ, że tak naprawdę linię można ograniczyć dwoma obiektami (I), których wartość ulega zmianie poprzez użycie operatora "--" oraz połączenie ich przez binarny operator "-".
Analogicznie jest dla 2D - to po prostu 2 linie z tym, że jedna jest modyfikowana przez "!" (zwiększa wysokość) a potem linia + linia z wysokością są scalane przez operator binarny "|".
Myślę, że rozjaśni się wszystko jak pokażę kod (testowany na VC2k5 i ideone). Kod jest brzydki i prototypowy - używać na własną odpowiedzialność a najlepiej zamknąć oczy czytając ;)
typedef unsigned int uint; const uint II = 0; /// Literal analogowy 1D oraz 2D class _ALiteral { public: _ALiteral() : width(1), height(0) {} uint len() const { return width; } uint len2() const { return height; } float ratio() const { static_cast<float>(width) / height; } uint area() const { return width * height; } // niejawna konwersja do uint - czasem moze troche popsuc :( // ale umozliwia pisanie uint t = I---I; zamiast (I---I).len() operator uint() { return len(); } _ALiteral operator-(_ALiteral right) const { _ALiteral t; t.width = width + (right.width-1); t.height = right.height + height; return t; } _ALiteral& operator--() { width += 1; return *this; } _ALiteral operator | (_ALiteral right) { height = 1 + right.height; // bo | zastepuje jeden znak ! height >>= 1; // bo ! jest aplikowane 2 razy, mozna dodac sprawdzanie parzystosci return *this; } _ALiteral& operator!() { height += 1; return *this; } private: uint width, height; }; // ukrycie konstrukcji obiektu _ALiteral #define I _ALiteral()
Brak komentarzy:
Prześlij komentarz