Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- {**
- * Pierwsza czesc gry Tetris. Losuje klocki, czyta z wejscia ruchy gracza
- * i wypisuje na wyjscie polecenia przekazania mu komunikatu, umieszczenia
- * klocka na planszy lub pokazania jej stanu.
- *
- * Program nalezy uruchamiac, laczac jego wyjscie za pomoca potoku z wejsciem
- * programu "ris" interpretujacego polecenia.
- *
- * Gracz podaje swoje ruchy w postaci ciagu par znakow, po jednej parze dla
- * kazdego klocka wskazanego przez program. Pierwszym znakiem pary jest
- * litera od 'a' do 'd' okreslajaca obrot klocka a drugim cyfra od '0' do '9'
- * wskazujaca kolumne, w ktorej ma sie znalezc pierwszy skrajnie lewy blok
- * klocka. W przypadku bledu program wskazuje go uzytkownikowi i prosi o
- * ponowne wprowadzenie ruchu.
- *
- * Gra konczy sie, gdy uzytkownik odmowi podania kolejnego ruchu naciskajac ^D.
- * Koniec nastepuje tez w przypadku przegranej. Program "ris" konczy wowczas
- * prace. Gdy program "tet" probuje wyslac do nigo polecenie przez potok, jest
- * przerywany przez system operacyjny.
- *
- * Algorytm losujacy klocki pobiera je z nieskonczonego strumienia, ktorego
- * zawartosc powstaje przez konkatenacje losowych permutacji zbioru wszystkich
- * klockow. Permutacje losujemy za pomoca algorytmu tasowania Knutha.
- *
- * autor: Artur Zaroda <zaroda@mimuw.edu.pl>
- * wersja: 1.0
- * data: 5 listopada 2012
- *}
- program tet;
- const
- {**
- * Liczba klockow, ktore w jednym ruchu gracz musi umiescic na planszy.
- *
- * Wartosc tej stalej decyduje o stopniu trudnosci gry. Powinna byc rowna
- * co najmniej 1. Gra staje sie nietrywialna dla wiekszych wartosci.
- *}
- WYMAGANE = 2;
- {**
- * Liczba podgladanych klockow.
- *
- * Powinna byc rowna co najmniej 1. Im jest wieksza, tym latwiej wybrac
- * dobry ruch.
- *}
- PODGLADANE = 2 * WYMAGANE - 1;
- {**
- * Nazwy klockow.
- *}
- NAZWY = 'IJLOSTZ';
- {**
- * Rozmiar zbioru klockow.
- *}
- KLOCKI = 7;
- {**
- * Rozmiar tablicy sluzacej do realizacji strumienia klockow.
- *
- * Jest dobrany tak, by mieszczaca sie w niej liczba permutacji
- * wystarczala do podgladania.
- *}
- ROZMIAR = KLOCKI * (1 + (PODGLADANE - 2 + KLOCKI) div KLOCKI);
- {**
- * Liczba kolumn na planszy.
- *}
- KOLUMNY = 10;
- type
- {**
- * Reprezentacja losowego strumienia klockow.
- *}
- StrumienKlockow = record
- { bufor cykliczny z klockami }
- zawartosc : array [0 .. ROZMIAR - 1] of Char;
- { pozycja klocka bedacego na poczatku strumienia }
- pozycja : Integer
- end;
- {**
- * Zamienia wartosci dwoch zmiennych.
- *}
- procedure zamien(var x, y : Char);
- var z : Char;
- begin
- z := x;
- x := y;
- y := z
- end;
- {**
- * Losuje klocek we wskazanym miejscu.
- *}
- procedure losuj(var s : StrumienKlockow; i : Integer);
- begin
- assert((0 <= i) and (i <= ROZMIAR - 1));
- zamien(s.zawartosc[i],
- s.zawartosc[(i + random(KLOCKI - i mod KLOCKI)) mod ROZMIAR])
- end;
- {**
- * Inicjalizuje strumien klockow.
- *}
- procedure przygotuj(var s : StrumienKlockow);
- var i : Integer;
- begin
- for i := 0 to ROZMIAR - 1 do
- s.zawartosc[i] := NAZWY[1 + i mod KLOCKI];
- for i := 0 to PODGLADANE - 1 do
- losuj(s, i);
- s.pozycja := 0
- end;
- {**
- * Przesuwa sie o jedna pozycje w strumieniu klockow.
- *}
- procedure nastepne(var s : StrumienKlockow);
- begin
- losuj(s, (s.pozycja + PODGLADANE) mod ROZMIAR);
- s.pozycja := (s.pozycja + 1) mod ROZMIAR
- end;
- {**
- * Odczytuje klocek, znajdujacy sie w strumieniu na pozycji okreslonej drugim
- * argumentem.
- *
- * Pozycje numerujemy od 1.
- *}
- function element(const s : StrumienKlockow; i : Integer) : Char;
- begin
- assert((1 <= i) and (i <= PODGLADANE));
- element := s.zawartosc[(s.pozycja + i - 1) mod ROZMIAR]
- end;
- {**
- * Okresla wysokosc klocka.
- *}
- function wysokosc(k : Char) : Integer;
- begin
- case k of
- 'I':
- wysokosc := 4;
- 'J', 'L':
- wysokosc := 3;
- 'O', 'S', 'T', 'Z':
- wysokosc := 2
- end
- end;
- {**
- * Okresla szerokosc klocka.
- *}
- function szerokosc(k : Char) : Integer;
- begin
- case k of
- 'I':
- szerokosc := 1;
- 'J', 'L', 'O':
- szerokosc := 2;
- 'S', 'T', 'Z':
- szerokosc := 3
- end
- end;
- {**
- * Przekazuje polecenie do drugiej czesci gry.
- *}
- procedure przekaz(s : String);
- begin
- writeln(s);
- { komunikacja przez potok jest buforowana, wiec trzeba oczyscic bufor }
- flush(output)
- end;
- {**
- * Sprawdza poprawnosc ruchu przekazanego jako argument, dotyczacego klockow
- * znajdujacych sie na poczatku strumienia. Gdy ruch jest poprawny, wynikiem
- * jest 0, w przeciwnym przypadku wynikiem jest pozycja, na ktorej wykryto
- * blad.
- *}
- function sprawdz(var s : StrumienKlockow; ruch : String) : Integer;
- var
- i, rozmiar, kolumna : Integer;
- ok : Boolean;
- klocek : Char;
- begin
- if length(ruch) < 2 * WYMAGANE then
- sprawdz := 1 + length(ruch)
- else if length(ruch) > 2 * WYMAGANE then
- sprawdz := 2 * WYMAGANE + 1
- else begin
- ok := true;
- i := 1;
- while (i <= length(ruch)) and ok do begin
- { poprawnosc obrotu }
- ok := ('a' <= ruch[i]) and (ruch[i] <= 'd');
- if ok then begin
- klocek := element(s, 1 + i div 2);
- { sprawdzamy, czy klocek ma byc ulozony pionowo czy poziomo }
- if (ruch[i] = 'a') or (ruch[i] = 'c') then
- rozmiar := szerokosc(klocek)
- else
- rozmiar := wysokosc(klocek);
- i := i + 1;
- { poprawnosc numeru kolumny }
- ok := ('0' <= ruch[i]) and (ruch[i] <= '9');
- if ok then begin
- kolumna := ord(ruch[i]) - ord('0');
- { sprawdzamy, czy numer kolumny nie jest za duzy }
- ok := kolumna <= KOLUMNY - rozmiar;
- if ok then
- i := i + 1
- end
- end
- end;
- if ok then
- sprawdz := 0
- else
- sprawdz := i
- end
- end;
- {**
- * Przeprowadza rozgrywke. Losuje klocki, odczytuje ruchy uzytkownika i
- * przekazuje polecenia do drugiej czesci gry.
- *}
- procedure graj;
- var
- losowe : StrumienKlockow;
- i, j, pozycjaBledu : Integer;
- komunikat, ruch : String;
- koniec : Boolean;
- begin
- przygotuj(losowe);
- writeStr(komunikat, '>tet|ris (stopien trudnosci ', WYMAGANE, ')');
- przekaz(komunikat);
- przekaz('>');
- { stan poczatkowy planszy }
- przekaz('');
- koniec := false;
- repeat
- przekaz('>');
- { przygotowanie komunikatu o podgladanych klockach }
- komunikat := '>';
- for i := 1 to PODGLADANE do begin
- komunikat := komunikat + element(losowe, i) + ' ';
- { klocki, ktorych dotyczy aktualny ruch, oddzielamy od reszty }
- if i = WYMAGANE then
- komunikat := komunikat + 'kolejne: '
- end;
- przekaz(komunikat);
- if eof then
- koniec := true
- else begin
- readln(ruch);
- pozycjaBledu := sprawdz(losowe, ruch);
- if pozycjaBledu <> 0 then begin
- { ruch nie jest poprawny, wskazujemy miejsce wykrycia bledu }
- przekaz('>' + stringOfChar(' ', pozycjaBledu - 1) + '^');
- przekaz('>Blad. Sprobuj jeszcze raz:')
- end else begin
- { ciag polecen umieszczajacych klocki }
- for j := 1 to WYMAGANE do begin
- przekaz(element(losowe, 1) + copy(ruch, 2 * j - 1, 2));
- nastepne(losowe)
- end;
- { jeden wiersz odstepu }
- przekaz('>');
- { rysowanie stanu planszy po wykonanym ruchu }
- przekaz('')
- end
- end
- until koniec
- end;
- begin
- randomize;
- graj
- end.
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement