Advertisement
Guest User

tet.pas

a guest
Nov 23rd, 2014
129
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Pascal 8.02 KB | None | 0 0
  1. {**
  2.  * Pierwsza czesc gry Tetris. Losuje klocki, czyta z wejscia ruchy gracza
  3.  * i wypisuje na wyjscie polecenia przekazania mu komunikatu, umieszczenia
  4.  * klocka na planszy lub pokazania jej stanu.
  5.  *
  6.  * Program nalezy uruchamiac, laczac jego wyjscie za pomoca potoku z wejsciem
  7.  * programu "ris" interpretujacego polecenia.
  8.  *
  9.  * Gracz podaje swoje ruchy w postaci ciagu par znakow, po jednej parze dla
  10.  * kazdego klocka wskazanego przez program. Pierwszym znakiem pary jest
  11.  * litera od 'a' do 'd' okreslajaca obrot klocka a drugim cyfra od '0' do '9'
  12.  * wskazujaca kolumne, w ktorej ma sie znalezc pierwszy skrajnie lewy blok
  13.  * klocka. W przypadku bledu program wskazuje go uzytkownikowi i prosi o
  14.  * ponowne wprowadzenie ruchu.
  15.  *
  16.  * Gra konczy sie, gdy uzytkownik odmowi podania kolejnego ruchu naciskajac ^D.
  17.  * Koniec nastepuje tez w przypadku przegranej. Program "ris" konczy wowczas
  18.  * prace. Gdy program "tet" probuje wyslac do nigo polecenie przez potok, jest
  19.  * przerywany przez system operacyjny.
  20.  *
  21.  * Algorytm losujacy klocki pobiera je z nieskonczonego strumienia, ktorego
  22.  * zawartosc powstaje przez konkatenacje losowych permutacji zbioru wszystkich
  23.  * klockow. Permutacje losujemy za pomoca algorytmu tasowania Knutha.
  24.  *
  25.  * autor: Artur Zaroda <zaroda@mimuw.edu.pl>
  26.  * wersja: 1.0
  27.  * data: 5 listopada 2012
  28.  *}
  29. program tet;
  30.  
  31. const
  32.  
  33.     {**
  34.      * Liczba klockow, ktore w jednym ruchu gracz musi umiescic na planszy.
  35.      *
  36.      * Wartosc tej stalej decyduje o stopniu trudnosci gry. Powinna byc rowna
  37.      * co najmniej 1. Gra staje sie nietrywialna dla wiekszych wartosci.
  38.      *}
  39.     WYMAGANE = 2;
  40.  
  41.     {**
  42.      * Liczba podgladanych klockow.
  43.      *
  44.      * Powinna byc rowna co najmniej 1. Im jest wieksza, tym latwiej wybrac
  45.      * dobry ruch.
  46.      *}
  47.     PODGLADANE = 2 * WYMAGANE - 1;
  48.  
  49.     {**
  50.      * Nazwy klockow.
  51.      *}
  52.     NAZWY = 'IJLOSTZ';
  53.  
  54.     {**
  55.      * Rozmiar zbioru klockow.
  56.      *}
  57.     KLOCKI = 7;
  58.  
  59.     {**
  60.      * Rozmiar tablicy sluzacej do realizacji strumienia klockow.
  61.      *
  62.      * Jest dobrany tak, by mieszczaca sie w niej liczba permutacji
  63.      * wystarczala do podgladania.
  64.      *}
  65.     ROZMIAR = KLOCKI * (1 + (PODGLADANE - 2 + KLOCKI) div KLOCKI);
  66.  
  67.     {**
  68.      * Liczba kolumn na planszy.
  69.      *}
  70.     KOLUMNY = 10;
  71.  
  72. type
  73.  
  74.     {**
  75.      * Reprezentacja losowego strumienia klockow.
  76.      *}
  77.     StrumienKlockow = record
  78.         { bufor cykliczny z klockami }
  79.         zawartosc : array [0 .. ROZMIAR - 1] of Char;
  80.         { pozycja klocka bedacego na poczatku strumienia }
  81.         pozycja : Integer
  82.     end;
  83.  
  84. {**
  85.  * Zamienia wartosci dwoch zmiennych.
  86.  *}
  87. procedure zamien(var x, y : Char);
  88. var z : Char;
  89. begin
  90.     z := x;
  91.     x := y;
  92.     y := z
  93. end;
  94.  
  95. {**
  96.  * Losuje klocek we wskazanym miejscu.
  97.  *}
  98. procedure losuj(var s : StrumienKlockow; i : Integer);
  99. begin
  100.     assert((0 <= i) and (i <= ROZMIAR - 1));
  101.     zamien(s.zawartosc[i],
  102.             s.zawartosc[(i + random(KLOCKI - i mod KLOCKI)) mod ROZMIAR])
  103. end;
  104.  
  105. {**
  106.  * Inicjalizuje strumien klockow.
  107.  *}
  108. procedure przygotuj(var s : StrumienKlockow);
  109. var i : Integer;
  110. begin
  111.     for i := 0 to ROZMIAR - 1 do
  112.         s.zawartosc[i] := NAZWY[1 + i mod KLOCKI];
  113.     for i := 0 to PODGLADANE - 1 do
  114.         losuj(s, i);
  115.     s.pozycja := 0
  116. end;
  117.  
  118. {**
  119.  * Przesuwa sie o jedna pozycje w strumieniu klockow.
  120.  *}
  121. procedure nastepne(var s : StrumienKlockow);
  122. begin
  123.     losuj(s, (s.pozycja + PODGLADANE) mod ROZMIAR);
  124.     s.pozycja := (s.pozycja + 1) mod ROZMIAR
  125. end;
  126.  
  127. {**
  128.  * Odczytuje klocek, znajdujacy sie w strumieniu na pozycji okreslonej drugim
  129.  * argumentem.
  130.  *
  131.  * Pozycje numerujemy od 1.
  132.  *}
  133. function element(const s : StrumienKlockow; i : Integer) : Char;
  134. begin
  135.     assert((1 <= i) and (i <= PODGLADANE));
  136.     element := s.zawartosc[(s.pozycja + i - 1) mod ROZMIAR]
  137. end;
  138.  
  139. {**
  140.  * Okresla wysokosc klocka.
  141.  *}
  142. function wysokosc(k : Char) : Integer;
  143. begin
  144.     case k of
  145.         'I':
  146.             wysokosc := 4;
  147.         'J', 'L':
  148.             wysokosc := 3;
  149.         'O', 'S', 'T', 'Z':
  150.             wysokosc := 2
  151.     end
  152. end;
  153.  
  154. {**
  155.  * Okresla szerokosc klocka.
  156.  *}
  157. function szerokosc(k : Char) : Integer;
  158. begin
  159.     case k of
  160.         'I':
  161.             szerokosc := 1;
  162.         'J', 'L', 'O':
  163.             szerokosc := 2;
  164.         'S', 'T', 'Z':
  165.             szerokosc := 3
  166.     end
  167. end;
  168.  
  169. {**
  170.  * Przekazuje polecenie do drugiej czesci gry.
  171.  *}
  172. procedure przekaz(s : String);
  173. begin
  174.     writeln(s);
  175.     { komunikacja przez potok jest buforowana, wiec trzeba oczyscic bufor }
  176.     flush(output)
  177. end;
  178.  
  179. {**
  180.  * Sprawdza poprawnosc ruchu przekazanego jako argument, dotyczacego klockow
  181.  * znajdujacych sie na poczatku strumienia. Gdy ruch jest poprawny, wynikiem
  182.  * jest 0, w przeciwnym przypadku wynikiem jest pozycja, na ktorej wykryto
  183.  * blad.
  184.  *}
  185. function sprawdz(var s : StrumienKlockow; ruch : String) : Integer;
  186. var
  187.     i, rozmiar, kolumna : Integer;
  188.     ok : Boolean;
  189.     klocek : Char;
  190. begin
  191.     if length(ruch) < 2 * WYMAGANE then
  192.         sprawdz := 1 + length(ruch)
  193.     else if length(ruch) > 2 * WYMAGANE then
  194.         sprawdz := 2 * WYMAGANE + 1
  195.     else begin
  196.         ok := true;
  197.         i := 1;
  198.         while (i <= length(ruch)) and ok do begin
  199.             { poprawnosc obrotu }
  200.             ok := ('a' <= ruch[i]) and (ruch[i] <= 'd');
  201.             if ok then begin
  202.                 klocek := element(s, 1 + i div 2);
  203.                 { sprawdzamy, czy klocek ma byc ulozony pionowo czy poziomo }
  204.                 if (ruch[i] = 'a') or (ruch[i] = 'c') then
  205.                     rozmiar := szerokosc(klocek)
  206.                 else
  207.                     rozmiar := wysokosc(klocek);
  208.                 i := i + 1;
  209.                 { poprawnosc numeru kolumny }
  210.                 ok := ('0' <= ruch[i]) and (ruch[i] <= '9');
  211.                 if ok then begin
  212.                     kolumna := ord(ruch[i]) - ord('0');
  213.                     { sprawdzamy, czy numer kolumny nie jest za duzy }
  214.                     ok := kolumna <= KOLUMNY - rozmiar;
  215.                     if ok then
  216.                         i := i + 1
  217.                 end
  218.             end
  219.         end;
  220.         if ok then
  221.             sprawdz := 0
  222.         else
  223.             sprawdz := i
  224.     end
  225. end;
  226.  
  227. {**
  228.  * Przeprowadza rozgrywke. Losuje klocki, odczytuje ruchy uzytkownika i
  229.  * przekazuje polecenia do drugiej czesci gry.
  230.  *}
  231. procedure graj;
  232. var
  233.     losowe : StrumienKlockow;
  234.     i, j, pozycjaBledu : Integer;
  235.     komunikat, ruch : String;
  236.     koniec : Boolean;
  237. begin
  238.     przygotuj(losowe);
  239.     writeStr(komunikat, '>tet|ris (stopien trudnosci ', WYMAGANE, ')');
  240.     przekaz(komunikat);
  241.     przekaz('>');
  242.     { stan poczatkowy planszy }
  243.     przekaz('');
  244.     koniec := false;
  245.     repeat
  246.         przekaz('>');
  247.         { przygotowanie komunikatu o podgladanych klockach }
  248.         komunikat := '>';
  249.         for i := 1 to PODGLADANE do begin
  250.             komunikat := komunikat + element(losowe, i) + ' ';
  251.             { klocki, ktorych dotyczy aktualny ruch, oddzielamy od reszty }
  252.             if i = WYMAGANE then
  253.                 komunikat := komunikat + 'kolejne: '
  254.         end;
  255.         przekaz(komunikat);
  256.         if eof then
  257.             koniec := true
  258.         else begin
  259.             readln(ruch);
  260.             pozycjaBledu := sprawdz(losowe, ruch);
  261.             if pozycjaBledu <> 0 then begin
  262.                 { ruch nie jest poprawny, wskazujemy miejsce wykrycia bledu }
  263.                 przekaz('>' + stringOfChar(' ', pozycjaBledu - 1) + '^');
  264.                 przekaz('>Blad. Sprobuj jeszcze raz:')
  265.             end else begin
  266.                 { ciag polecen umieszczajacych klocki }
  267.                 for j := 1 to WYMAGANE do begin
  268.                     przekaz(element(losowe, 1) + copy(ruch, 2 * j - 1, 2));
  269.                     nastepne(losowe)
  270.                 end;
  271.                 { jeden wiersz odstepu }
  272.                 przekaz('>');
  273.                 { rysowanie stanu planszy po wykonanym ruchu }
  274.                 przekaz('')
  275.             end
  276.         end
  277.     until koniec
  278. end;
  279.  
  280. begin
  281.     randomize;
  282.     graj
  283. end.
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement