Wyjście Spis treści Poprzedni Następny
Prezentowane materiały są przeznaczone dla uczniów szkół ponadgimnazjalnych. Autor: mgr Jerzy Wałaszek, wersja 3.0 |
©2008 mgr
Jerzy Wałaszek |
Kolejna, stara gra komputerowa z lat 70-tych ubiegłego wieku. Zasady są następujące. Po prostokątnej planszy porusza się wąż, którym steruje gracz za pomocą klawiszy kursora. W przypadkowych miejscach planszy pojawiają się malinki zjadane przez węża. Po zjedzeniu malinki długość węża rośnie. Gra kończy się, gdy gracz uderzy wężem w ścianę planszy lub w samego węża. Oczywiście zawsze stanie się to prędzej czy później, ponieważ wąż nigdy się nie zatrzymuje i wymaga od gracza ciągłej uwagi.
Podstawowym problemem w tej grze jest rysowanie wizerunku węża na planszy. Wąż będzie zbudowany z segmentów o rozmiarze jednego znaku. Na segment wybierzemy literkę O. Po planszy porusza się jedynie głowa węża. Po każdym ruchu głowy ostatni segment jest usuwany z planszy - tzn. na jego pozycji będziemy drukować znak spacji. W rezultacie otrzymamy wrażenie ruchu węża.
Do wykonania tej animacji musimy przechowywać współrzędne poszczególnych segmentów węża. Wykorzystamy tutaj specjalną strukturę danych zwaną kolejką cykliczną o następującej budowie:
|
elementy | e0 | e1 | e2 | e3 | e4 | e5 | e6 | e7 | e8 | e9 | e10 | e11 | e12 | e13 | e14 | e15 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
wskaźniki | kk |
kolejka |
pk |
Powyżej podajemy przykład kolejki zrealizowanej w 16-to
elementowym ciągu elementów. Początek kolejki, czyli jej pierwszy element
znajduje się w elemencie e11. Koniec kolejki, czyli jej ostatni
element, znajduje się w elemencie e5. Kolejka zawiera elementy
Aby obliczyć długość kolejki cyklicznej nie wystarczy wykonać odejmowanie pk - kk, ponieważ wskaźniki mogą być przewijane na początek struktury danych z uwagi na operację modulo, jak w poniższym przykładzie:
elementy | e0 | e1 | e2 | e3 | e4 | e5 | e6 | e7 | e8 | e9 | e10 | e11 | e12 | e13 | e14 | e15 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
wskaźniki | kolejka | pk | kk |
kolejka |
Teraz kolejka obejmuje elementy e2,e1,e0,e15,e14,e13 i e12. Aby zatem obliczyć długość kolejki cyklicznej na podstawie indeksów pk i kk musimy zastosować poniższą metodę:
if pk > kk then dk := pk - kk + 1 else dk := n + pk - kk + 1; |
pk - wskaźnik początku kolejki kk - wskaźnik końca kolejki dk - długość kolejki n - liczba elementów struktury zawierającej kolejkę |
Długość kolejki jest dla nas istotnym parametrem, ponieważ określa ilość segmentów węża. Struktura przechowująca kolejkę powinna posiadać wystarczająco dużo elementów, aby nigdy nie zdarzyło się, iż początek kolejki nadpisuje jej koniec. Dla prostoty załóżmy, że potrzebne jest tyle elementów, ile wynosi liczba pozycji znakowych na planszy gry. Plansza posiadać będzie 22 wiersze po 78 kolumn, zatem struktura powinna mieć rozmiar 1716 elementów.
Wąż żyje na planszy tak długo, aż nie uderzy głową w barierkę lub w samego siebie. Również musimy sprawdzać, czy głowa węża trafiła w malinkę, której zjedzenie spowoduje wydłużenie węża o 1 segment. Wynika z tego, iż potrzebna nam jest procedura odczytująca znak umieszczony na zadanej pozycji okna konsoli. Procedury takiej nie ma w module Crt, zatem napiszemy ją sami.
Biblioteka Win32 API posiada wszystkie niezbędne procedury do obsługi okienek konsoli. Aby z niej skorzystać, musimy dołączyć do naszego programu moduł Windows, w którym znajdują się deklaracje tych procedur oraz wykorzystywanych przez nie struktur danych. Na początku programu umieszczamy wpis:
... uses Crt, Windows; ... |
Od tego momentu mamy w naszym programie dostęp do wszystkich
procedur biblioteki Win32 API. Do odczytu znaku wykorzystamy następujące
struktury danych i procedury:
HANDLE - liczba 32-bitowa zawierająca tzw. numer dojścia lub uchwyt. Biblioteka Win32 posługuje się dojściami przy odwołaniu do jej wewnętrznych struktur danych.
COORD - struktura definiująca współrzędne pozycji w okienku konsoli. Definicja tej struktury dla języka Pascal jest następująca:
type COORD = record X,Y : word; end; |
Pole X przechowuje numer kolumny, a pole Y przechowuje numer wiersza pozycji w oknie konsoli. Przy zapisie danych do tych pól musimy pamiętać o zmniejszeniu wartości o 1, ponieważ konsola Windows numeruje wiersze i kolumny od 0, a nie od 1 jak w module Crt. Zatem pozycja (1,1) powinna być zapisana w strukturze COORD jako (0,0).
GetStdHandle(typ_dojścia)
- funkcja biblioteki Win32 API udostępniająca dojście do
odpowiedniego kanału przesyłu danych w okienku konsoli. Jako parametr stosujemy
jedną ze stałych zdefiniowanych w module Windows:
Stała | Opis |
---|---|
STD_INPUT_HANDLE | standardowe dojście do wejścia danych |
STD_OUTPUT_HANDLE | standardowe dojście do wyjścia danych |
STD_ERROR_HANDLE | standardowe dojście do wyjścia wiadomości o błędach |
Nas będzie interesowało dojście do wyjścia danych, czyli do zawartości okienka konsoli - STD_OUTPUT_HANDLE.
ReadConsoleOutputCharacter(dojście, bufor, ile, współrzędne, odczytane) - procedura odczytująca z okienka konsoli podaną liczbę znaków do bufora. Parametry są następujące:
dojście | tutaj przekazujemy wartość dojścia do standardowego wyjścia danych konsoli, które otrzymamy z wywołania funkcji GetStdHandle(STD_OUTPUT_HANDLE). |
bufor | adres zmiennej znakowej, do której zostaną przesłane znaki odczytane z okienka konsoli |
ile | liczba znaków do odczytania. Nas będzie interesował tylko jeden znak na danej pozycji, zatem parametr ten przyjmie wartość 1. |
współrzędne | struktura COORD zawierająca pozycję w okienku konsoli, z której mają zostać odczytane znaki. |
odczytane | adres zmiennej, w której procedura umieści liczbę odczytanych znaków. |
Funkcja zwracająca znak z zadanej pozycji okienka konsoli ma następującą postać:
function Znak_na_pozycji(p : COORD) : char; var c : char; k : integer; begin dec(p.x); dec(p.y); // Dostosowujemy współrzędne ReadConsoleOutputCharacter(GetStdHandle(STD_OUTPUT_HANDLE),addr(c),1,p,k); Result := c; end; |
Wąż jest w ciągłym ruchu. Klawisze kursora nie sterują zatem ruchem węża, lecz jego kierunkiem. Aby gra posiadała odpowiednią dynamikę odczyt klawiatury będziemy wykonywać co około 10 milisekund. Natomiast ruchy węża wykonywane będą co 16 obiegów pętli. Pętla będzie posiadała następujący schemat:
Schemat pętli głównej gry |
---|
|
I Liceum Ogólnokształcące |
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