Zadanie zaliczeniowe z Programowania Wizualnego dla MSUI 
Rok 2OO4/2OO5 
Autorzy: Paulina Domagalska, Weronika Buczyńska, Janusz Jabłonowski 
Wersja 1.06 
1 Wstęp 
Za siedmioma górami, za siedmioma lasami starożytne królestwo nawiedził wielki i potężny Kamienny Smok. Wiele 
szkód uczynił: podpalał lasy i chłopskie chaty, porywał owce i dzieci (powiadano, że trafiały potem na jego stół). Wielu 
śmiałków próbowało już zgładzić potwora, żadnemu jednak nie udało się dotąd dotrzeć do jego legowiska, gdyż droga doń 
wiodła przez Labirynt. Niezwyczajny był to Labirynt - pełno w nim bezdennych przepaści, dziwnych, wybuchających 
miejsc i magii. Próbowano juz wyburzać mury - ale po pewnym czasie odrastały jak przebiśniegi; zamurowywano 
przepaście, ale po pewnym czasie cegły rozsypywały się w proch. Aż wreszcie przybyła drużyna bohaterskich rycerzy 
pod twoim dowództwem aby zmierzyć się z Niebezpieczeństwem. Dla okolicznych mieszkańców po raz pierwszy zaświecił 
promień nadziei. 
2 Opis 
2.1 Plansza 
Plansza labiryntu jest podzielona na kwadraty - pola labiryntu. Gracz “chodzi” po labiryncie swoimi rycerzami. W 
jednym ruchu gracz może przesunąć jednego z rycerzy na jedno z czterech pól mających wspólną krawędź z polem, 
na którym stoi przesuwany rycerz, pod warunkiem, ze nie jest to pole z murem (patrz opis pól labiryntu), że nie jest 
to pole zajęte przez innego rycerza i że pole mieści się na planszy. (Niektórzy rycerze poruszają się inaczej, patrz ich 
opis.) Numery pól planszy rosną w dół i w prawo. 
Plansza labiryntu jest plikiem o formacie opisanym w punkcie Format pliku z labiryntem. 
2.2 Rycerze 
Każdy uczestnik wyprawy należy do jednej z 4 kategorii: 
• rycerz Nadzwyczajny 
Nie posiada żadnych wyróżniających zdolności, poza wyjątkowym uporem w dążeniu do celu. 
• rycerz Zjadacz 
Posiada specjalną, stalową Sztuczną Szczękę, pozwalającą przegryzać niektóre typy murów. Niestety posiada ona 
ograniczoną liczbę zębów, a zjedzenie jednego muru powoduje utratę jednego z nich. Liczba zębów którą posiada 
Zjadacz na początku gry zależy od planszy - labiryntu; zużyte zęby może sobie wymienić na nowe w specjalnym 
polu - magazynie dentystycznym (patrz opis pól labiryntu). Niestety, w żadnym momencie gry Szczęka nie może 
posiadać więcej zębów, niż na początku planszy. 
• rycerz Budowniczy 
Nie rozstaje się nigdy z workiem pełnym cegieł. Jego specjalnością jest zamurowywanie Bezdennych Przepa- 
ści. Nowe cegły może otrzymać w magazynie budowlanym. Niestety, pojemność jego worka jest ograniczona 
(ograniczenie zależy od planszy i jest wyznaczone przez liczbę cegieł posiadanych po uruchomieniu planszy). 
• rycerz Skoczek 
Potrafi przeskoczyć nad jednym polem labiryntu, niezależnie od tego, jakiego rodzaju jest to pole. Często bywa 
wykorzystywany jako zwiadowca, co niestety czasem kończy się jego niespodziewaną śmiercią (jeśli wpadnie do 
dziury lub na minę - gracz nie zawsze widzi pole na które skacze Skoczek). Zgodnie z ogólnymi zasadami nie 
może skoczyć na pole znajdujące się poza labiryntem, pole z innym rycerzem lub z murem. Skoczek skacze tylko 
w pionie i w poziomie (nie na ukos). Może też chodzić (na normalnych zasadach). 
1

2.3 Pola labiryntu 
• pole zwykłe 
Pole, na które rycerz może wejść, nie mające żadnych własności dodatkowych. 
• pole mur 
Można spotkać dwa rodzaje murów: mury jadalne i wieczne. Mury wieczne są to pola, na które gracz nigdy nie 
może wejść. Nie można ich zjeść; nie zniszczy ich nawet mina. 
Mury jadalne są to pola, na które rycerz nie może wejść, chyba że usunie mur poprzez zjedzenie go lub wybuch 
miny. Zburzenie takiego muru jest tylko czasowe - mur odrasta po 10 jednostkach czasu. Jeżeli na tym polu stoi 
w tym momencie rycerz, to ginie. 
• pole z miną 
Jeśli rycerz wejdzie na pole z miną, mina wybucha. W polu rażenia miny znajduje się pole, na którym mina była 
umieszczona oraz wszystkie pola, które miały wspólną krawędź z tym polem. Wszystkie mury jadalne znajdujące 
się w polu rażenia miny ulegają zburzeniu, a wszyscy rycerze giną. Pod wpływem czarów działających w labiryncie 
po 10 jednostkach czasu od wybuchu miny na polu tworzy się nowa mina. Jeśli w momencie odrośnięcia miny 
na jej polu stoi rycerz mina wybucha. Miny znajdujące się w sąsiedztwie wybuchającej miny nie wybuchają w 
wyniku jej eksplozji (nie ma propagacji wybuchów). 
• pole teleport 
Każdy rycerz, który znajdzie się na tym polu, zostanie przeteleportowany na inne pole znajdujące się na planszy. 
Na szczęście jeden teleport może przenosić tylko w jedno miejsce. Przy wchodzeniu na miejsce docelowe teleportu 
obowiązują takie same reguły co zawsze (czyli np. nie da się wejść na mur, chyba że jest to mur jadalny, który 
nie odrósł albo nawet mur jadalny stojący, ale teleportuje się Zjadacz z zębami). Przyjmujemy dodatkowo, że 
teleport do teleportu nie działa (żeby uniknąć problemów z ewentualnymi cyklami). 
• pole dziura 
Rycerz, który stanie na to pole wpada w przepaść bez dna i ginie. Każda dziura ma swój rozmiar - jest to liczba 
cegieł, której potrzebuje rycerz Budowniczy do jej zamurowania. Jeśli rycerz ma za mało cegieł, nawet o jedną, to 
niestety ginie. Nikną też jego cegły (dziura się nie zmniejszyła). Po zamurowaniu można bezpiecznie przechodzić 
przez pole z dziurą dopóki pod wpływem czarów działających w labiryncie cegły użyte do zamurowania nie 
rozsypią się w proch, co następuje po 10 jednostkach czasu. Jeśli jakiś pechowiec stoi akurat na tym polu w 
momencie rozsypania się cegieł, to ginie. 
• pola magazyny 
Na początku gry każdy magazyn ma pewną, określoną liczbę zasobów (magazyn dentystyczny - zębów, a ma- 
gazyn budowniczy - cegieł), która jest równa pojemności magazynu. Od momentu, w którym liczba zasobów w 
magazynie stanie się mniejsza niż jego pojemność, alchemicy rozpoczynają produkcję nowego zasobu. Niestety, 
czas produkcji jednego zasobu to 5 jednostek czasu. Alchemicy zaprzestają produkcji, jeśli skończy się wolne 
miejsce w magazynie. Magazyny są dwóch typów: 
– pole magazyn cegieł 
Na tym polu rycerz Budowniczy może uzupełnić worek z cegłami. Ładowanie cegieł do worka odbywa się w 
momencie wejście rycerza na pole z magazynem cegieł. Oczywiście tylko wtedy, gdy rycerz jest budowniczym 
- w przeciwnym przypadku nic się nie dzieje. 
– pole magazyn dentystyczny 
Na tym polu rycerz Zjadacz może uzupełnić brakujące zęby w Stalowej Szczęce. Uzupełnianie odbywa się 
w momencie wejścia na pole; jeśli na pole wejdzie rycerz o innej specjalności niż Zjadacz, nic się nie dzieje. 
• pole legowisko smoka 
To tu mają dotrzeć rycerze. Jeśli rycerz dojdzie do legowiska smoka, to ukrywa się tam, czekając na resztę 
towarzyszy (liczba rycerzy, którzy muszą dojść do tego miejsca jest określana w pliku z danymi). Wynika stąd, 
że gracz nie może go już przesuwać. 
2.4 Co widzi gracz 
Program powinien zapewniać wygodny interfejs graficzny. Gdy gracz wybiera rycerza, to z boku okna powinien widzieć 
opis tego rycerza, np. z liczbą posiadanych zębów. Poza tym gracz powinien widzieć (lub móc zobaczyć) podstawowe 
informacje dotyczące stanu gry (np. ilu ma rycerzy, ilu musi jeszcze doprowadzić do smoka, itp.). Podobnie należy 
postąpic z informacjami np. o liczbie cegieł potrzebnych do zamurowania dziury, gdy ona jest zamurowana. 
2

Na polach kiedyś odwiedzonych gracz powinien widzieć ich obecny stan (co może się różnić od stanu widzianego przez 
rycerza, który odkrył to pole i poszedł sobie dalej, np. dziura mogła się odsłonić, mur odrosnąć, itp.). Jak to możliwe, 
że widzimy stan aktualny? Magia ... 
Należy graficznie rozróżnić dziurę zamurowaną czy zjedzony mur od zwykłego gruntu (wszak wkrótce zamurowanie 
może się rozpaść, a mur odrosnąć). Analogicznie gracz powinien móc odróżnić mur jadalny i niejadalny, pole z miną od 
pola pustego. Pole z miną ma mieć swój specyficzny wygląd (inny od pozostałych pól). Również pole z nieodrośniętą 
miną mają się różnić graficznie od pozostałych rodzajów pól. 
Można założyć, że planszy nie trzeba będzie przewijać (choć przewijanie nie jest trudne). Trzeba tylko zadbać, żeby 
ikonki pól nie były zbyt wielkie (czyli żeby dało się sensownie pograć na planszy mieszczącej się w całości na ekranie). 
2.5 Inne 
Rycerz, który zginął w labiryncie, znika z planszy. Jedna jednostka czasu w labiryncie to jeden ruch - czyli jedno 
przesunięcie rycerza (pod wpływem działania magii czas utracił swoją ciągłość). Gracz widzi pola, na których stoją 
rycerze, pola, które mają wspólną krawędź z jednym z pól, na których stoją rycerze, oraz wszystkie pola, które widział 
do tej pory. “Widzenie” pola oznacza, że gracz wie, jakiego typu ono jest, oraz zna pewne jego parametry: 
• w przypadku pola dziury, jest to jej szerokość, czyli liczba cegieł, potrzebna do jej zamurowania; 
• w przypadku magazynu, wie ile i jakie zasoby magazyn posiada w danej chwili. 
Nie widzi jednak: 
• dokąd prowadzi teleport; 
• ile jeszcze czasu pozostało do odrośnięcia muru, do odnowienia się dziury lub miny. 
Gracz może w danej kolejce zrezygnować z ruchu. 
Należy zaimplementować zapisywanie gry i wczytywanie (tak by móc zacząć grę w miejscu jej przerwania). 
Nie trzeba implementować cofania ruchów (gra stałaby się za łatwa dla grającego). 
2.6 Kończenie gry 
Gra się kończy, gdy wymagana liczba rycerzy dotrze do legowiska smoka (wygrana gracza), liczba rycerzy spadnie 
poniżej liczby wymaganej do zwycięstwa (jeśli do razu było za mało? To plansza była źle skonstruowana!), żaden 
rycerz nie może się ruszyć (w obu przypadkach przegrana gracza). Gracz może także się poddać. 
Program powinien jakoś zasygnalizować wynik gry (np. wyświetlając okienko ze stosownym komunikatem), potem ma 
prawo się zakończyć, może też zaproponować nową rozgrywkę. 
Uwaga: Jeśli gracz nie może wykonać ruchu, to jest jeszcze w pewnych sytuacjach możliwe, że nie przegrał (mina 
może odrosnąć, wybuchnąć i zburzyć jadalny mur blokujący jakiegoś rycerza, mogą też pojawić się zęby w magazynie 
otoczonym jadalnym murem, w którym to magazynie stoi zjadacz). Program nie musi analizować tych sytuacji, 
powinien umożliwić graczowi przechodzenie do następnej kolejki (bez wykonanaia ruchu oczywiście), lub poddanie się. 
2.7 Format pliku z labiryntem 
Liczba całkowita dodatnia (w), podana w pierwszym wierszu pliku jest wysokością labiryntu. W drugim wierszu 
znajduje się liczba równa szerokości labiryntu (s). W następnych w wierszach znajduje się zakodowany opis pól planszy 
- w każdym wierszu znajduje się opis s pól. (Opis pola labiryntu o współrzędnych (i,j) znajduje się więc w i+2 wierszu 
i jest to j-ty z kolei symbol). Symbole kodujące pola planszy są oddzielone średnikami. Lista symboli: 
• Z (pole zwykłe) 
3

• J (mur jadalny) 
• W (mur wieczny) 
• M (pole z miną) 
• Tn,m (teleport przenoszący rycerza na pole o współrzędnych (n,m), gdzie 1<=n<=w, 1<=m<=s) 
• Dk (pole dziura, k jest liczbą całkowitą dodatnią opisującą, jaka jest szerokość dziury, czyli ile potrzeba cegieł, 
aby ją zamurować) 
• Cp (magazyn cegieł, p jest liczbą całkowitą dodatnią określającą pojemność magazynu) 
• Ap (magazyn dentystyczny, p jest liczbą całkowitą dodatnią określającą pojemność magazynu) 
• L (legowisko smoka, takie pole jest na planszy dokładnie jedno) 
Wnastępnym wierszu znajduje się para liczb całkowitych oddzielona średnikiem. Są to współrzędne wejścia do labiryntu 
(wiersz, kolumna). W kolejnym wierszu znajdują się symbole (oddzielone średnikami) opisujące klejnych rycerzy 
drużyny. Symbole mogą się powtarzać. Dozwolone symbole to: 
• N (Rycerz Nadzwyczajny) 
• Zn (Rycerz Zjadacz; n jest liczbą całkowitą dodatnią opisującą liczbę zębów, jaką posiada on w swojej Stalowej 
Szczęce) 
• Bn (Rycerz Budowniczy; n jest liczbą całkowitą dodatnią opisującą liczbę cegieł znajdujących się w jego worku) 
• S (Rycerz Skoczek) 
W ostatnim wierszu znajduje się liczba całkowita dodatnia nie większa od liczby rycerzy w poprzednim wierszu, 
określająca ilu rycerzy musi dojść do legowiska smoka, aby gracz został uznany za zwycięzcę. 
Ponieważ na jednym polu labiryntu może stać tylko jeden rycerz (oczywistym wyjątkiem jest legowisko smoka), to 
rycerze na polu startowym pojawiają się pojedynczo (gdy jeden zejdzie z tego pola wchodzi tam następny - o ile jeszcze 
jest oczywiście - kolejność jest zadana kolejnością w danych). Zasady wchodzenia na pole startowe są takie jak dla 
każdego pola (np. jeśli to by była dziura, to rycerze będą w nią wpadać i ginąć, aż do momentu gdy pojawi się 
Budowniczy. Jeśli byłby to mur, to gracz przegra, bo nie uda mu się wprowadzić na planszę rycerza. Gdyby to był 
mur jadalny, to o ile pierwszy rycerz nie jest Zjadaczem, to gracz przegrywa (nawet jeśli wszyscy pozostali rycerze to 
Zjadacze). 
Przykładowy plik z planszą może więc wyglądać w ten sposób: 
4
3
Z;L;W 
T1,2;Z;J 
C2;D1;Z 
A1;Z;W 
4;2 
N;S;B3;Z2;S 
3 
Należy sprawdzić poprawność danych. 
3 Zadanie 
Napisz program umożliwiający przeprowadzenie pojedynczej rozgrywki. Program ma na początku wczytać planszę, 
potem ma ją wyświetlić i umożliwić graczowi wykonywanie poszczególnych ruchów. Interfejs powinien być graficzny 
(przyciski, mysz) i wygodny. Należy wykorzystać różnorodne elementy tworzeniu GUI przedstawiane na zajęciach. 
Życzę powodzenia! 
4

4 Historia zmian 
1.05: 20/21.04.2005 (JJ) 
– zmiana formatu na LATEXa (dokładniej: LATEX2"), 
– scalenie z PiO. 
1.06: 21/22.04.2005 (JJ) 
– drobne korekty edytorskie, 
– korekta numeracji wersji (+0.01), 
– przywrócenie korekt z zagubionej wersji 1.04: 
 zamienienie s i w w opisie pola teleport, 
 dopisanie, że współrzędne pola wejściowego także są podane w kolejności wiersz-kolumna, 
5