Pole minowe - algorytm


Podrozdziały:

 

Zanim utworzymy schemat blokowy algorytmu gry w Pole Minowe, musimy określić zastosowane tutaj struktury danych. Najważniejszą z nich będzie tablica zawierająca planszę gry. Jest to tablica dwuwymiarowa, ponieważ odzwierciedla ona w naturalny sposób naszą planszę. Deklaracja tablicy dwuwymiarowej wygląda następująco:

 

const
  PM_MAX_Y = 19; // określa wysokość pola minowego - 1
  PM_MAX_X = 77; // określa szerokość pola minowego - 1

var
  pm : array[0..PM_MAX_Y,0..PM_MAX_X] of char;

 

Pierwszy wymiar określa liczbę wierszy. Drugi wymiar określa liczbę komórek tablicy w każdym wierszu. Dostęp do poszczególnych elementów (pól) tablicy odbywa się za pomocą dwóch indeksów - numeru wiersza oraz numeru elementu w wierszu. Indeksy te możemy potraktować jako współrzędne pola planszy - pierwsza współrzędna określa położenie pola w pionie, druga w poziomie. Na przykład

pm[4,27]

 

Element ten odpowiada polu planszy umiejscowionemu w piątym wierszu (wiersze są w tablicy numerowane od 0, ponieważ tak jest wygodniej) i w dwudziestej ósmej kolumnie (kolumny również dla wygody są numerowane w tablicy od 0).

 

Symbol Przeznaczenie w algorytmie
px współrzędna x pola, na którym znajduje się gracz, czyli położenie w obrębie wiersza planszy gry.
py współrzędna y pola gracza, czyli numer wiersza.
pmmax y maksymalna ilość wierszy, czyli wysokość pola gry. Wiersze są numerowane od 0!
obrazek

Do rozwiązania problemu gry podejdziemy w sposób funkcyjny. Na głównym schemacie blokowym określimy jedynie podstawowe operacje, które będą zrealizowane, a później zajmiemy się nimi szczegółowo. Taka metoda nosi nazwę zstępującej - duży problem rozbijamy na problemy mniejsze i nie zajmujemy się już całością, lecz poszczególnymi fragmentami.

Grę rozpoczynamy od wyświetlenia strony tytułowej. Tej funkcji nie opiszemy, ponieważ jest ona bardzo prosta i oczywista.

Następnie inicjujemy tablicę Pola Minowego. Operację tę przedstawiamy dokładnie poniżej. Polega ona na wyczyszczeniu tablicy oraz umieszczeniu w niej min w przypadkowo wybranych polach.

Po ustawieniu pola gry wyświetlamy je. Tutaj będzie wykorzystywana procedura Plansza przyjmująca jeden parametr. Parametr ten określa, czy w trakcie wyświetlania planszy pokazywać na niej miny (true), czy też nie (false). Dlaczego tak? - ponieważ na zakończenie gry powinniśmy wyświetlić planszę gry z zaznaczeniem min, aby zatem nie tworzyć dwóch różnych procedur wykonujących w zasadzie to samo, tworzymy jedną z parametrem wybierającym wariant działania.

Gdy plansza gry jest już gotowa, ustalamy początkową pozycję gracza w zmiennych px oraz py. Pozycja ta znajduje się w lewym dolnym narożniku pola gry.

Teraz rozpoczynamy pętlę główną rozgrywki. W pętli wykonujemy tylko dwie operacje złożone. Pierwsza sprawdza, czy w sąsiednich polach wokół położenia gracza znajdują się jakieś miny i wyświetla odpowiednie komunikaty pod polem gry. Procedura obsługująca wymaga przesłania dwóch parametrów - współrzędnych położenia gracza na planszy.

Druga operacja obsługuje ruchy gracza i sprawdza, czy jest to ruch końcowy, tzn. czy gracz doszedł do pola docelowego w prawym górnym narożniku planszy, czy też wpadł na minę. W takich przypadkach ruch jest końcowy i gra się kończy. Wewnątrz funkcji obsługującej te operacje umieścimy wypisywanie odpowiednich napisów. Jeśli ruch nie jest ruchem końcowym, to następuje powrót na początek pętli.Na końcu sprawdzamy, czy gracz życzy sobie zakończyć grę. Jeśli tak, kończymy. W przeciwnym razie wracamy na początek algorytmu.

Ustawienie Pola minowego

Symbol Przeznaczenie w algorytmie
i,j zmienne licznikowe pętli.
pmmax x maksymalna liczba kolumn w wierszu, szerokość planszy gry
pmmax y maksymalna liczba wierszy, wysokość planszy gry
pmi,j pole leżące w i-tym wierszu j-tej kolumnie.
x,y zmienne pomocnicze
puste specjalna wartość oznaczająca, iż pole nie zawiera miny. Będzie to znak spacji.
mina specjalna wartość oznaczająca, iż pole zawiera minę. Będzie to znak gwiazdki.
start wartość określająca pole startowe, u nas jest to znak minus
stop         wartość określająca pole docelowe, u nas jest to znak plus
random(n) wartość pseudolosowa z zakresu od 0 do n-1
obrazek

Zadaniem tej operacji jest utworzenie pola minowego w tablicy pm. Pierwsze dwie pętle wypełniają całą tablicę znakiem spacji, który będzie oznaczał pole puste - nie zawierające min.

Ostatnia pętla wykonywana jest 100 razy. Wewnątrz obliczamy za pomocą funkcji pseudolosowej random() współrzędne pola gry i umieszczamy je odpowiednio w zmiennej x (współrzędna pozioma) i zmiennej y (współrzędna pionowa). Następnie wykorzystujemy te współrzędne do umieszczenia w wybranym losowo polu miny, którą w naszym rozwiązaniu będzie reprezentował znak gwiazdki.

Po zakończeniu tej pętli umieszczamy jeszcze pola startu (w lewym dolnym narożniku) i końca (w prawym górnym narożniku). Plansza jest gotowa. Algorytm kończymy.

Wyświetlanie planszy gry

Symbol Przeznaczenie w algorytmie
i,j zmienne licznikowe pętli. Służą jako indeksy kolumnowe i wierszowe przy dostępie do pól planszy
pmmax x maksymalna liczba kolumn w wierszu, szerokość planszy gry
pmmax y maksymalna liczba wierszy, wysokość planszy gry
pmi,j pole leżące w i-tym wierszu j-tej kolumnie.
puste specjalna wartość oznaczająca, iż pole nie zawiera miny. Będzie to znak spacji.
mina specjalna wartość oznaczająca, iż pole zawiera minę. Będzie to znak gwiazdki.
ślad specjalna wartość oznaczająca, iż gracz już przebywał na danym polu. Stosujemy znak kropki.
start wartość określająca pole startowe, u nas jest to znak minus
stop         wartość określająca pole docelowe, u nas jest to znak plus
obrazek

Chociaż na pierwszy rzut oka algorytm ten wydaje się bardzo skomplikowany, to w rzeczywistości tak nie jest. Operacja wyświetlania planszy gry realizowana jest w dwóch pętlach - zewnętrznej sterowanej przez zmienną i oraz wewnętrznej sterowanej zmienną j. Pętla zewnętrzna jest wykonywana tyle razy, ile wynosi liczba wierszy pola gry. Przy każdym jej obiegu rysowany jest jeden wiersz przez pętlę wewnętrzną.  Każdy wiersz planszy rozpoczyna się na pozycji kolumny ekranu o numerze 2 oraz w wierszu o numerze o 2 większym od numeru wiersza w tablicy pm. Dzięki temu plansza jest ładnie wycentrowana w obrębie okienka konsoli. Pozycję tę ustawiamy przed wykonaniem pętli wewnętrznej.

W pętli wewnętrznej wyświetlane są poszczególne pola planszy zawarte w i-tym wierszu tablicy pm. Pobieramy z tablicy pm po kolei kolejne pola i w zależności od ich typu umieszczamy na ekranie spację w odpowiednio dobranym kolorze tła. Jedynym wyjątkiem są pola zawierające miny. W tym przypadku algorytm sprawdza, czy parametr mina, przekazany z algorytmu głównego, ma wartość logiczną true. Jeśli tak, to wyświetlany jest znak gwiazdki. W przeciwnym razie wyświetlona zostaje spacja. Rozwiązanie to umożliwia wykorzystanie tego samego algorytmu w formie procedury do dwóch zadań - do narysowania planszy bez min na początku gry oraz do wyrysowania tej samej planszy z widocznymi minami po zakończeniu gry wraz z przebytą przez gracza drogą.

Uwaga - operacja pisz znak nie przesuwa wydruku na początek nowego wiersza tylko na następną pozycję wydruku na ekranie. W Pascalu zostanie ona zrealizowana za pomocą procedury write(znak).

Sprawdzanie obecności min

Gracza otacza 8 pól planszy (z wyjątkiem przypadków, gdy znajduje się on przy jej krawędzi):

 

Współrzędne pól planszy
(x-1,y-1) (x,y-1) (x+1,y-1)
(x-1,y) (x,y) (x+1,y)
(x-1,y+1) (x,y+1) (x+1,y+1)

 

Symbol Przeznaczenie w algorytmie
x,y współrzędne pozycji gracza
i,j zmienne licznikowe pętli.
pmi,j pole leżące w i-tym wierszu j-tej kolumnie.
mina zmienna logiczna ustawiana na true, jeśli zostanie wykryta mina
gwiazdka  znak w pm reprezentujący minę
obrazek

Zadaniem procedury jest sprawdzenie, czy na polach o podanych powyżej współrzędnych znajdują się jakieś miny i wyświetlenie komunikatu.

Najpierw ustawiamy pozycję wydruku, w której zostanie umieszczona informacja o wykryciu lub nie wykryciu min.

Zmienna mina przyjmie wartość true, jeśli w sąsiednich polach w stosunku do pozycji gracza występują miny. Pola te przeszukujemy za pomocą dwóch pętli. Zewnętrzna adresuje kolejne wiersze od y-1 do y+1, a wewnętrzna adresuje kolumny od x-1 do x+1.

Warunki sprawdzane w pętli wewnętrznej mają na celu wykrycie sytuacji, gdy gracz znajduje się przy jednej z krawędzi pola gry. W takim przypadku pewnych pól nie będzie - na przykład dla górnej krawędzie wypadnie cały wiersz y-1. Gdy warunki te zostaną spełnione, to pole wskazywane przez indeksy i i j zawarte jest wewnątrz planszy gry i możemy sprawdzić, czy nie ma na nim min. Jeśli są, ustawiamy zmienną mina na true.

Po zakończeniu obu pętli wszystkie pola otaczające pozycję gracza są przeskanowane i zmienna mina zawiera informację o wykrytych tam minach. Zatem testujemy jej zawartość i wypisujemy odpowiedni napis, który pojawi się na pozycji ustawionej na samym początku procedury.

Obsługa ruchów gracza

Symbol Przeznaczenie w algorytmie
x,y współrzędne pozycji gracza
c zmienna z kodem naciśniętego klawisza
pmmax x maksymalna ilość kolumn pola gry
pmmax y maksymalna ilość wierszy pola gry
pmy,x pole planszy na pozycji gracza
mina mina - jest to gwiazdka
koniec pole docelowe - jest to znak plus
start pole startowe - jest to znak minus
ślad pole planszy przebyte przez gracza
obrazek

Algorytm obsługi ruchu gracza nie jest skomplikowany, lecz nieco długi w porównaniu z poprzednio opisywanymi. Na wejściu otrzymujemy dostęp do współrzędnych x i y gracza. Musi być to dostęp poprzez referencję, ponieważ współrzędne te będą zmieniane wewnątrz algorytmu.

Wyświetlamy figurkę gracza i czekamy na klawisz kursora. Po odczycie kodu tego klawisza figurkę gracza należy usunąć z planszy - w przeciwnym razie pozostawałby nieładny ślad ruchów.

Teraz analizujemy kod odczytanego klawisza i podejmujemy stosowne modyfikacje współrzędnych pozycji gracza. Testy mają na celu sprawdzenie, czy gracz nie osiągnął którejś z czterech krawędzi pola gry - wtedy ruch poza krawędź nie może być wykonany i odpowiednia współrzędna nie będzie modyfikowana.

Po zmianie współrzędnych, sprawdzamy na jakim polu znajduje się gracz. Jeśli jest to pole z miną, to gra kończy się raczej nieszczęśliwie. Przed zakończeniem wyświetlamy odpowiedni napis i zawartość planszy wraz z minami i ścieżką przebytą przez gracza. Na pozycji gracza umieszczamy krzyżyk i nich spoczywa w spokoju. Algorytm zwraca wartość true do algorytmu głównego, co zostanie tam zinterpretowane jako ruch końcowy i gra się zakończy.

Jeśli polem, na którym stanął gracz, jest pole docelowe, to wypisujemy gratulacje, wyświetlamy planszę gry z widokiem min, a na pozycji gracza umieszczamy jego figurkę. Do algorytmu głównego zwracamy wartość true, co zakończy rozgrywkę.

Jeśli aktualne pole gracza nie jest polem startowym, to umieszczamy w nim ślad bytności gracza.

Wracamy do algorytmu głównego z wartością false, co zostanie zinterpretowane jako ruch nie kończący grę, zatem gracz wciąż będzie mógł się poruszać po swoim polu minowym.
 


   I Liceum Ogólnokształcące   
im. Kazimierza Brodzińskiego
w Tarnowie

©2021 mgr Jerzy Wałaszek

Dokument ten rozpowszechniany jest zgodnie z zasadami licencji
GNU Free Documentation License.

Pytania proszę przesyłać na adres email: i-lo@eduinf.waw.pl

W artykułach serwisu są używane cookies. Jeśli nie chcesz ich otrzymywać,
zablokuj je w swojej przeglądarce.
Informacje dodatkowe