Wyjście Spis treści 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 |
W rozdziale | ||||||
|
Celem artykułu nie jest udostępnianie gier - na pewno w Internecie znajdziecie ich więcej i będą dużo lepsze oraz ciekawsze. Nam chodzi o zademonstrowanie praktycznego zastosowania algorytmów i języka programowania do tworzenia gier logiczno zręcznościowych (wszyscy dobrze zarabiający programiści zaczynali od tego typu programów). Jeśli dokładnie prześledzisz przykłady, poznasz podstawowe metody programowania. Każdy rozdział podzielony jest logicznie na kilka sekcji. Na początku wyjaśniamy zasady danej gry. Następnie na ich podstawie tworzymy algorytm, który prezentujemy również w formie schematów blokowych. Według schematów blokowych piszemy programy w języku Pascal (czasem również w C++).
Powinieneś zapoznać się z algorytmem gry i schematami blokowymi i za ich pomocą próbować samodzielnie napisać program gry - może ci to nawet wyjść dużo lepiej niż nam. Do prezentowanych rozwiązań programów staraj się zaglądać tylko w ostateczności, gdy zupełnie nie wiesz jak zacząć. Bezmyślne kopiowanie naszych rozwiązań nic cię nie nauczy - lepiej dojdź do nich samodzielnie a nie pożałujesz włożonego w to wysiłku.
Prezentowane gry zostały zaimplementowane w dwóch językach programowania:
Oba środowiska są darmowo dostępne w sieci Internet. Zamiast Dev-Pascala można z powodzeniem stosować pakiet FreePascal.
Ponieważ prezentowane gry przeznaczone są dla początkujących programistów, zdecydowaliśmy się oprzeć całkowicie na aplikacji konsoli. Jest to tryb znakowy, w którym program nie korzysta z graficznych funkcji systemu Windows. Dzięki temu możemy zająć się istotą algorytmu, a nie sposobami konwersacji z systemem operacyjnym, które w programach Windows zajmują nawet 80 - 90 % kodu. Oczywiście większość prezentowanych tutaj gier można również z powodzeniem zrealizować w wersji graficznej. W takim przypadku sam algorytm gry nie zmienia się, lecz zmianie ulegają procedury zapisujące elementy gry w okienku konsoli - zamiast zapisywania znaków, należy rysować grafikę.
Aby uzyskać dostęp do funkcji obsługujących konsolę w języku Pascal musimy dołączyć do naszego programu moduł Crt w sposób następujący:
program nazwa; uses Crt; ... |
Od tej chwili program może korzystać ze wszystkich funkcji modułu. Poniżej umieściłem tłumaczenie na język polski fragmentu instrukcji dla Free Pascala, który dotyczy modułu Crt.
Rozdział ten opisuje moduł CRT dla Free Pascala, zarówno w systemie DOS/Windows jak i Linux. Autorem pierwszej wersji dla DOS jest Florian Klämpfl. Moduł został przeniesiony do systemu Linux przez Marka Maya i rozbudowany przez Michaëla Van Canneyta i Petera Vremana. Działa on w konsoli Linuxa oraz w oknach xterm i rxvt pod systemem X-Windows. Oba moduły działają identycznie, z wyjątkiem tego, iż pod Linuxem we wczesnej implementacji (wersje kompilatora 0.9.1 i wcześniejsze) moduł CRT automatycznie czyścił treść okna konsoli przy starcie programu.
Rozdział ten podzielony został na dwie części.
Definicje kolorów :
Black = 0; Blue = 1; Green = 2; Cyan = 3; Red = 4; Magenta = 5; Brown = 6; LightGray = 7; DarkGray = 8; LightBlue = 9; LightGreen = 10; LightCyan = 11; LightRed = 12; LightMagenta = 13; Yellow = 14; White = 15; Blink = 128; |
Różnorodne stałe:
TextAttr: byte = $07; TextChar: char = ' '; CheckBreak: boolean = true; CheckEOF: boolean = false; CheckSnow: boolean = false; DirectVideo: boolean = false; LastMode: word = 3; WindMin: word = $0; WindMax: word = $184f; ScreenWidth = 80; ScreenHeight = 25; |
Kilka zmiennych dla kompatybilności z Turbo Pascalem. Jednakże Free Pascal z nich nie korzysta
var checkbreak : boolean; checkeof : boolean; checksnow : boolean; |
Poniższe stałe definiują tryby pracy ekranu w systemie DOS.
const bw40 = 0; co40 = 1; bw80 = 2; co80 = 3; mono = 7; |
Zmienna TextAttr kontroluje atrybuty koloru, które są używane przy zapisie znaków na ekran.
var TextAttr : byte; |
Zmienna DirectVideo kontroluje zapis na ekran. Jeśli zawiera true, to dostęp jest bezpośredni. Jeśli zawiera false, to wykorzystywane są procedury w BIOS. Zmienna ta działa jedynie w systemie DOS.
var DirectVideo : boolean; |
Zmienna LastMode informuje nas o numerze ostatnio używanego trybu pracy ekranu. Zdefiniowana jest tylko w systemie DOS.
var LastMode : Word; |
Prezentowane przykłady programów działają poprawnie tylko w przypadku uruchomienia ich z poziomu okienka poleceń. W przeciwnym razie okienko konsoli jest natychmiast zamykane po zakończeniu pracy programu. Aby temu zapobiec, dodaj na końcu swojego programu pustą instrukcję readln. Program nie zamknie wtedy swojego okienka konsoli aż naciśniesz klawisz Enter.
Deklaracja:
procedure AssignCrt(var F: Text); |
Opis:
Przypisuje do konsoli plik F. Zapis danych
do pliku F zostaje przekierowany do okienka konsoli.
Jeśli konsola zawiera okno, wszystko zostanie zapisane w oknie.
Zobacz również: Window
Przykład:
program Example1; uses Crt; var F : Text; begin AssignCrt(F); Rewrite(F); { Nie zapomnij otworzyć do zapisu! } WriteLn(F,'To jest zapisywane do Przypisanego Pliku'); Close(F); end. |
Deklaracja:
procedure BigCursor; |
Opis:
Tworzy kursor o kształcie dużego prostokąta. Nie zaimplementowane w wersji Linux.
Zobacz również: CursorOn, CursorOff
Deklaracja:
procedure ClrEol ; |
Opis:
ClrEol czyści bieżący wiersz poczynając od pozycji kursora aż do końca okna. Kursor nie zmienia swojej pozycji.
Zobacz również: DelLine, InsLine, ClrScr
Przykład:
program Example9; uses Crt; begin write('Ten wiersz zostanie usuniety od', ' pozycji kursora do prawego brzegu ekranu'); GotoXY(31,WhereY); ReadKey; ClrEol; writeln; end. |
Deklaracja:
procedure ClrScr; |
Opis:
ClrScr czyści bieżące okno stosując aktualne kolory tekstu i tła. Kursor ustawiany jest w lewym górnym narożniku okna.
Zobacz również: Window
Przykład:
program Example8; uses Crt; begin writeln('Nacisnij dowolny klawisz, aby wyczyscic ekran'); ReadKey; ClrScr; writeln('Teraz pociesz sie wyczyszczonym ekranem'); end. |
Deklaracja:
procedure CursorOff; |
Opis:
Wyłącza widok kursora. W wersji Linux nie zaimplementowane.
Zobacz również: CursorOn, BigCursor
Deklaracja:
procedure CursorOn; |
Opis:
Włącza widok kursora. W wersji Linux nie zaimplementowane.
Zobacz również: BigCursor, CursorOff
Deklaracja:
procedure Delay(DTime: Word); |
Opis:
Delay czeka przez zadaną liczbę milisekund (1/1000 sekundy). Czas ten jest tylko przybliżony i w przypadku przeciążenia systemu może znacznie się różnić od wartości dokładnej. Zatem nie wykorzystuj jej do konstrukcji np. stopera lub zegara.
Zobacz również: Sound, NoSound
Przykład:
program Example15; uses Crt; var i : integer; begin writeln('Odliczanie wsteczne'); for i:=10 downto 1 do begin writeln(i); Delay(1000); {Czekaj przez 1 sekundę} end; writeln('BUCH!!!'); end. |
Deklaracja:
procedure DelLine; |
Opis:
DelLine usuwa bieżący wiersz. Wiersze leżące poniżej zostają przemieszczone w górę o 1 wiersz, a na spodzie bieżącego okna zostaje wstawiony pusty wiersz znaków. Kursor nie zmienia pozycji.
Zobacz również: ClrEol, InsLine, ClrScr
Przykład:
program Example10; uses Crt; begin ClrScr; writeln; writeln('Wiersz nr 1'); writeln('Wiersz nr 2'); writeln('Wiersz nr 2'); writeln('Wiersz nr 3'); writeln; writeln('Ups, Wiersz 2 jest wypisany dwa razy,', ' usunmy go z ekranu'); GotoXY(1,3); ReadKey; DelLine; GotoXY(1,10); end. |
Deklaracja:
procedure GotoXY(X: byte; Y: byte); |
Opis:
Umieszcza kursor na pozycji (X,Y), X jest pozycją w poziomie a Y w pionie względem początku bieżącego okna. Początek ten znajduje się na współrzędnych (1,1) w lewym górnym narożniku okna.
Zobacz również: WhereX, WhereY, Window
Przykład:
program Example6; uses Crt; begin ClrScr; GotoXY(10,10); write('10,10'); GotoXY(70,20); write('70,20'); GotoXY(1,22); end. |
Deklaracja:
procedure HighVideo; |
Opis:
HighVideo przełącza wyświetlanie znaków w tryb podwyższonej jasności ustawiając bit wysokiej intensywności koloru w atrybucie wideo.
Zobacz również: TextColor, TextBackground, LowVideo, NormVideo
Przykład:
program Example14; uses Crt; begin LowVideo; writeln('To jest zapisane z niska intensywnoscia koloru'); HighVideo; writeln('Teraz intensywnosc koloru jest wysoka'); NormVideo; writeln('Kolor wrocil do normalnej wartosci'); end. |
Deklaracja:
procedure InsLine; |
Opis:
InsLine wstawia pusty wiersz na bieżącej pozycji kursora. Wiersze leżące poniżej zostają opuszczone o jedną linijkę w dół. co powoduje zniknięcie ostatniego wiersza z okna. Kursor nie zmienia położenia.
Zobacz również: ClrEol, DelLine, ClrScr
Przykład:
program Example10; uses Crt; begin ClrScr; writeln; writeln('Wiersz nr 1'); writeln('Wiersz nr 3'); writeln; writeln('Ups, zapomnielismy o wierszu nr 2,' + ' wstawmy go na wlasciwe miejsce'); GotoXY(1,3); ReadKey; InsLine; write('Wiersz nr 2'); GotoXY(1,10); end. |
Deklaracja:
function KeyPressed : boolean; |
Opis:
Funkcja Keypressed skanuje bufor klawiatury sprawdzając, czy nie został naciśnięty klawisz. Jeśli tak, to zwraca w wyniku True, a False w przypadku przeciwnym. Nie są zgłaszane klawisze Shift, Alt i Ctrl. Kod klawisza nie zostaje usunięty z bufora i można go odczytać po wywołaniu tej funkcji za pomocą np. ReadKey.
Zobacz również: ReadKey
Przykład:
program Example2; uses Crt; begin writeln('Czekam na nacisniecie klawisza...'); repeat until KeyPressed; { Klawisz nie został odczytany, zatem powinien również pojawić się w wierszu polecenia} end. |
Deklaracja:
procedure LowVideo; |
Opis:
LowVideo przełącza wyjście tekstu do koloru w normalnej intensywności zerując bit intensywności w atrybucie koloru wideo.
Zobacz również: TextColor, TextBackground, HighVideo, NormVideo
Przykład użycia jest w opisie procedury HighVideo.
Deklaracja:
procedure NormVideo; |
Opis:
NormVideo przełącza na standardowe kolory, odczytane przy starcie z pozycji kursora.
Zobacz również: TextColor, TextBackground, LowVideo, HighVideo
Przykład użycia jest w opisie procedury HighVideo.
Deklaracja:
procedure NoSound; |
Opis:
Zatrzymuje dźwięk wydawany przez głośniczek w komputerze. W wersji Linux nie zaimplementowane
Zobacz również: Sound
Przykład:
program Example16; uses Crt; var i : longint; begin writeln('Z glosniczka PC uslyszysz pewne piski'); while (i<15000) do begin inc(i,500); Sound(i); Delay(100); end; writeln('Teraz cisza!'); NoSound; {Zatrzymujemy hałas} end. |
Deklaracja:
function ReadKey : Char; |
Opis:
Funkcja ReadKey odczytuje z bufora klawiatury kod jednego klawisza i zwraca go jako swój wynik. Jeśli jest to klawisz sterujący lub funkcyjny, to zwraca kod ASCII 0. Drugi odczyt funkcją ReadKey da w takim przypadku kod matrycowy danego klawisza.
Uwagi
Odwzorowanie klawiszy pod systemem Linux może powodować zgłaszanie przez funkcję ReadKey złych kodów, zatem należy stosować ją z ostrożnością..
Zobacz również: KeyPressed
Przykład:
program Example3; uses Crt; var ch : char; begin writeln('Nacisnij klawisze kursora w lewo lub w prawo,' + ' Esc=Koniec'); repeat ch := ReadKey; case ch of #0 : begin ch := ReadKey; {Czytamy kod matrycowy} case ch of #75 : writeln('W lewo'); #77 : writeln('W prawo'); end; end; #27 : writeln('ESC'); end; until ch = #27 {Esc} end. |
Deklaracja:
procedure Sound(hz : word); |
Opis:
Wytwarza pisk o częstotliwości hz z głośniczka PC. W wersji Linux nie jest to obsługiwane.
Zobacz również: NoSound
Deklaracja:
procedure TextBackground(CL: Byte); |
Opis:
TextBackground ustawia kolor tła na CL. CL może być jedną z predefiniowanych stałych koloru.
Zobacz również: TextColor, HighVideo, LowVideo, NormVideo
Przykład:
program Example13; uses Crt; begin TextColor(White); writeln('To jest zapisywane ze standardowym kolorem tla'); TextBackground(Green); writeln('Teraz tlo tekstu jest zielone'); TextBackground(Brown); writeln('Teraz tlo tekstu jest brazowe'); TextBackground(Black); writeln('I znow mamy tlo czarne'); end. |
Deklaracja:
procedure TextColor(CL: Byte); |
Opis:
TextColor ustawia kolor tekstu na CL. CL może być jedną z predefiniowanych stałych koloru.
Zobacz również: TextBackground, HighVideo, LowVideo, NormVideo
Przykład:
program Example12; uses Crt; begin writeln('To jest zapisane w standardowym kolorze tekstu'); TextColor(Red); writeln('Teraz na czerwono'); TextColor(White); writeln('Teraz na bialo'); TextColor(LightBlue); writeln('A teraz na jasno niebiesko'); end. |
Deklaracja:
function WhereX : byte; |
Opis:
WhereX zwraca bieżącą współrzędną X pozycji kursora względem bieżącego okna. Początek jest na pozycji (1,1) w lewym górnym narożniku okna.
Zobacz również: GotoXY, WhereY, Window
Przykład:
program Example7; uses Crt; begin writeln('Pozycja kursora: X=',WhereX,' Y=',WhereY); end. |
Deklaracja:
function WhereY : byte; |
Opis:
WhereY zwraca bieżącą współrzędną Y kursora względem bieżącego okna. Początek jest na pozycji (1,1) w lewym górnym narożniku okna.
Zobacz również: GotoXY, WhereX, Window
Deklaracja:
procedure Window(X1, Y1, X2, Y2: byte); |
Opis:
Window tworzy okno tekstowe na ekranie konsoli, do którego będzie przesyłany tekst. Współrzędne (X1,Y1) określają lewy górny narożnik tego okna, a (X2,Y2) prawy dolny. Współrzędne te odnoszą się do ekranu, którego lewy górny narożnik znajduje się na pozycji (1,1). Dalsze operacje związane ze współrzędnymi, za wyjątkiem kolejnego wywołania procedury Window, są względem lewego górnego narożnika tego okna.
Zobacz również: GotoXY, WhereX, WhereY, ClrScr
Przykład:
program Example5; uses Crt; begin ClrScr; writeln('Tworzenie okna od 30,10 do 50,20'); Window(30,10,50,20); writeln('Teraz zapisujemy tekst w tym malym oknie,' + ' ktore wlasnie stworzylismy.' + ' Nie mozemy wyjsc poza jego krawedzie' + ' przy zapisie takiego dlugiego tekstu'); write('Nacisnij dowolny klawisz, aby wyczyscic to okno'); ReadKey; ClrScr; write('Okno jest wyczyszczone, nacisnij dowolny klawisz,' + ' aby powrocic do pelnego ekranu'); ReadKey; {Pełny ekran ma wymiary 80x25} Window(1,1,80,25); Clrscr; writeln('Wrocilismy do pelnego ekranu'); end. |
W grach bardzo często musimy korzystać z sytuacji losowych.
Dokonujemy tego przy pomocy liczb pseudolosowych. Do ich generacji wykorzystywać
będziemy w Pascalu funkcję:
liczba_pseudolosowa := random(zakres); |
Funkcja random zwraca wartość pseudolosową
o wartości od 0 do zakres -1. Jeśli potrzebujemy zakresu od a do b, to
korzystamy z następującego przepisu:
liczba_pseudolosowa := a + random(b - a + 1); |
W programie korzystającym z liczb pseudolosowych należy na samym
początku zainicjować generator tych liczb. Operację tą realizujemy poprzez
wywołanie procedury randomize w sposób następujący:
program nazwa; ... begin randomize; // zainicjowanie generatora liczb pseudolosowych ... // dalsza część programu end. |
Jest to o tyle ważne, iż jeśli pominiemy inicjalizację generatora pseudolosowego, to przy każdym uruchomieniu programu dostaniemy identyczny ciąg liczb pseudolosowych. W konsekwencji gra może szybko się znudzić.
Zainteresowanych tym tematem odsyłam do naszego artykułu o liczbach pierwszych, gdzie dokładnie opisany został problem tworzenia liczb pseudolosowych.
Ponieważ jesteśmy Polakami, powinniśmy pisać programy komunikujące się z użytkownikiem poprawnie po polsku. Tutaj niestety czeka nas niemiła niespodzianka. System Windows i konsola korzystają z innej definicji polskich literek. Jeśli pracujemy w edytorze DevPascala, to nasz tekst programu kodowany jest wg standardu Windows 1250. A gdy teraz tekst polski wyślemy, np. instrukcją writeln, do konsoli korzystającej ze standardu Latin II, zamiast polskich literek zobaczymy inne znaki. Rozwiązaniem jest specjalna funkcja, która konwertuje tekst ze standardu Windows 1250 na standard Latin II (oczywiście możesz pracować w edytorze znakowym Free Pascala, który znajduje się w katalogu bin instalacji DevPascala pod nazwą fp.exe, lecz to rozwiązanie, chociaż pozwala stosować bezproblemowo polskie znaki konsoli, posiada inne wady - np. późniejsza edycja plików w edytorach Windows).
program test; // Funkcja PL konwertuje tekst ze standardu Windows 1250 // na standard konsoli znakowej Latin II //------------------------------------------------------ function PL(s : string) : string; var i : integer; c : char; begin for i := 1 to length(s) do begin case s[i] of 'ą' : c := #165; 'ć' : c := #134; 'ę' : c := #169; 'ł' : c := #136; 'ń' : c := #228; 'ó' : c := #162; 'ś' : c := #152; 'ż' : c := #190; 'ź' : c := #171; 'Ą' : c := #164; 'Ć' : c := #143; 'Ę' : c := #168; 'Ł' : c := #157; 'Ń' : c := #227; 'Ó' : c := #224; 'Ś' : c := #151; 'Ż' : c := #189; 'Ź' : c := #141; else c := s[i]; end; s[i] := c; end; Result := s; end; begin writeln(PL('Sprawdźmy, czy piszę już w języku polskim.')); readln; end. |
Zasada działania funkcji PL jest bardzo prosta. Przegląda ona literka po literce otrzymany jako argument tekst. Jeśli natrafi na polski znak, to zmienia jego kod na Latin II. Dla pozostałych znaków funkcja jest przezroczysta. Poniżej umieściłem przykładowe zastosowanie tej funkcji. Dzięki niej możemy, jak widać, bezproblemowo pisać programy dla konsoli w edytorze pracującym w systemie Windows.
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