poniedziałek, 16 lipca 2012

Analogowe literały w C++

Ostatnio w pracy troszkę się nudziło (bywa ;)), co spowodowało, że następujący kod zaczął się kompilować:
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).