![]() |
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