![]() |
Wyjście Spis treści Poprzedni Następny
Autor: mgr Jerzy Wałaszek, wersja 3.0 |
©2008 mgr
Jerzy Wałaszek |
W tym rozdziale: | Podrozdziały: |
Prezentowane poniżej programy utworzono w następujących środowiskach programowania:
Jeśli stosujesz inne środowiska, to prawdopodobnie będziesz musiał przetworzyć odpowiednio kod programów.
Na podstawie opisanego algorytmu tworzymy program w języku Pascal. Poniżej przedstawiamy przykładowe zrzuty zawartości okienka konsoli oraz kod źródłowy programu.
![]() Strona tytułowa gry |
---|
![]() Przykładowa rozgrywka |
// D O M I N O // WERSJA FUNKCYJNA //-------------------------------------------- // (C)2004 mgr Jerzy Wałaszek I LO w Tarnowie program GraDomino; uses Crt, Windows; //---------------------------------------------------- // PROCEDURY I FUNKCJE POMOCNICZE //---------------------------------------------------- // 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; // Procedura centruje w bieżącym wierszu // tekst podany jako parametr //---------------------------------------------------- procedure Centruj(t : string); begin GotoXY(1 + (80-length(t)) div 2, WhereY); writeln(t); end; // Procedura rysuje pojedynczą ramkę ze znaków // tabelek. Parametry określają współrzędne // lewego górnego i prawego dolnego narożnika //---------------------------------------------------- procedure Ramka(xp,yp,xk,yk : integer); var i : integer; begin GotoXY(xp,yp); write(#218); GotoXY(xp,yk); write(#192); GotoXY(xk,yp); write(#191); GotoXY(xk,yk); write(#217); for i := xp + 1 to xk - 1 do begin GotoXY(i,yp); write(#196); GotoXY(i,yk); write(#196); end; for i := yp + 1 to yk - 1 do begin GotoXY(xp,i); write(#179); GotoXY(xk,i); write(#179); end; end; // Funkcja odczytuje znak na pozycji p okna konsoli // Uwaga - znaki ramki będą odczytane nieprawidłowo jako // literki. //------------------------------------------------------ function Znak_na_pozycji(p : COORD) : char; var c : char; k : integer; begin dec(p.x); dec(p.y); ReadConsoleOutputCharacter(GetStdHandle(STD_OUTPUT_HANDLE), addr(c),1,p,k); Result := c; end; //------------------------------------------------------ // PROGRAM GRY //------------------------------------------------------ // Stałe definiujące kierunek układania kostek domina //------------------------------------------------------ const gora = 0; prawo = 1; dol = 2; lewo = 3; // Stała definiująca rodzaj znaku kostki domina w zależności // od poprzedniego kierunku układania i bieżącego. //------------------------------------------------------ domino : string[16] = '-\X/\|/|X/-\/|\|'; // Stała definiująca znaki dla walących się kostek domina //------------------------------------------------------ upadek : string[16] = '/-/-|\-\\-\||/|/'; MAX_STOS = 840; // Maksymalny rozmiar stosu // Definicje typów //------------------------------------------------------ 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; //------------------------------------------------------ // Zmienne globalne //------------------------------------------------------ var gracz_bialy, gracz_czarny : TGracz; // Procedura odczytuje kostkę ze stosu //------------------------------------------------------ procedure Czytaj(var g : TGracz); begin with g do begin if wskaznik > 0 then dec(wskaznik); with stos[wskaznik] do begin pozycja := p; kkod := kod; end; end; end; // Procedura zapisuje kostkę na stosie //------------------------------------------------------ procedure Zapisz(var g : TGracz); begin with g do if wskaznik <= MAX_STOS then begin with stos[wskaznik] do begin p := pozycja; kod := poprzedni * 4 + obecny; end; inc(wskaznik); end; end; // Procedura zapisuje na stosie bieżącą kostkę, a na jej // pozycji rysuje głowicę X //------------------------------------------------------ procedure PiszGlowice(var g : TGracz; a : integer); begin TextAttr := a; with g do begin GotoXY(pozycja.X,pozycja.Y); write('X'); end; end; // Procedura wyświetla stronę tytułową, czeka na dowolny // klawisz i czyści ekran //------------------------------------------------------ procedure StronaTytulowa; begin TextAttr := $07; ClrScr; GotoXY(1,4); TextAttr := $8f; Centruj(PL(' ')); Centruj(PL(' D O M I N O ')); Centruj(PL(' ')); TextAttr := $71; Centruj(PL(' ')); Centruj(PL(' (C)2004 mgr Jerzy Wałaszek ')); Centruj(PL(' ')); TextAttr := $9f; Centruj(PL(' ')); Centruj(PL(' I Liceum Ogólnokształcące ')); Centruj(PL(' im. Kazimierza Brodzińskiego ')); Centruj(PL(' w Tarnowie ')); Centruj(PL(' ')); TextAttr := $f1; Centruj(PL(' ')); Centruj(PL(' Pokonaj komputer w układaniu ')); Centruj(PL(' kostek domina ')); Centruj(PL(' ')); TextAttr := $f4; Centruj(PL(' Gdy będziesz gotowy, ')); Centruj(PL(' naciśnij dowolny klawisz ')); Centruj(PL(' ')); TextAttr := $0e; Ramka(23,3,58,22); while ReadKey = #0 do; // Oczekiwanie na dowolny klawisz TextAttr := $07; ClrScr; end; // Procedura inicjuje wszystkie zmienne rundy //------------------------------------------------------ procedure InicjujRunde; begin with gracz_bialy do begin wskaznik := 0; obecny := lewo; poprzedni := lewo; pozycja.X := 55; pozycja.Y := 13; zderzenie := false; end; with gracz_czarny do begin wskaznik := 0; obecny := prawo; poprzedni := prawo; pozycja.X := 25; pozycja.Y := 14; dlugosc := 0; zderzenie := false; end; end; // Procedura wyświetla bieżącą punktację //------------------------------------------------------ procedure Wyniki; begin TextAttr := $80; GotoXY(20,2); write(gracz_czarny.wynik:2); GotoXY(30,2); write('<'); TextAttr := $8f; GotoXY(61,2); write(gracz_bialy.wynik:2); GotoXY(51,2); write('>'); end; // Procedura wyświetla planszę gry //------------------------------------------------------ procedure Plansza; var i : integer; begin TextAttr := $80; ClrScr; for i := 2 to 40 do begin GotoXY(i,3); write(#219); GotoXY(i,24); write(#219); end; TextAttr := $8f; for i := 41 to 79 do begin GotoXY(i,3); write(#219); GotoXY(i,24); write(#219); end; for i := 4 to 23 do begin TextAttr := $80; GotoXY(2,i); write(#219); TextAttr := $8f; GotoXY(79,i); write(#219); end; TextAttr := $80; GotoXY(38,2); write('PUNKTY'); PiszGlowice(gracz_czarny,$80); PiszGlowice(gracz_bialy,$8f); Wyniki; end; // Procedura odczytuje stan klawiatury i jeśli naciśnięto // klawisz kursora, zmieniany jest odpowiednio kierunek // układania kostek domina gracza białego //------------------------------------------------------ procedure CzytajKlawiature; var c : char; begin with gracz_bialy do if KeyPressed then begin repeat c := ReadKey; until c <> #0; case c of #75 : obecny := lewo; #77 : obecny := prawo; #72 : obecny := gora; #80 : obecny := dol; end; end; end; // Procedura analizuje sytuacje komputera i generuje // odpowiednie kierunki ruchu //------------------------------------------------------ procedure Analiza; var l,i : integer; k : array[0..3] of integer; p : COORD; begin with gracz_czarny do if not zderzenie then begin p := pozycja; case obecny of gora : dec(p.Y); dol : inc(p.Y); prawo : inc(p.X); lewo : dec(p.X); end; if Znak_na_pozycji(p) <> ' ' then dlugosc := 0; if dlugosc = 0 then begin dlugosc := 1 + random(10); l := 0; for i := gora to lewo do begin p := pozycja; case i of gora : dec(p.Y); dol : inc(p.Y); prawo : inc(p.X); lewo : dec(p.X); end; if Znak_na_pozycji(p) = ' ' then begin k[l] := i; inc(l); end; end; if l > 0 then obecny := k[random(l)]; end; end; end; // Procedura dokonuje ruchu. Jeśli głowica zderza się // z przeszkodą, ustawia pole zderzenie. Jeśli zderzenie // następuje z głowicą drugiego gracza, zostaje ustawione // pole zderzenie w obu rekordach. //------------------------------------------------------ procedure Ruch(var g : TGracz; a : integer); begin with g do begin TextAttr := a; gotoXY(pozycja.X,pozycja.Y); write(domino[poprzedni * 4 + obecny + 1]); Zapisz(g); poprzedni := obecny; if not zderzenie then begin dec(dlugosc); case obecny of gora : dec(pozycja.Y); dol : inc(pozycja.Y); lewo : dec(pozycja.X); prawo : inc(pozycja.X); end; case Znak_na_pozycji(pozycja) of ' ' : begin // wolne miejsce PiszGlowice(g,a); end; 'X' : begin // zderzenie z głowicą gracz_bialy.zderzenie := true; gracz_czarny.zderzenie := true; end; else // zderzenie z normalną przeszkodą zderzenie := true; end; end; end; end; // Procedura pobiera ze stosu kostkę domina gracza. // Sprawdza, czy jest ustawione pole zderzenie. Jeśli tak, // pobrana kostka zostanie wyswietlona jako przewrócona. //------------------------------------------------------ procedure PrzewracajKostke(var g : TGracz; a : integer); begin TextAttr := a; with g do begin Czytaj(g); if zderzenie then begin GotoXY(pozycja.X,pozycja.Y); write(upadek[kkod + 1]); end; end; end; // Procedura animuje przewracanie kostek domina dla gracza // przegranego (lub obu). Modyfikuje liczbę punktów. //------------------------------------------------------ procedure PodsumujRunde; begin while (gracz_czarny.wskaznik > 0) or (gracz_bialy.wskaznik > 0) do begin PrzewracajKostke(gracz_czarny,$80); PrzewracajKostke(gracz_bialy,$8f); Delay(50); end; if gracz_czarny.zderzenie then inc(gracz_bialy.wynik); if gracz_bialy.zderzenie then inc(gracz_czarny.wynik); Wyniki; while KeyPressed do begin ReadKey; Delay(100); end; end; // Procedura obsługuje jedną rundę. Wyjście następuje // po przegranej jednego z graczy (lub obu) //------------------------------------------------------ procedure GrajRunde; var l : integer; begin InicjujRunde; Plansza; l := 0; repeat inc(l); Delay(8); CzytajKlawiature; if l = 10 then begin Analiza; Ruch(gracz_czarny,$80); end; if l = 20 then begin l := 0; Ruch(gracz_bialy,$8f); end; until gracz_bialy.zderzenie or gracz_czarny.zderzenie; PodsumujRunde; end; // Funkcja sprawdza, czy któryś z graczy osiągnął 12 punktów. // Jeśli nie, to zwraca false. Jeśli tak, to wypisuje // informacje o końcu gry i zwraca true. //------------------------------------------------------ function KoniecRund : boolean; begin if (gracz_bialy.wynik = 12) or (gracz_czarny.wynik = 12) then begin TextAttr := $8f; GotoXY(1,1); Centruj(PL('G-R-A S-K-O-Ń-C-Z-O-N-A')); Result := true; end else Result := false; end; // Funkcja upewnia się, czy gracz chce zakończyć grę w Domino. // Jeśli tak, zwraca true. //------------------------------------------------------ function KoniecGry : boolean; begin TextAttr := $8e; GotoXY(21,25); write('Jeszcze raz ? '); TextAttr := $8f; write('[T] = Tak, [Inny] = Nie.'); Result := UpCase(ReadKey) <> 'T'; end; var a : integer; begin Randomize; a := TextAttr; CursorOff; repeat StronaTytulowa; gracz_bialy.wynik := 0; gracz_czarny.wynik := 0; repeat GrajRunde; until KoniecRund; until KoniecGry; TextAttr := a; CursorOn; ClrScr; end. |
Gra Domino jest jakby stworzona dla wersji obiektowej. Obiektem bazowym będzie TStos, który umożliwi zapisywanie kostek gracza na stosie oraz pobieranie ich ze stosu. Operację tę zrealizujemy za pomocą własności d. Zapis do niej powoduje umieszczenie przekazanych danych na stosie, a odczyt pobranie tych danych ze stosu.
Na bazie obiektu TStos powstanie obiekt TGracz, który będzie zawierał pozostałe procedury i funkcje obsługujące poszczególnych graczy.
W końcu zbudujemy obiekt TGra łączący w sobie obiekty gracza białego i czarnego.
// D O M I N O // WERSJA OBIEKTOWA //-------------------------------------------- // (C)2004 mgr Jerzy Wałaszek I LO w Tarnowie program GraDomino; uses Crt, Windows; //---------------------------------------------------- // PROCEDURY I FUNKCJE POMOCNICZE //---------------------------------------------------- // 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; // Procedura centruje w bieżącym wierszu // tekst podany jako parametr //---------------------------------------------------- procedure Centruj(t : string); begin GotoXY(1 + (80-length(t)) div 2, WhereY); writeln(t); end; // Procedura rysuje pojedynczą ramkę ze znaków // tabelek. Parametry określają współrzędne // lewego górnego i prawego dolnego narożnika //---------------------------------------------------- procedure Ramka(xp,yp,xk,yk : integer); var i : integer; begin GotoXY(xp,yp); write(#218); GotoXY(xp,yk); write(#192); GotoXY(xk,yp); write(#191); GotoXY(xk,yk); write(#217); for i := xp + 1 to xk - 1 do begin GotoXY(i,yp); write(#196); GotoXY(i,yk); write(#196); end; for i := yp + 1 to yk - 1 do begin GotoXY(xp,i); write(#179); GotoXY(xk,i); write(#179); end; end; // Funkcja odczytuje znak na pozycji p okna konsoli // Uwaga - znaki ramki będą odczytane nieprawidłowo jako // literki. //------------------------------------------------------ function Znak_na_pozycji(p : COORD) : char; var c : char; k : integer; begin dec(p.x); dec(p.y); ReadConsoleOutputCharacter(GetStdHandle(STD_OUTPUT_HANDLE), addr(c),1,p,k); Result := c; end; //------------------------------------------------------ // PROGRAM GRY //------------------------------------------------------ // Stałe definiujące kierunek układania kostek domina //------------------------------------------------------ const gora = 0; prawo = 1; dol = 2; lewo = 3; // Stała definiująca rodzaj znaku kostki domina w zależności // od poprzedniego kierunku układania i bieżącego. //------------------------------------------------------ domino : string[16] = '-\X/\|/|X/-\/|\|'; // Stała definiująca znaki dla walących się kostek domina //------------------------------------------------------ upadek : string[16] = '/-/-|\-\\-\||/|/'; MAX_STOS = 840; // Maksymalny rozmiar stosu // Definicje obiektów //------------------------------------------------------ type TKostka = record p : COORD; kod : integer; end; TStos = class private s : array[0..MAX_STOS] of TKostka; w : integer; procedure FPut(k : TKostka); function FGet : TKostka; public constructor Tworz; property d : TKostka read FGet write FPut; procedure ZerujStos; function StosPusty : boolean; end; TGracz = class(TStos) private pozycja : COORD; kolor : integer; obecny : integer; poprzedni : integer; kod : integer; wynik : integer; dlugosc : integer; zderzenie : boolean; public constructor Tworz(k : integer); procedure Analiza; procedure CzytajKlawiature; procedure Inicjuj; procedure InicjujRunde; procedure PiszGlowice; procedure PrzewracajKostke; end; TGra = class private gracz_bialy : TGracz; gracz_czarny : TGracz; a : integer; public constructor Tworz; destructor Usun; procedure Graj; procedure GrajRunde; function KoniecGry : boolean; function KoniecRund : boolean; procedure Plansza; procedure PodsumujRunde; procedure Ruch(var g : TGracz); procedure StronaTytulowa; procedure Wyniki; end; // Metody obiektu TStos //------------------------------------------------------ constructor TStos.Tworz; begin ZerujStos; end; procedure TStos.FPut(k : TKostka); begin s[w] := k; Inc(w); end; function TStos.FGet : TKostka; begin if w > 0 then dec(w); Result := s[w]; end; procedure TStos.ZerujStos; begin w := 0; end; function TStos.StosPusty : boolean; begin Result := (w = 0); end; // Metody obiektu TGracz //------------------------------------------------------ constructor TGracz.Tworz(k : integer); begin inherited Tworz; kolor := k; end; // Procedura pobiera ze stosu kostkę domina gracza. // Sprawdza, czy jest ustawione pole zderzenie. Jeśli tak, // pobrana kostka zostanie wyswietlona jako przewrócona. //------------------------------------------------------ procedure TGracz.PrzewracajKostke; var k : TKostka; begin TextAttr := kolor; k := d; // odczyt kostki ze stosu if zderzenie then begin GotoXY(k.p.X,k.p.Y); write(upadek[k.kod + 1]); end; end; // Procedura inicjalizacji danych gracza na początku // rozgrywki. //------------------------------------------------------ procedure TGracz.Inicjuj; begin wynik := 0; end; // Procedura analizuje sytuacje komputera i generuje // odpowiednie kierunki ruchu //------------------------------------------------------ procedure TGracz.Analiza; var l,i : integer; k : array[0..3] of integer; p : COORD; begin if not zderzenie then begin p := pozycja; case obecny of gora : dec(p.Y); dol : inc(p.Y); prawo : inc(p.X); lewo : dec(p.X); end; if Znak_na_pozycji(p) <> ' ' then dlugosc := 0; if dlugosc = 0 then begin dlugosc := 1 + random(10); l := 0; for i := gora to lewo do begin p := pozycja; case i of gora : dec(p.Y); dol : inc(p.Y); prawo : inc(p.X); lewo : dec(p.X); end; if Znak_na_pozycji(p) = ' ' then begin k[l] := i; inc(l); end; end; if l > 0 then obecny := k[random(l)]; end; end; end; // Procedura odczytuje stan klawiatury i jeśli naciśnięto // klawisz kursora, zmieniany jest odpowiednio kierunek // układania kostek domina gracza białego //------------------------------------------------------ procedure TGracz.CzytajKlawiature; var c : char; begin if KeyPressed then begin repeat c := ReadKey; until c <> #0; case c of #75 : obecny := lewo; #77 : obecny := prawo; #72 : obecny := gora; #80 : obecny := dol; end; end; end; // Procedura inicjuje wszystkie zmienne rundy // dla danego gracza //------------------------------------------------------ procedure TGracz.InicjujRunde; begin dlugosc := 0; zderzenie := false; ZerujStos; if kolor = $8f then begin obecny := lewo; poprzedni := lewo; pozycja.X := 55; pozycja.Y := 13; end else begin obecny := prawo; poprzedni := prawo; pozycja.X := 25; pozycja.Y := 14; end; end; // Procedura zapisuje na stosie bieżącą kostkę, a na jej // pozycji rysuje głowicę X //------------------------------------------------------ procedure TGracz.PiszGlowice; var k : TKostka; begin TextAttr := kolor; GotoXY(pozycja.X,pozycja.Y); write('X'); end; // Metody obiektu TGra //------------------------------------------------------ constructor TGra.Tworz; begin Randomize; CursorOff; a := TextAttr; gracz_czarny := TGracz.Tworz($80); gracz_bialy := TGracz.Tworz($8f); end; destructor TGra.Usun; begin TextAttr := a; CursorOn; ClrScr; end; // Funkcja sprawdza, czy któryś z graczy osiągnął 12 punktów. // Jeśli nie, to zwraca false. Jeśli tak, to wypisuje // informacje o końcu gry i zwraca true. //------------------------------------------------------ function TGra.KoniecRund : boolean; begin if (gracz_bialy.wynik = 12) or (gracz_czarny.wynik = 12) then begin TextAttr := $8f; GotoXY(1,1); Centruj(PL('G-R-A S-K-O-Ń-C-Z-O-N-A')); Result := true; end else Result := false; end; // Funkcja upewnia się, czy gracz chce zakończyć grę w Domino. // Jeśli tak, zwraca true. //------------------------------------------------------ function TGra.KoniecGry : boolean; begin TextAttr := $8e; GotoXY(21,25); write('Jeszcze raz ? '); TextAttr := $8f; write('[T] = Tak, [Inny] = Nie.'); Result := UpCase(ReadKey) <> 'T'; end; // Procedura animuje przewracanie kostek domina dla gracza // przegranego (lub obu). Modyfikuje liczbę punktów. //------------------------------------------------------ procedure TGra.PodsumujRunde; begin repeat gracz_czarny.PrzewracajKostke; gracz_bialy.PrzewracajKostke; Delay(50); until gracz_czarny.StosPusty and gracz_bialy.StosPusty; if gracz_czarny.zderzenie then inc(gracz_bialy.wynik); if gracz_bialy.zderzenie then inc(gracz_czarny.wynik); Wyniki; while KeyPressed do begin ReadKey; Delay(100); end; end; // Procedura wyświetla bieżącą punktację //------------------------------------------------------ procedure TGra.Wyniki; begin TextAttr := $80; GotoXY(20,2); write(gracz_czarny.wynik:2); GotoXY(30,2); write('<'); TextAttr := $8f; GotoXY(61,2); write(gracz_bialy.wynik:2); GotoXY(51,2); write('>'); end; // Procedura wyświetla planszę gry //------------------------------------------------------ procedure TGra.Plansza; var i : integer; begin TextAttr := $80; ClrScr; for i := 2 to 40 do begin GotoXY(i,3); write(#219); GotoXY(i,24); write(#219); end; TextAttr := $8f; for i := 41 to 79 do begin GotoXY(i,3); write(#219); GotoXY(i,24); write(#219); end; for i := 4 to 23 do begin TextAttr := $80; GotoXY(2,i); write(#219); TextAttr := $8f; GotoXY(79,i); write(#219); end; TextAttr := $80; GotoXY(38,2); write('PUNKTY'); gracz_czarny.PiszGlowice; gracz_bialy.PiszGlowice; Wyniki; end; // Procedura wyświetla stronę tytułową, czeka na dowolny // klawisz i czyści ekran //------------------------------------------------------ procedure TGra.StronaTytulowa; begin TextAttr := $07; ClrScr; GotoXY(1,4); TextAttr := $8f; Centruj(PL(' ')); Centruj(PL(' D O M I N O ')); Centruj(PL(' ')); TextAttr := $71; Centruj(PL(' ')); Centruj(PL(' (C)2004 mgr Jerzy Wałaszek ')); Centruj(PL(' ')); TextAttr := $9f; Centruj(PL(' ')); Centruj(PL(' I Liceum Ogólnokształcące ')); Centruj(PL(' im. Kazimierza Brodzińskiego ')); Centruj(PL(' w Tarnowie ')); Centruj(PL(' ')); TextAttr := $f1; Centruj(PL(' ')); Centruj(PL(' Pokonaj komputer w układaniu ')); Centruj(PL(' kostek domina ')); Centruj(PL(' ')); TextAttr := $f4; Centruj(PL(' Gdy będziesz gotowy, ')); Centruj(PL(' naciśnij dowolny klawisz ')); Centruj(PL(' ')); TextAttr := $0e; Ramka(23,3,58,22); while ReadKey = #0 do; // Oczekiwanie na dowolny klawisz TextAttr := $07; ClrScr; end; // Procedura dokonuje ruchu. Jeśli głowica zderza się // z przeszkodą, ustawia pole zderzenie. Jeśli zderzenie // następuje z głowicą drugiego gracza, zostaje ustawione // pole zderzenie w obu rekordach. //------------------------------------------------------ procedure TGra.Ruch(var g : TGracz); var k : TKostka; begin with g do begin TextAttr := kolor; GotoXY(pozycja.X,pozycja.Y); write(domino[poprzedni * 4 + obecny + 1]); k.p := pozycja; k.kod := poprzedni * 4 + obecny; d := k; // zapisujemy kostkę na stosie poprzedni := obecny; if not zderzenie then begin dec(dlugosc); case obecny of gora : dec(pozycja.Y); dol : inc(pozycja.Y); lewo : dec(pozycja.X); prawo : inc(pozycja.X); end; case Znak_na_pozycji(pozycja) of ' ' : g.PiszGlowice; // wolne miejsce 'X' : begin // zderzenie z głowicą gracz_bialy.zderzenie := true; gracz_czarny.zderzenie := true; end; else // zderzenie z normalną przeszkodą zderzenie := true; end; end; end; end; // Procedura obsługuje jedną rundę. Wyjście następuje // po przegranej jednego z graczy (lub obu) //------------------------------------------------------ procedure TGra.GrajRunde; var l : integer; begin gracz_czarny.InicjujRunde; gracz_bialy.InicjujRunde; Plansza; l := 0; repeat inc(l); Delay(8); gracz_bialy.CzytajKlawiature; if l = 10 then begin gracz_czarny.Analiza; Ruch(gracz_czarny); end; if l = 20 then begin l := 0; Ruch(gracz_bialy); end; until gracz_bialy.zderzenie or gracz_czarny.zderzenie; PodsumujRunde; end; // Procedura obsługuje całą rozgrywkę //------------------------------------------------------ procedure TGra.Graj; begin repeat StronaTytulowa; gracz_bialy.Inicjuj; gracz_czarny.Inicjuj; repeat GrajRunde; until KoniecRund; until KoniecGry; end; // Program główny //------------------------------------------------------ var gra : TGra; begin gra := TGra.Tworz; gra.Graj; gra.Destroy; end. |
Program uruchomiono w środowisku Dev-C++.
// D O M I N O //-------------------------------------------- // (C)2004 mgr Jerzy Wałaszek I LO w Tarnowie #include <conio.h> #include <windows.h> #include <iostream> #include <iomanip> using namespace std; //---------------------------------------------------- // PROCEDURY I FUNKCJE POMOCNICZE //---------------------------------------------------- const int BLACK = 0; const int BLUE = 1; const int GREEN = 2; const int CYAN = 3; const int RED = 4; const int MAGENTA = 5; const int BROWN = 6; const int LIGHTGRAY = 7; const int DARKGRAY = 8; const int LIGHTBLUE = 9; const int LIGHTGREEN = 10; const int LIGHTCYAN = 11; const int LIGHTRED = 12; const int LIGHTMAGENTA = 13; const int YELLOW = 14; const int WHITE = 15; static int __BACKGROUND = BLACK; static int __FOREGROUND = LIGHTGRAY; // Procedura ustawia pozycję wydruku w oknie konsoli //---------------------------------------------------- void gotoxy(int x, int y) { COORD c; c.X = x - 1; c.Y = y - 1; SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), c); } // Procedura ustawia kolor tła wydruku //---------------------------------------------------- void textbackground(int color) { __BACKGROUND = color; SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), __FOREGROUND + (color << 4)); } // Procedura ustawia kolor tekstu //---------------------------------------------------- void textcolor(int color) { __FOREGROUND = color; SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), color + (__BACKGROUND << 4)); } // Procedura ustawia atrybuty koloru tekstu i tła //---------------------------------------------------- void textattr(int _attr) { SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), _attr); } // Funkcja zwraca aktualną pozycję x kursora //---------------------------------------------------- int wherex() { CONSOLE_SCREEN_BUFFER_INFO info; GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &info); return info.dwCursorPosition.X + 1; } // Funkcja zwraca aktualną pozycję y kursora //---------------------------------------------------- int wherey() { CONSOLE_SCREEN_BUFFER_INFO info; GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &info); return info.dwCursorPosition.Y + 1; } // Procedura czyści zawartość okna konsoli //---------------------------------------------------- void clrscr() { DWORD written; FillConsoleOutputAttribute(GetStdHandle (STD_OUTPUT_HANDLE), __FOREGROUND + (__BACKGROUND << 4), 2000, (COORD){0, 0}, &written); FillConsoleOutputCharacter(GetStdHandle(STD_OUTPUT_HANDLE), ' ', 2000, (COORD){0, 0}, &written); gotoxy(1, 1); } // Procedura ukrywa kursor okienka konsoli //------------------------------------------------------ void CursorOff() { CONSOLE_CURSOR_INFO Info; GetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &Info); Info.bVisible = 0; SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &Info); }; // Procedura przywraca kursor okienka konsoli //------------------------------------------------------ void CursorOn() { CONSOLE_CURSOR_INFO Info; GetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &Info); Info.bVisible = -1; SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &Info); }; // Funkcja PL konwertuje tekst ze standardu Windows 1250 // na standard konsoli znakowej Latin II //------------------------------------------------------ string PL(string s) { int i; char c; for(i = 0; i < s.length(); i++) { switch(s[i]) { case 'ą' : c = char(165); break; case 'ć' : c = char(134); break; case 'ę' : c = char(169); break; case 'ł' : c = char(136); break; case 'ń' : c = char(228); break; case 'ó' : c = char(162); break; case 'ś' : c = char(152); break; case 'ż' : c = char(190); break; case 'ź' : c = char(171); break; case 'Ą' : c = char(164); break; case 'Ć' : c = char(143); break; case 'Ę' : c = char(168); break; case 'Ł' : c = char(157); break; case 'Ń' : c = char(227); break; case 'Ó' : c = char(224); break; case 'Ś' : c = char(151); break; case 'Ż' : c = char(189); break; case 'Ź' : c = char(141); break; default: c = s[i]; }; s[i] = c; }; return(s); } // Procedura centruje w bieżącym wierszu // tekst podany jako parametr //---------------------------------------------------- void Centruj(string t) { gotoxy(1 + (80 - t.length()) / 2, wherey()); cout << t << endl; } // Procedura rysuje pojedynczą ramkę ze znaków // tabelek. Parametry określają współrzędne // lewego górnego i prawego dolnego narożnika //---------------------------------------------------- void Ramka(int xp,int yp,int xk,int yk) { int i; gotoxy(xp,yp); putch(char(218)); gotoxy(xp,yk); putch(char(192)); gotoxy(xk,yp); putch(char(191)); gotoxy(xk,yk); putch(char(217)); for(i = xp + 1; i <= xk - 1; i++) { gotoxy(i,yp); putch(char(196)); gotoxy(i,yk); putch(char(196)); }; for(i = yp + 1; i <= yk - 1; i++) { gotoxy(xp,i); putch(char(179)); gotoxy(xk,i); putch(char(179)); }; } // Procedura wprowadza opóźnienie // o zadaną ilość milisekund //---------------------------------------------------- void Delay(int d) { long start; start = GetTickCount(); while((GetTickCount() - start) < d); } // Funkcja odczytuje znak na pozycji p okna konsoli // Uwaga - znaki ramki będą odczytane nieprawidłowo jako // literki. //------------------------------------------------------ char Znak_na_pozycji(COORD p) { char c; DWORD k; p.X--; p.Y--; ReadConsoleOutputCharacter(GetStdHandle(STD_OUTPUT_HANDLE), &c,1,p,&k); return(c); } // Stałe definiujące kierunek układania kostek domina //------------------------------------------------------ const int gora = 0; const int prawo = 1; const int dol = 2; const int lewo = 3; // Stała definiująca rodzaj znaku kostki domina w zależności // od poprzedniego kierunku układania i bieżącego. //------------------------------------------------------ const char domino[] = " -\\X/\\|/|X/-\\/|\\|"; // Stała definiująca znaki dla walących się kostek domina //------------------------------------------------------ const char upadek[] = " /-/-|\\-\\\\-\\||/|/"; const int MAX_STOS = 840; // Maksymalny rozmiar stosu // Definicje obiektów //------------------------------------------------------ struct TKostka { COORD p; int kod; }; class TStos { private: TKostka s[MAX_STOS+1]; int w; public: void Zapisz(TKostka k); TKostka Czytaj(); void ZerujStos(); int StosPusty(); }; class TGracz : public TStos { public: COORD pozycja; int kolor, obecny, poprzedni, kod, wynik, dlugosc, zderzenie; void Tworz(int k); void Analiza(); void CzytajKlawiature(); void Inicjuj(); void InicjujRunde(); void PiszGlowice(); void PrzewracajKostke(); }; class TGra { private: TGracz gracz_bialy, gracz_czarny; void GrajRunde(); int KoniecGry(); int KoniecRund(); void Plansza(); void PodsumujRunde(); void Ruch(TGracz * g); void StronaTytulowa(); void Wyniki(); public: TGra(); ~TGra(); void Graj(); }; // Metody obiektu TStos //------------------------------------------------------ void TStos::Zapisz(TKostka k) { s[w++] = k; } TKostka TStos::Czytaj() { if(w > 0) w--; return(s[w]); } void TStos::ZerujStos() { w = 0; } int TStos::StosPusty() { return(w == 0); } // Metody obiektu TGracz //------------------------------------------------------ void TGracz::Tworz(int k) { kolor = k; } // Procedura pobiera ze stosu kostkę domina gracza. // Sprawdza, czy jest ustawione pole zderzenie. Jeśli tak, // pobrana kostka zostanie wyswietlona jako przewrócona. //------------------------------------------------------ void TGracz::PrzewracajKostke() { TKostka k; textattr(kolor); k = Czytaj(); // odczyt kostki ze stosu if(zderzenie) { gotoxy(k.p.X,k.p.Y); cout << upadek[k.kod + 1]; }; } // Procedura inicjalizacji danych gracza na początku // rozgrywki. //------------------------------------------------------ void TGracz::Inicjuj() { wynik = 0; } // Procedura analizuje sytuacje komputera i generuje // odpowiednie kierunki ruchu //------------------------------------------------------ void TGracz::Analiza() { int l,i,k[4]; COORD p; if(!zderzenie) { p = pozycja; switch(obecny) { case gora : p.Y--; break; case dol : p.Y++; break; case prawo : p.X++; break; case lewo : p.X--; break; }; if(Znak_na_pozycji(p) != ' ') dlugosc = 0; if(!dlugosc) { dlugosc = 1 + rand() % 10; l = 0; for(i = gora; i <= lewo; i++) { p = pozycja; switch(i) { case gora : p.Y--; break; case dol : p.Y++; break; case prawo : p.X++; break; case lewo : p.X--; break; }; if(Znak_na_pozycji(p) == ' ') k[l++] = i; }; if(l) obecny = k[rand() % l]; }; }; } // Procedura odczytuje stan klawiatury i jeśli naciśnięto // klawisz kursora, zmieniany jest odpowiednio kierunek // układania kostek domina gracza białego //------------------------------------------------------ void TGracz::CzytajKlawiature() { char c; if(kbhit()) { do { c = getch(); } while(c == '\0'); switch(c) { case char(75) : obecny = lewo; break; case char(77) : obecny = prawo; break; case char(72) : obecny = gora; break; case char(80) : obecny = dol; break; }; }; } // Procedura inicjuje wszystkie zmienne rundy // dla danego gracza //------------------------------------------------------ void TGracz::InicjujRunde() { dlugosc = 0; zderzenie = false; ZerujStos(); if(kolor == 0x8f) { obecny = lewo; poprzedni = lewo; pozycja.X = 55; pozycja.Y = 13; } else { obecny = prawo; poprzedni = prawo; pozycja.X = 25; pozycja.Y = 14; }; } // Procedura zapisuje na stosie bieżącą kostkę, a na jej // pozycji rysuje głowicę X //------------------------------------------------------ void TGracz::PiszGlowice() { textattr(kolor); gotoxy(pozycja.X,pozycja.Y); cout << "X"; } // Metody obiektu TGra //------------------------------------------------------ TGra::TGra() { srand((unsigned)time(NULL)); CursorOff(); gracz_czarny.Tworz(0x80); gracz_bialy.Tworz(0x8f); } TGra::~TGra() { textattr(7); CursorOn(); clrscr(); } // Funkcja sprawdza, czy któryś z graczy osiągnął 12 punktów. // Jeśli nie, to zwraca false. Jeśli tak, to wypisuje // informacje o końcu gry i zwraca true. //------------------------------------------------------ int TGra::KoniecRund() { if((gracz_bialy.wynik == 12) ||(gracz_czarny.wynik == 12)) { textattr(0x8f); gotoxy(1,1); Centruj(PL("G-R-A S-K-O-Ń-C-Z-O-N-A")); return(true); } else return(false); } // Funkcja upewnia się, czy gracz chce zakończyć grę w Domino. // Jeśli tak, zwraca true. //------------------------------------------------------ int TGra::KoniecGry() { textattr(0x8e); gotoxy(21,25); cout << "Jeszcze raz ? "; textattr(0x8f); cout << "[T] = Tak, [Inny] = Nie."; return(toupper(getch()) != 'T'); } // Procedura animuje przewracanie kostek domina dla gracza // przegranego (lub obu). Modyfikuje liczbę punktów. //------------------------------------------------------ void TGra::PodsumujRunde() { do { gracz_czarny.PrzewracajKostke(); gracz_bialy.PrzewracajKostke(); Delay(50); } while(!gracz_czarny.StosPusty() || !gracz_bialy.StosPusty()); if(gracz_czarny.zderzenie) gracz_bialy.wynik++; if(gracz_bialy.zderzenie) gracz_czarny.wynik++; Wyniki(); while(kbhit()) { getch(); Delay(100); }; } // Procedura wyświetla bieżącą punktację //------------------------------------------------------ void TGra::Wyniki() { textattr(0x80); gotoxy(20,2); cout << setw(2) << gracz_czarny.wynik; gotoxy(30,2); cout << "<"; textattr(0x8f); gotoxy(61,2); cout << setw(2) << gracz_bialy.wynik; gotoxy(51,2); cout << ">"; } // Procedura wyświetla planszę gry //------------------------------------------------------ void TGra::Plansza() { int i; textbackground(8); clrscr(); textattr(0x80); for(i = 2; i <= 40; i++) { gotoxy(i,3); cout << char(219); gotoxy(i,24); cout << char(219); }; textattr(0x8f); for(i = 41; i <= 79; i++) { gotoxy(i,3); cout << char(219); gotoxy(i,24); cout << char(219); }; for(i = 4; i <= 23; i++) { textattr(0x80); gotoxy(2,i); cout << char(219); textattr(0x8f); gotoxy(79,i); cout << char(219); }; textattr(0x80); gotoxy(38,2); cout << "PUNKTY"; gracz_czarny.PiszGlowice(); gracz_bialy.PiszGlowice(); Wyniki(); } // Procedura wyświetla stronę tytułową, czeka na dowolny // klawisz i czyści ekran //------------------------------------------------------ void TGra::StronaTytulowa() { textbackground(0); clrscr(); gotoxy(1,4); textattr(0x8f); Centruj(PL(" ")); Centruj(PL(" D O M I N O ")); Centruj(PL(" ")); textattr(0x71); Centruj(PL(" ")); Centruj(PL(" (C)2004 mgr Jerzy Wałaszek ")); Centruj(PL(" ")); textattr(0x9f); Centruj(PL(" ")); Centruj(PL(" I Liceum Ogólnokształcące ")); Centruj(PL(" im. Kazimierza Brodzińskiego ")); Centruj(PL(" w Tarnowie ")); Centruj(PL(" ")); textattr(0xf1); Centruj(PL(" ")); Centruj(PL(" Pokonaj komputer w układaniu ")); Centruj(PL(" kostek domina ")); Centruj(PL(" ")); textattr(0xf4); Centruj(PL(" Gdy będziesz gotowy, ")); Centruj(PL(" naciśnij dowolny klawisz ")); Centruj(PL(" ")); textattr(0x0e); Ramka(23,3,58,22); while(getch() == '\0') ; // Oczekiwanie na dowolny klawisz clrscr(); } // Procedura dokonuje ruchu. Jeśli głowica zderza się // z przeszkodą, ustawia pole zderzenie. Jeśli zderzenie // następuje z głowicą drugiego gracza, zostaje ustawione // pole zderzenie w obu rekordach. //------------------------------------------------------ void TGra::Ruch(TGracz * g) { TKostka k; textattr(g->kolor); gotoxy(g->pozycja.X,g->pozycja.Y); cout << domino[g->poprzedni * 4 + g->obecny + 1]; k.p = g->pozycja; k.kod = g->poprzedni * 4 + g->obecny; g->Zapisz(k); // zapisujemy kostkę na stosie g->poprzedni = g->obecny; if(!g->zderzenie) { (g->dlugosc)--; switch(g->obecny) { case gora : (g->pozycja.Y)--; break; case dol : (g->pozycja.Y)++; break; case lewo : (g->pozycja.X)--; break; case prawo : (g->pozycja.X)++; break; }; switch(Znak_na_pozycji(g->pozycja)) { case ' ' : g->PiszGlowice(); break; case 'X' : gracz_bialy.zderzenie = true; gracz_czarny.zderzenie = true; break; default : g->zderzenie = true; break; }; }; } // Procedura obsługuje jedną rundę. Wyjście następuje // po przegranej jednego z graczy (lub obu) //------------------------------------------------------ void TGra::GrajRunde() { int l; gracz_czarny.InicjujRunde(); gracz_bialy.InicjujRunde(); Plansza(); l = 0; do { l++; Delay(8); gracz_bialy.CzytajKlawiature(); if(l == 10) { gracz_czarny.Analiza(); Ruch(&gracz_czarny); }; if(l == 20) { l = 0; Ruch(&gracz_bialy); }; } while(!gracz_bialy.zderzenie && !gracz_czarny.zderzenie); PodsumujRunde(); } // Procedura obsługuje całą rozgrywkę //------------------------------------------------------ void TGra::Graj() { do { StronaTytulowa(); gracz_bialy.Inicjuj(); gracz_czarny.Inicjuj(); do { GrajRunde(); } while(!KoniecRund()); } while(!KoniecGry()); } // Program główny //------------------------------------------------------ int main() { TGra gra; gra.Graj(); return(0); } |
![]() | 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