Domino - algorytm


Podrozdziały:

 

obrazek

 

Algorytm gry opracujemy metodą zstępującą. Na początku inicjujemy generator liczb pseudolosowych.

Wchodzimy do pętli głównej, która kontroluje całą rozgrywkę. Pętla ta jest kontynuowana tak długo, aż gracz zrezygnuje z dalszej gry. Na początku pętli wyświetlamy stronę tytułową gry. Ponieważ jest to zadanie standardowe, nie będziemy go opisywać.

Zerujemy wyniki graczy i rozpoczynamy rozgrywkę w pętli wewnętrznej, która wykonuje się tak długo, aż jeden z graczy osiągnie wynik 12 punktów. Rozgrywką rundy zajmuje się procedura Graj Rundę. Funkcja Koniec Rund sprawdza wyniki graczy i przerywa wykonywanie pętli wewnętrznej przy wyniku równym 12. Funkcja Koniec Gry sprawdza, czy gracz ma ochotę zakończyć grę.
 

Runda

Symbol Przeznaczenie w algorytmie
l zmienna zliczająca kolejne obiegi pętli
obrazek

Zadaniem tej procedury jest obsługa jednej rundy gry. Algorytm również rozwiążemy metodą zstępującą. Całość jest wykonywana w pętli sterowanej zmienną l. Ruchy wykonywane są na przemian co 10 obiegów tej pętli - najpierw gracz komputerowy, a później gracz człowiek. Przy każdym obiegu odczytywany jest stan klawiatury. Dzięki temu rozwiązaniu gra ma większą dynamikę przy odczycie klawiatury - np. gracz może zmienić kilka razy kierunek ruchu, zanim postawiona zostanie kostka domina na planszy.

Wykonanie procedury rozpoczniemy od inicjalizacji zmiennych globalnych, z których korzysta nasza gra. Następnie wyświetlamy w oknie konsoli planszę gry. Inicjujemy licznik l na 0 i rozpoczynamy pętlę rozgrywki.

Na początku pętli zwiększamy o 1 licznik, odczekujemy 8 milisekund i odczytujemy klawiaturę. Zadaniem tej procedury jest określenie kierunku układania kostek gracza białego, którym jest człowiek.

Jeśli licznik obiegów pętli osiągnie wartość 10, wykonywana jest analiza ruchu dla komputera. Procedura ta określi kierunek układania czarnych kostek domina, którymi steruje komputer. Po analizie wykonujemy ruch czarnymi kostkami. Procedura Ruch stawia na bieżących współrzędnych w okienku konsoli kostkę domina odpowiedniego gracza, przemieszcza głowicę w odpowiednim kierunku, umieszcza symbol głowicy X na nowych współrzędnych o ile nie nastąpiło zderzenie - jeśli tak, to ustawia odpowiednią informację o tym fakcie w strukturze danych gracza.

Jeśli licznik obiegów osiągnie wartość 20, zerujemy go i wykonujemy ruch białymi kostkami domina.

Pętla rundy jest wykonywana do momentu, aż jeden z graczy zderzy się z przeszkodą. W takim przypadku wywołana zostaje procedura podsumowująca rundę, która animuje upadające kostki domina oraz ustala punktację.

Po tych operacjach algorytm procedury kończy się.

Inicjalizacja danych rundy

W grze wykorzystujemy następujące struktury danych:

 

type
  TKostka = record
    p   : COORD;   // współrzędne w okienku konsoli
    kod : integer; // kod kierunkowy
  end;

  TGracz = record
    stos      : array[0..MAX_STOS] of TKostka;
    wskaznik  : integer;
    pozycja   : COORD;
    obecny    : integer;
    poprzedni : integer;
    kkod      : integer;
    wynik     : integer;
    dlugosc   : integer;
    zderzenie : boolean;
  end;

 

Typ TKostka reprezentuje kostkę domina na planszy. Posiada on dwa pola:


Pole Przeznaczenie
p współrzędne pozycji kostki w obrębie planszy gry
kod złożony kod kierunkowy kostki obliczany wg wzoru:
kierunek poprzedni * 4 + kierunek obecny

 

Typ TGracz reprezentuje dane gracza. Składa się z następujących pól:


Pole Przeznaczenie
stos struktura zawierająca stos kostek
wskaznik zawiera indeks elementu będącego szczytem stosu. Przyjmujemy założenie, iż wskaźnik pokazuje zawsze puste miejsce na stosie
pozycja współrzędne aktualnej pozycji gracza na planszy gry
obecny kod obecnego kierunku układania kostek domina
poprzedni kod kierunku układania kostek w poprzedniej kolejce
kkod służy do wyliczania złożonego kodu kierunkowego kostki
wynik obecna punktacja gracza, wyświetlana na planszy ponad polem gry
dlugosc to pole wykorzystuje gracz komputerowy do generowania długości swojego ruchu. Zawarta w nim liczba określa, przez ile kolejek kostki gracza komputerowego będą układane w bieżącym kierunku, zanim kierunek ten zmieni się na nowy.
zderzenie pole informujące, czy głowica gracza nie zderzyła się z przeszkodą. Jeśli tak, to przyjmuje ono wartość true i rozgrywka się kończy.

 

Dane graczy są w naszej grze umieszczone w dwóch zmiennych globalnych typu TGracz:

 

//------------------------------------------------------
// Zmienne globalne
//------------------------------------------------------
var
  gracz_bialy, gracz_czarny : TGracz;

 

Zadaniem procedury Inicjalizacji Rundy jest nadanie poszczególnym polom tych zmiennych odpowiednich wartości.

Pola należy ustawić następująco:

Dla obu graczy:

Pole Wartość
wskaznik zerujemy, co powoduje ustawienie szczytu stosu na początku struktury stos
wynik zerujemy
zderzenie ustawiamy na false

 

Dla gracza czarnego (komputerowego):

 

Pole Wartość
pozycja X = 25, Y = 14. Ustawi to kostki gracza na środku lewej połówki planszy gry
obecny w prawo - kierunek układania kostek
poprzedni w prawo
dlugosc na 0, co wymusi generację kierunku dla gracza komputerowego

 

Dla gracza białego (człowieka):

Pole Wartość
pozycja X = 55, Y = 13. Ustawi to kostki gracza na środku prawej połówki planszy gry
obecny w lewo - kierunek układania kostek
poprzedni w lewo

 

Plansza gry

obrazek

Po ustawieniu kolorów tła i wymazaniu okienka konsoli rysujemy barierkę. Barierka jest prostokątem zbudowanym ze znaków o kodzie 219, który zajmuje obszar od punktu (2,3) do (79,24). Prostokąt ten w lewej połówce powinien być czarny, a w prawej biały.

Nad barierką umieszczamy czarny napis 'PUNKTY'. Napis ten powinien znajdować się na środku wiersza nr 2, ponieważ wiersz nr 1 zarezerwujemy dla napisu 'GRA SKOŃCZONA', który pojawi się po zakończeniu rozgrywki.

W kolejnym kroku wyświetlamy na środku lewej i prawej połówki planszy gry głowice graczy. Głowice mają postać literki X i umieszczone są na początku układanych kostek domina. Wykorzystamy tutaj odpowiednia procedurę.

Na koniec wyświetlamy ponad barierką wyniki obu graczy i kończymy procedurę.

Zapis głowicy

Symbol Przeznaczenie w algorytmie
gracz reprezentuje rekord danych gracza
kolor określa kolor głowicy
obrazek

Ustawiamy kolor tuszu zgodnie z otrzymanym parametrem kolor. Z pola rekordu gracza pozycja odczytujemy aktualną pozycję głowicy i ustawiamy zgodnie z nią współrzędne wydruku w okienku konsoli. Na koniec wyświetlamy na tych współrzędnych literkę X.

Zapis kostki na stos

Symbol Przeznaczenie w algorytmie
gracz reprezentuje rekord danych gracza przekazany jako parametr wywołania procedury.
stos struktura stosu zawarta w rekordzie gracz
wskaznik pole wskaźnika stosu zawarte w rekordzie gracz
stos[wskaznik] element kostki na stosie wskazywany przez wskaźnik stosu
stos[...].p pole elementu kostki zawierający jej współrzędne
pozycja pole współrzędnych bieżącej kostki zawarte w rekordzie gracz.
stos[...].kod złożony kod kierunkowy kostki na szczycie stosu
poprzedni poprzedni kod kierunku układania kostek domina
obecny obecny kod kierunku układania kostek domina
obrazek


 

Odczyt kostki ze stosu

Symbol Przeznaczenie w algorytmie
gracz reprezentuje rekord danych gracza przekazany jako parametr wywołania procedury.
stos struktura stosu zawarta w rekordzie gracz
wskaznik pole wskaźnika stosu zawarte w rekordzie gracz
stos[wskaznik] element kostki na stosie wskazywany przez wskaźnik stosu
stos[...].p pole elementu kostki zawierający jej współrzędne
pozycja pole współrzędnych pobranej ze stosu kostki zawarte w rekordzie gracz.
stos[...].kod złożony kod kierunkowy kostki na szczycie stosu
kkod złożony kod kierunkowy pobranej kostki zawarty w rekordzie gracz
obrazek



Wyniki

Ta procedura umieszcza ponad ramką pola gry aktualne wyniki graczy - po stronie lewej wynik gracza czarnego, a po stronie prawej wynik gracza białego.

 

Odczyt klawiatury

Procedura odczytu klawiatury sprawdza, czy jest naciśnięty jakiś klawisz, odczytuje go i jeśli jest to jeden z klawiszy kursora, ustawia odpowiednio do kierunku strzałki pole obecny gracza białego.

 

Analiza

Symbol Przeznaczenie w algorytmie
zderzenie zmienna logiczna przyjmująca wartość true, jeśli gracz zderzył się z jakąś przeszkodą
p zmienna pomocnicza używana do przechowania pozycji
pozycja przechowuje aktualną pozycję gracza
obecny kierunek ruchu gracza
dlugosc ilość kroków, po wykonaniu których następuje zmiana kierunku ruchu
l,i zmienne pomocnicze
k[] tablica przechowująca możliwe kierunki ruchu dla gracza
obrazek

 

Procedura Analiza ma za zadanie wygenerowanie kierunku ruchu dla gracza komputerowego. Na początku sprawdzamy, czy jest ustawiona zmienna zderzenie. Jeśli tak, to nie generujemy nowego kierunku ruchu i przerywamy procedurę.

Pierwsza część algorytmu ma za zadanie sprawdzić, czy na drodze gracza komputerowego znajduje się jakaś przeszkoda. W tym celu badamy znak na pozycji, do której dojdzie gracz w następnym ruchu. Jeśli jest on inny niż spacja, zerujemy zmienną dlugosc.

Druga część algorytmu sprawdza, czy dlugosc ma wartość 0. Jeśli tak, to zmienna dlugość przyjmuje nową wartość pseudolosową z zakresu od 1 do 10. Następnie badamy cztery kierunki wokół bieżącej pozycji. Jeśli pozycje te są puste - zawierają spację - to zapisujemy je kolejno w tablicy k[], a zmienna l zawiera liczbę wolnych kierunków. Na końcu wybieramy przypadkowy kierunek z tablicy k[] w przypadku, gdy tablica ta coś zawiera, czyli l > 0. Jeśli warunek ten nie jest spełniony to kierunku nie zmieniamy, co i tak nie ma znaczenia, gdyż gracz nie ma przed sobą żadnej wolnej drogi.

 

Ruch

Symbol Przeznaczenie w algorytmie
gracz rekord danych gracza
kolor kod koloru do ustawienia wydruku kostek domina
pozycja pole rekordu gracza zawierające aktualną pozycję kostek domina
poprzedni kod poprzedniego kierunku ustawiania kostek
obecny kod obecnego kierunku ustawiania kostek
domino tablica znakowa zawierająca znaki kostek domina w zależności od kodów kierunku
zderzenie pole zawiera true, jeśli gracz zderzył się z przeszkodą
c zmienna pomocnicza
obrazek

Procedura drukuje w okienku konsoli kostkę domina gracza, zapamiętuje ją na stosie i przemieszcza głowicę na nową pozycję. Dla gracza komputerowego zmniejszana jest o 1 zawartość zmiennej dlugosc - gdy dojdzie do zera, procedura Analiza wygeneruje nowy kierunek ruchu.

Jeśli nowa pozycja jest pusta, procedura umieszcza tam znak X i kończy działanie.

Jeśli na nowej pozycji znajduje się głowica przeciwnika, następuje zderzenie obu graczy i procedura ustawia odpowiednie pola w rekordach gracza białego i czarnego.

W przeciwnym razie jest to zwykłe zderzenie gracza i zostaje ustawione pole zderzenie. Spowoduje to zakończenie rundy. i przewrócenie kostek domina należących do gracza wykonującego ten ruch.

Podsumowanie Rundy

Symbol Przeznaczenie w algorytmie
gracz czarny rekord danych gracza czarnego - komputera
gracz bialy rekord danych gracza białego - człowieka
wskaznik pole danych gracza zawierające pozycję na stosie kostek
zderzenie pole zawierające informację o zderzeniu gracza z przeszkodą
wynik pole zawierające punktację gracza
obrazek

Zadaniem procedury jest wykonanie animacji przewracających się kostek domina gracza, który uderzył w przeszkodę. Następnie zaliczeniu punktu dla gracza przeciwnego.

Animację wykonujemy w pierwszej pętli. Działa ona do momentu wyzerowania obu wskaźników stosu dla graczy. Wewnątrz pętli wywoływana jest procedura przewracania kostki, do której przekazujemy rekord danych gracza oraz kolor kostek. Procedura Przewracaj Kostkę powinna ustawić kolor wydruku zgodnie z drugim parametrem, następnie pobrać ze stosu gracza kostkę domina i jeśli gracz ma ustawione pole zderzenie, to w zależności od złożonego kodu kierunkowego kostki wyświetlić odpowiedni znak zgodnie z tabelą przewróconych kostek domina. Procedurę tę wywołujemy kolejno dla gracza czarnego i białego.

W dalszej kolejności sprawdzamy, który z graczy się zderzył i zwiększamy punkty gracza przeciwnego. Zwróć uwagę, iż procedura reaguje poprawnie na sytuację, gdy obaj gracze zderzyli się głowicami - przewrócone zostaną kostki czarne i białe oraz zwiększone punkty obu graczy.

Bardzo ważną rzeczą jest opróżnienie bufora klawiatury, ponieważ może to powodować problemy w następnej rundzie. Bufor opróżniamy bardzo prosto: wystarczy sprawdzać w pętli, czy jest naciśnięty jakiś klawisz i jeśli tak, to odczytujemy go i czekamy około 100 milisekund, po czym całość powtarzamy aż do momentu, gdy żaden klawisz nie będzie naciśnięty.

Koniec Rund

Funkcja końca rund sprawdza jedynie, czy wynik jednego z graczy jest równy 12 punktów. Jeśli tak, to na środku pierwszego wiersza wypisuje napis G-R-A S-K-O-N-C-Z-O-N-A i zwraca wartość logiczną true. Spowoduje to zakończenie rozgrywki. W przeciwnym razie zwraca false i gra jest kontynuowana w następnej rundzie.

 

Koniec Gry

Funkcja końca gry upewnia się, czy gracz chce zakończyć grę. Jeśli tak, zwraca true. W przeciwnym razie zwraca false.

 


   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