Table of Contents

Poli TicTacToe

Responsabili:

Deadline: 26.11.2018 23:55

Actualizări

Obiective

CITEȘTE!

Tema NU interzice folosirea celorlalte concepte din C care nu sunt menționate mai sus.

Aveți voie să folosiți orice, atâta timp cât respectați convențiile stabilitate la curs/laborator (ex. nu aveți voie cu variabile globale sau goto). Puteți folosi macrouri, pointeri/pointeri la funcții, alocare dinamică, stringuri, structuri, funcții variadice, funcții polimorfice etc dacă vă ajută și le utilizați într-un mod corespunzător. Folosirea greșită se depunctează (ex. alocare dinamică fără eliberare de memorie).

Menționăm că pentru testare (pe vmchecker) se folosește o mașină virtuală pe 32 de biți. În caz că sistemul vostru de operare de pe mașina fizică este pe 64 de biți, sugerăm să faceți testarea finală și pe o mașină (virtuală sau nu) de 32 de biți.

Compilați cu flag-urile din exemplul următor:

gcc -Wall -Wextra -std=c99 main.c -o gigel
  • -Wall -Wextra : Vă arată warning-uri pentru a putea primi indicații suplimentare despre codul vostru (ex. posibile probleme). Va trebui să modificați codul a.i. să nu mai aveți warning-uri.
  • -std=c99 : Din păcate versiunea de compilator de pe vmchecker este foarte veche si are standardul c89 default. Noi folosim c99, de aceea trebuie să adăugați acest flag la compilare.

Sugerăm să citiți cu atenție TOATĂ secțiunea Testare, înainte de a folosi checkerul local.

Enunţ

Gigel și Maria vă propun să jucați o variantă nouă a jocului X și O, care are următoarele reguli: Tabla de joc are dimensiune $ n^2 $ x $ n^2 $ și se numește board. Acesta este împărțit în $n$ x $n$ table mai mici numite miniboard-uri, fiecare având fix $n$ x $n$ elemente (celule). În fiecare miniboard se va desfășura un joc de X și O.

Exemplu: Pentru n = 3, un board are dimensiune $3^2$ x $3^2$ = 9 x 9, iar un miniboard are dimensiune 3 x 3. Acest exemplu este ilustrat în figura de mai jos, unde cele 9 miniboard-uri au fost numerotate de la 0 la 8 (având culori diferite pentru a scoate în evidență celule componente).

Pe acest board se efectuează m mutări de forma: <nume> x y

O astfel de mutare înseamnă că jucătorul cu numele dat alege să seteze elementul de pe poziția (x, y) din board cu X sau 0 (X pentru primul jucător, 0 pentru cel de-al doilea jucător). Ca în orice joc de X și 0, jucătorii trebuie să mute alternativ.

Exemplu - n = 3, m = 9. Dacă șirul de mutări este următorul, atunci se obține board-ul din figura alăturată.

3 9
X 3 1
0 1 2
X 2 3
0 2 4
X 1 3
0 2 2
X 2 1
0 8 8
X 4 7

Task 1 (de la Gigel)

Primul vostru task este să validați aceste mutări verificând și tratând următoarele reguli/cazuri:

Rezultatul produs de task 1 este reprezentat de mesajele de eroare afișate de voi.

00-example.in (Task 1)

00-example.in (Task 1)

Fie un joc cu n = 3. Consirăm 8 mutări.

input output
3 8
X 0 0
0 0 3
X 0 1
0 0 4
X 0 2
0 0 5
0 0 0
X 0 0
NOT YOUR TURN
NOT AN EMPTY CELL







Explicație :

  • Executând pas cu pas, observăm că:
    • mutarea 0 0 0 este invalidă și produce mesajul NOT YOUR TURN
    • mutarea X 0 0 este invalidă și produce mesajul NOT AN EMPTY CELL
      • Se găsește primul element liber parcurgând pe diagonale: $(move_x, move_y) => (1, 1)$
  • Toate celelalte mutări au fost valide și au fost executate așa cum au fost date.

Configurația finală a board-ului este următoarea:

  012 345 678 
0 XXX 000 --- 
1 -X- --- --- 
2 --- --- --- 
 
3 --- --- --- 
4 --- --- --- 
5 --- --- --- 
 
6 --- --- --- 
7 --- --- --- 
8 --- --- ---

Task 2 (de la Maria)

După ce am efectuat cele m mutări de la task 1, Maria dorește să vedem care jucător a câștigat. Pentru aceasta vom introduce un tablou de dimensiune $n$ x $n$, pe care îl vom numi macroboard. Fiecare miniboard va avea o unică celulă asociată în macroboard.

Exemplu - pentru n = 3, asocierea este ilustrată în figura următoare.

După cum am spus anterior, în fiecare miniboard se va desfășura un joc de X și 0 de dimensiune n x n. Într-un miniboard câștigă jucătorul care are cel puțin o linie, o coloană sau o diagonală (cea principală sau cea secundară), plină cu X (pentru jucătorul cu X) sau cu 0 (pentru jucătorul cu 0).

Menționăm că un miniboard este câștigat de primul jucător care face o linie, o coloană sau o diagonală în acest miniboard. Se poate pune în continuare mutări într-un miniboard câștigat, dar acesta rămâne în continuare a celui care l-a câștigat inițial.

Pentru un miniboard câștigat, se va pune X sau 0 în macroaboard, corespunzător jucătorului care a câștigat.

În caz de remiză într-un miniboard, în macroboard se va pune caracterul - (liniuță). Considerăm remiză orice caz în care nu există un câștigător.

După completarea macroboard-ului, care are tot dimensiune $n$ x $n$, aplicăm următoarea regulă: jocul este câștigat de jucătorul care are cel puțin o linie, o coloană sau o diagonală (cea principală sau secundară) plină cu caracterul său în macroboard la finalul jocului.

Menționăm că jocul/macroboard-ul poate fi câștigat de un singur jucător. Acesta se stabilește la finalul execuției celor m mutări!

Pentru a rezolva task 2 se cer următoarele:

00-example.in (Tasks 1 + 2)

00-example.in (Tasks 1 + 2)

Fie un joc cu n = 3. Consirăm 8 mutări.

input output
3 8
X 0 0
0 0 3
X 0 1
0 0 4
X 0 2
0 0 5
0 0 0
X 0 0
NOT YOUR TURN
NOT AN EMPTY CELL
X0-
---’---
Draw again! Let's play darts!



Explicație :

  • Executând pas cu pas, observăm că:
    • mutarea 0 0 0 este invalidă și produce mesajul NOT YOUR TURN
    • mutarea X 0 0 este invalidă și produce mesajul NOT AN EMPTY CELL
      • Se găsește primul element liber parcurgând pe diagonale: $(move_x, move_y) => (1, 1)$
  • Toate celelalte mutări au fost valide și au fost executate așa cum au fost date.
  • Configurația finală pentru BOARD și MACROBOARD se poate vedea mai jos.
    • X a câștigat miniboard-ul 0, iar 0 a câștigat miniboard-ul 1.
    • Întrucât nu există un câștigător în macroboard, jocul s-a terminat remiză.
  012 345 678 
0 XXX 000 --- 
1 -X- --- --- 
2 --- --- --- 
 
3 --- --- --- 
4 --- --- --- 
5 --- --- --- 
 
6 --- --- --- 
7 --- --- --- 
8 --- --- ---
 
     BOARD
     012
   0 X0-
   1 ---
   2 ---
 
 MACROBOARD 

Task 3 (tot de la Gigel)

Deoarece Gigel poate folosi acum rezolvarea voastră să verifice șirul de mutări pe care le face cu Maria și poate determina câștigătorul, el vrea să vă mai dea încă un task greu.

Gigel se întreabă cât de inteligenți au fost ei doi când au generat acest șir de mutări. Probabil că ar fi foarte greu să calculați asta, așa că el dorește să calculați pentru jucătorul X și jucătorul 0 câte un coeficient de atenție, care se definește astfel: attention = numărul de situații în care player a câștigat prin alegerea sa un miniboard raportat la numărul de runde jucate de el.

Pentru a rezolva task 3 se cere să se afișeze 2 linii:

X <attention>
0 <attention>

Dacă nu se poate calcula coeficientul attention pentru un jucător, atunci se va afișa o linie de forma:

<jucator> N/A

00-example.in (Tasks 1 + 2 + 3)

00-example.in (Tasks 1 + 2 + 3)

Fie un joc cu n = 3. Consirăm 8 mutări.

input output
3 8
X 0 0
0 0 3
X 0 1
0 0 4
X 0 2
0 0 5
0 0 0
X 0 0
NOT YOUR TURN
NOT AN EMPTY CELL
X0-
---’---
Draw again! Let's play darts!
X 0.2500000000
0 0.3333333333



Explicație :

  • Executând pas cu pas, observăm că:
    • mutarea 0 0 0 este invalidă și produce mesajul NOT YOUR TURN
    • mutarea X 0 0 este invalidă și produce mesajul NOT AN EMPTY CELL
      • Se găsește primul element liber parcurgând pe diagonale: $(move_x, move_y) => (1, 1)$
  • Toate celelalte mutări au fost valide și au fost executate așa cum au fost date.
  • Configurația finală pentru BOARD și MACROBOARD se poate vedea mai jos.
    • X a câștigat miniboard-ul 0, iar 0 a câștigat miniboard-ul 1.
    • Întrucât nu există un câștigător în macroboard, jocul s-a terminat remiză.
  • Fiecare a câștigat câte un miniboard; X a jucat 4 runde, 0 a jucat 3 runde.
    • $1/4 = 0.2500000000$
    • $1/3 = 0.3333333333$
  012 345 678 
0 XXX 000 --- 
1 -X- --- --- 
2 --- --- --- 
 
3 --- --- --- 
4 --- --- --- 
5 --- --- --- 
 
6 --- --- --- 
7 --- --- --- 
8 --- --- ---
 
     BOARD
     012
   0 X0-
   1 ---
   2 ---
 
 MACROBOARD 

Cerință

Se citesc de la tastatură numerele n,m, apoi cele m mutări. Se cere să se aplice cele m mutări, să se rezolve cele m mutări și să se afișeze în ordine răspunsurile pentru cele 3 task-uri:

Format date de intrare

Prima linie conține numerele n și m despărțite prin câte un spațiu.

Următoarele m linii respectă formatul: un caracter (X sau 0), un spațiu, un număr întreg (x), un spațiu, un număr întreg (y).

Format date de ieșire

Să presupunem că la task 1 se vor detecta q erori, pentru fiecare afișându-se un mesaj. Se va afișa fiecare mesaj pe o linie! (nici un caracter în plus)

Urmează n linii, fiecare conținând câte n caractere. Aceste $n^2 $ elemente reprezintă macroboard-ul.

Următoarea linie conține mesajul prin care se anunță victori sau remiza din jocul curent.

Următoarele 2 linii conțin fiecare: un caracter (X sau O), un spațiu, apoi fie coeficientul de atenție cu fix 10 zecimale, fie mesajul “N/A”.

Restricții și precizări

Exemple

Mai jos se află o listă cu câteva exemple explicate pe scurt.

Toate aceste exemple se găsesc în arhiva de testare check_gigel.zip.

Pentru fiecare exemplu se găsesc:

  • fișierul de intrare (xy-example.in)
  • fișierul de referință (xy-example.ref)
  • un fișier care conține explicații sumare despre ce se îmtâmplă la fiecare pas (xy-example.summary)
  • un fișier care conține, în plus față de summary, stare board-ului la fiecare pas (xy-example.full)

00-example.in

00-example.in

Fie un joc cu n = 3. Consirăm 8 mutări.

00-example.in 00-example.ref
3 8
X 0 0
0 0 3
X 0 1
0 0 4
X 0 2
0 0 5
0 0 0
X 0 0
NOT YOUR TURN
NOT AN EMPTY CELL
X0-
---’---
Draw again! Let's play darts!
X 0.2500000000
0 0.3333333333


Explicație :

  • Executând pas cu pas, observăm că:
    • mutarea 0 0 0 este invalidă și produce mesajul NOT YOUR TURN
    • mutarea X 0 0 este invalidă și produce mesajul NOT AN EMPTY CELL
      • Se găsește primul element liber parcurgând pe diagonale: $(move_x, move_y) => (1, 1)$
  • Toate celelalte mutări au fost valide și au fost executate așa cum au fost date.
  • Configurația finală pentru BOARD și MACROBOARD se poate vedea mai jos.
    • X a câștigat miniboard-ul 0, iar 0 a câștigat miniboard-ul 1.
    • Întrucât nu există un câștigător în macroboard, jocul s-a terminat remiză.
  • Fiecare a câștigat câte un miniboard; X a jucat 4 runde, 0 a jucat 3 runde.
    • $1/4 = 0.2500000000$
    • $1/3 = 0.3333333333$
  012 345 678 
0 XXX 000 --- 
1 -X- --- --- 
2 --- --- --- 
 
3 --- --- --- 
4 --- --- --- 
5 --- --- --- 
 
6 --- --- --- 
7 --- --- --- 
8 --- --- ---
 
     BOARD
     012
   0 X0-
   1 ---
   2 ---
 
 MACROBOARD 

01-example.in

01-example.in

Fie un joc cu n = 4. Consirăm 8 mutări.

00-example.in 00-example.ref
4 8
X 0 0
0 1 0
X 0 1
0 1 1
X 0 2
0 1 2
X 0 3
0 1 3
X---
----
----
’---
Draw again! Let's play darts!
X 0.2500000000
0 0.0000000000


Explicație :

  • Executând pas cu pas, observăm că toate mutările sun valide!
  • Configurația finală pentru BOARD și MACROBOARD se poate vedea mai jos. ATENȚIE! Pentru aliniere in exemplu, coloanele 10, 11, 12, 13, 14, 15 au fost notate cu ultima cifră (0, 1, 2, 3, 4, 5).
    • X a câștigat miniboard-ul 0.
    • Întrucât nu există un câștigător în macroboard, jocul s-a terminat remiză.
  • X a jucat 4 runde (și a câștigat un miniboard), 0 a jucat 4 runde.
    • $1/4 = 0.2500000000$
    • $0/4 = 0.0000000000$
   0123 4567 8901 2345 
 0 XXXX ---- ---- ---- 
 1 0000 ---- ---- ---- 
 2 ---- ---- ---- ---- 
 3 ---- ---- ---- ----  
 
 4 ---- ---- ---- ---- 
 5 ---- ---- ---- ---- 
 6 ---- ---- ---- ---- 
 7 ---- ---- ---- ---- 
 
 8 ---- ---- ---- ---- 
 9 ---- ---- ---- ---- 
10 ---- ---- ---- ---- 
11 ---- ---- ---- ---- 
 
12 ---- ---- ---- ---- 
13 ---- ---- ---- ---- 
14 ---- ---- ---- ---- 
15 ---- ---- ---- ---- 
 
     BOARD
  0123
0 X---
1 ----
2 ----
3 ----
 
 MACROBOARD 

Testare

Testarea temei se va face folosind un script de evaluare automată, ce poate fi găsit în check_gigel.zip.

Compilați cu flag-urile din exemplul următor:

gcc -Wall -Wextra -std=c99 main.c -o gigel
  • -Wall -Wextra : Vă arată warning-uri pentru a putea primi indicații suplimentare despre codul vostru (ex. posibile probleme). Va trebui să modificați codul a.i. să nu mai aveți warning-uri.
  • -std=c99 : Din păcate versiunea de compilator de pe vmchecker este foarte veche si are standardul c89 default. Noi folosim c99, de aceea trebuie să adăugați acest flag la compilare.

Instrucţiuni de utilizare

Menționăm că pentru testare (pe vmchecker) se folosește o mașină virtuală pe 32 de biți. În caz că sistemul vostru de operare de pe mașina fizică este pe 64 de biți, sugerăm să faceți testarea finală și pe o mașină (virtuală sau nu) de 32 de biți.

Exemplu de utilizare:

darius@pc ~ $ ./check.sh

ea să-l rulaţi separat şi să experimentaţi cu el şi alte situaţii.

Testare manuală

Testare manuală

Dacă doriți să testați manual folosind redirectări (fără a introduce de fiecare dată datele de la tastatură), puteți folosi această metodă.

darius@pc ~ $ make build # imi va creea executabilul gigel
 
darius@pc ~ $ ./gigel < tests/in/00-gigel.in # voi rula pe gigel cu inputul din fisierul tests/in/00-gigel.in
                                             # rezultatul se va afisa pe ecran
 
darius@pc ~ $ ./gigel < tests/in/00-gigel.in > out # voi rula pe gigel cu inputul din fisierul tests/in/00-gigel.in
                                                   # rezultatul va fi salvat in fisierul out (pe care pot da cat sau il pot deschide in Sublie)
 
darius@pc ~ $ diff tests/ref/00-gigel.ref out # diff compara linie cu linie cele 2 fisiere
                                              # daca nu afiseaza ceva (erori) atunci sunt indentice
                                              # altfel arata cum este linia in primul fisier si cum arata in al 2lea  
                                              # DACA fisierele au linii mici, se pot compara in paralel (pe coloane), folosind parametrul -y.            

Un exemplu de comparare se află in poza următoare.

Barem corectare

Se pot aplica depunctări suplimentare pentru orice nu respectă standardele stabilite la curs/ laborator (ex. 5 puncte pentru warning-uri de compilare).

Punctajul pe teste este cel acordat pe vmchecker. Echipa de corectare își rezervă dreptul de a depuncta pentru orice încercare de a trece testele fraudulos (de exemplu prin hardcodare).

Punctajul pe README va fi stabilit în urma corectării manuale. Checker-ul doar vă reamintește dacă nu aveți README sau aveți un README gol în arhivă, pentru a submite unul în arhiva finală.

Checker-ul va încerca să detecteze în mod automat cele mai frecvente greșeli de coding style. Dacă checkerul penalizează cu 15p sursa voastră pentru coding style, atunci această decizie este finală . În caz contrar, checkerul nu va scădea puncte pentru coding style, dar la corectarea manuală se pot depuncta pentru lucruri suplimentare precum:

Regulament

Copierea parţială sau totală a unei rezolvări din altă sursă va atrage după sine anularea punctajelor pentru toate temele de casă , atât pentru cel care a copiat, cât şi pentru sursa acestuia.