Advertisement
Stranck

Tris

Sep 1st, 2017
299
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 13.86 KB | None | 0 0
  1. #include <iostream>
  2. #include <string>
  3. #include <time.h>
  4. #include <windows.h>
  5. #include <stdlib.h>
  6. #include <time.h>  
  7. using namespace std;
  8.  
  9. //dichiarazione lato della matrice a tutto il programma
  10. char** allocateChar(int x, int y) {
  11.     char **a = new char*[y];
  12.     for(int i = 0; i < y; i++)
  13.         a[i] = new char[x];
  14.     return a;
  15. }
  16. int** allocateInt(int y, int x) {
  17.     int **a = new int*[y];
  18.     for (int i = 0; i < y; i++)
  19.         a[i] = new int[x];
  20.     return a;
  21. }
  22.  
  23. char** cloneChar(char **m, int l, int w) {
  24.     //cout << "Cloning char matrix\n";
  25.     char **ret = allocateChar(l, w);
  26.     for (int y = 0; y < w; y++) {
  27.         for (int x = 0; x < l; x++) {
  28.             ret[x][y] = m[x][y];
  29.         }
  30.     }
  31.     return ret;
  32. }
  33.  
  34. void fillCharMatrix(char **m, int l, char c) {
  35.     for (int i = 0; i < l; i++)
  36.         for (int j = 0; j < l; j++)
  37.             m[i][j] = c;
  38. }
  39.  
  40. bool verifyCoor(int x, int y, char **m) {
  41.     return m[x][y] == '-';
  42. }
  43.  
  44. bool oob(int coor) {
  45.     return coor < 0 || coor > 2;
  46. }
  47.  
  48. //funzione di clear della console
  49. void clear_screen(char fill = ' ') {
  50.     COORD tl = {0,0};
  51.     CONSOLE_SCREEN_BUFFER_INFO s;
  52.     HANDLE console = GetStdHandle(STD_OUTPUT_HANDLE);  
  53.     GetConsoleScreenBufferInfo(console, &s);
  54.     DWORD written, cells = s.dwSize.X * s.dwSize.Y;
  55.     FillConsoleOutputCharacter(console, fill, cells, tl, &written);
  56.     FillConsoleOutputAttribute(console, s.wAttributes, cells, tl, &written);
  57.     SetConsoleCursorPosition(console, tl);
  58. }
  59.  
  60. void tutorial_matrice() {
  61.     //tutorial
  62.     cout << "    [0] [1] [2]" << endl;
  63.     cout << "[0]  -   -   -" << endl;
  64.     cout << "[1]  -   -   -" << endl;
  65.     cout << "[2]  -   -   -" << endl << endl;
  66.  
  67.     //istruzioni
  68.     cout << "Per indicare una posizione inserisci il numero relativo alla riga, premi invio e digita il numero relativo alla colonna, poi premi di nuovo invio" << endl;
  69. }
  70.  
  71. void stampa_matrice(char **m, int l) {
  72.     for (int i = 0; i < l; i++){
  73.         cout << endl;
  74.         for (int j = 0; j < l; j++)
  75.             cout << m[i][j] << "\t";       
  76.     }
  77. }      
  78.  
  79. //funzione di ricerca c su una colonna
  80. int numero_c(char **m, int l, int colonna, char c) {
  81.     int numerox = 0;
  82.     for (int i = 0; i < l; i++)
  83.         if (m[i][colonna] == c) numerox++;
  84.     return numerox;
  85. }
  86.  
  87. //funzione di ricerca c su una riga
  88. int numero_r(char **m, int l, int riga, char c) {
  89.     int numerox = 0;
  90.     for (int i = 0; i < l; i++)
  91.         if (m[riga][i] == c) numerox++;
  92.     return numerox;
  93. }
  94.  
  95. //funzione di ricerca c sulla diagonale principale
  96. int numero_cp(char **m, int l, char c) {
  97.     int numerox = 0;
  98.     for (int i = 0; i < l; i++)
  99.         if (m[i][i] == c) numerox++;
  100.     return numerox;
  101. }
  102.  
  103. //funzione di ricerca c sulla diagonale secondaria
  104. int numero_cs(char **m, int l, char c) {
  105.     int numerox = 0, j = 2;
  106.     for (int i = 0; i < l; i++)
  107.         if (m[i][j--] == c) numerox++;
  108.     return numerox;
  109. }
  110.  
  111. bool fillLine(char **m, int l, char c) {
  112.     bool trovato = false;
  113.  
  114.     for (int k = 0; (k < 3) && !trovato; k++) {
  115.         if (numero_r(m, l, k, c) == 2) //riga
  116.             for (int j = 0; j < l; j++)
  117.                 if (verifyCoor(k, j, m)) {
  118.                     m[k][j] = 'O';
  119.                     trovato = true;
  120.                 }
  121.         if (!trovato && numero_c(m, l, k, c) == 2) //colonna
  122.             for (int j = 0; j < 3; j++)
  123.                 if (verifyCoor(j, k, m)) {
  124.                     m[j][k] = 'O';
  125.                     trovato = true;
  126.                 }
  127.     }
  128.     if (!trovato && (numero_cp(m, l, c) == 2)) //diagonale principale
  129.         for (int j = 0; j < 3 ; j++)
  130.             if (verifyCoor(j, j, m)) {
  131.                 m[j][j] = 'O';
  132.                 trovato = true;
  133.             }
  134.     if (!trovato && (numero_cs(m, l, c) == 2)) { //diagonale secondaria
  135.         int ind = 2;
  136.         for (int controllod = 0; controllod < 3; controllod++) {
  137.             if (verifyCoor(controllod, ind, m)) {
  138.                 m[controllod][ind] = 'O';
  139.                 trovato = true;
  140.             }
  141.             ind--;
  142.         }
  143.     }
  144.     return trovato;
  145. }
  146.  
  147. int getDiagonalCoordinate(int x, int y, int **d) {
  148.     //cout << "Generating diagonal [" << x << ", " << y << "]\n";
  149.     int i = 0, xc, yc;
  150.     for (int xs = -1; xs < 2; xs++) {
  151.         for (int ys = -1; ys < 2; ys++) {
  152.             xc = x + xs;
  153.             yc = y + ys;
  154.             while (!(oob(xc) || oob(yc) || ((xs == 0) && (ys == 0)))) {
  155.                 //cout << xc << "XC " << yc << "YC " << xs << "XS " << ys << "YS\n";
  156.                 d[i][0] = xc;
  157.                 d[i][1] = yc;
  158.                 //cout << " X:" << d[i][0] << " Y:" << d[i][1] << "\n";
  159.                 xc += xs;
  160.                 yc += ys;
  161.                 i++;
  162.             }
  163.         }
  164.     }
  165.     return i;
  166. }
  167.  
  168. int checkCollision(int **d1, int d1length, int **d2, int d2length, int **result) {
  169.     int i = 0;
  170.     //cout << "Checking for collision\n";
  171.     for (int d1c = 0; d1c < d1length; d1c++) {
  172.         for (int d2c = 0; d2c < d2length; d2c++) {
  173.             //cout << d1[d1c][0] << "xd1 " << d2[d2c][0] << "xd2 " << d1[d1c][1] << "yd1 " << d2[d2c][1] << "yd2\n";
  174.             if ((d1[d1c][0] == d2[d2c][0]) && (d1[d1c][1] == d2[d2c][1])) {
  175.                 result[i][0] = d1[d1c][0];
  176.                 result[i][1] = d1[d1c][1];
  177.                 i++;
  178.             }
  179.         }
  180.     }
  181.     return i;
  182. }
  183.  
  184. char **mergePath(char **m, int **p, char c) {
  185.     //cout << "Merging path\n";
  186.     char **ret = cloneChar(m, 3, 3);
  187.     for (int i = 0; i < 3; i++) if (verifyCoor(p[i][0], p[i][1], ret)) ret[p[i][0]][p[i][1]] = c;
  188.     return ret;
  189. }
  190.  
  191. bool pathIsValid(char **m, int **p) {
  192.     //cout << "Checking if path is valid\n";
  193.     char **idealPath = mergePath(m, p, 'O');
  194.     int valid = 0;
  195.     for (int i = 0; i < 3; i++) {
  196.         if ((numero_c(idealPath, 3, i, 'O') == 2) && (numero_c(idealPath, 3, i, 'X') == 0)) valid++;
  197.         if ((numero_r(idealPath, 3, i, 'O') == 2) && (numero_r(idealPath, 3, i, 'X') == 0)) valid++;
  198.     }
  199.     if ((numero_cp(idealPath, 3, 'O') == 2) && (numero_cp(idealPath, 3, 'X') == 0)) valid++;
  200.     if ((numero_cs(idealPath, 3, 'O') == 2) && (numero_cs(idealPath, 3, 'X') == 0)) valid++;
  201.     return valid >= 2;
  202. }
  203.  
  204. bool findThirdPoint(int **p, char **m) {
  205.     int **d1 = allocateInt(8, 2), **d2 = allocateInt(8, 2), **collision = allocateInt(8, 2);
  206.     int d1Length = getDiagonalCoordinate(p[0][0], p[0][1], d1), d2Length = getDiagonalCoordinate(p[1][0], p[1][1], d2);
  207.     int collisionlength = checkCollision(d1, d1Length, d2, d2Length, collision), i = 0;
  208.     bool found = false;
  209.     //cout << "Selecting the third point\n Collision length = " << collisionlength << "\n";
  210.     while (i < collisionlength && !found) {
  211.         if (verifyCoor(collision[i][0], collision[i][1], m)) {
  212.             p[2][0] = collision[i][0];
  213.             p[2][1] = collision[i][1];
  214.             if (pathIsValid(m, p)) {
  215.                 //cout << "Third point [" << p[2][0] << "," << p[2][1] << "]\n";
  216.                 found = true;
  217.             }
  218.         }
  219.         i++;
  220.     }
  221.     return found;
  222. }
  223.  
  224. bool newPath(char **m, int **p) {
  225.     int totalAttemps = 8;
  226.     srand(time(NULL));
  227.     do {
  228.         for (int i = 0; i < 2; i++) {
  229.             do {
  230.                 p[i][0] = rand() % 3;
  231.                 p[i][1] = rand() % 3;
  232.                 //cout << "Placing point " << i << " [" << p[i][0] << ", " << p[i][1] << "]\n";
  233.             } while (!verifyCoor(p[i][0], p[i][1], m));
  234.         }
  235.     } while ((((p[0][0] == p[1][0]) && (p[0][1] == p[1][1])) || !findThirdPoint(p, m)) && (totalAttemps-- > 0));
  236.     return totalAttemps > 0;
  237. }
  238.  
  239. int getPlacedCoordinate(char **m, int **p, char c) {
  240.     //cout << "Getting point already placed\n";
  241.     int i = 0;
  242.     for(int x = 0; x < 3; x++)
  243.         for(int y = 0; y < 3; y++)
  244.             if (m[x][y] == c) {
  245.                 p[i][0] = x;
  246.                 p[i][1] = y;
  247.                 i++;
  248.             }
  249.     return i;
  250. }
  251.  
  252. bool regeneratePath(char **m, int **p, char c) {
  253.     srand(time(NULL));
  254.     int **oldPosition = allocateInt(5, 2);
  255.     int oldPositionLength = getPlacedCoordinate(m, oldPosition, c), totalAttemps = 8;
  256.     //cout << "Regenerating coordinate from " << oldPositionLength << " points\n";
  257.     do {
  258.         if (oldPositionLength <= 2) {
  259.             p[0][0] = oldPosition[0][0];
  260.             p[0][1] = oldPosition[0][1];
  261.             if (oldPositionLength == 1) {
  262.                 p[1][0] = rand() % 3;
  263.                 p[1][1] = rand() % 3;
  264.                 //cout << "p1 [" << p[1][0] << ", " << p[1][1] << "]\n";
  265.             } else {
  266.                 p[1][0] = oldPosition[1][0];
  267.                 p[1][1] = oldPosition[1][1];
  268.             }
  269.         } else {
  270.             int n;
  271.             for (int i = 0; i < 2; i++) {
  272.                 n = rand() % oldPositionLength;
  273.                 p[i][0] = oldPosition[n][0];
  274.                 p[i][1] = oldPosition[n][1];
  275.                 //cout << "p" << i << " [" << p[1][0] << ", " << p[1][1] << "]\n";
  276.             }
  277.         }
  278.     } while ((((p[0][0] == p[1][0]) && (p[0][1] == p[1][1])) || !findThirdPoint(p, m)) && (totalAttemps-- > 0));
  279.     return totalAttemps > 0;
  280. }
  281.  
  282. void placeRandomPoint(char **m, char c) {
  283.     int x, y;
  284.     do {
  285.         x = rand() % 3;
  286.         y = rand() % 3;
  287.     } while (!verifyCoor(x, y, m));
  288.     //cout << "Placing random point [" << x << ", " << y << "]\n";
  289.     m[x][y] = c;
  290. }
  291.  
  292.  
  293. void attacco(char **m, int l, char c, int **path, bool *pathStatus, int *pathIndex) {
  294. //ci pensa sorace
  295.  
  296. //Sorace says: mori.
  297.  
  298.     /*
  299.         (Per creare un nuovo path)
  300.             Controlla se esiste già un path
  301.                 NO: Crea un path
  302.                         Piazza posizione 1 e 2 (Controllando se cella è vuota)
  303.                         Piazza posizione 3 su intersezioni
  304.                             Genera tutte le linee passanti per i punti 1 e 2
  305.                             Trova tutte le intersezioni di queste linee
  306.                             posizione 3 = prima intersezione libera
  307.                         Controlla se è valido
  308.                     Creato un path con successo?
  309.                         SI: Piazza posizione 0
  310.                         NO: Piazza un punto a caso
  311.                 SI: Controlla se è valdo
  312.                         SI: Prova a piazzare posizione pathIndex
  313.                                 La posizione pathIndex è libera?
  314.                                     SI: Piazza
  315.                                 Incrementa pathIndex
  316.                                 Se non è stato piazzato niente ripeti fino a che pathIndex < 2
  317.                                 Se non è stato piazzato ancora niente, piazza un cerchio a caso
  318.                         NO: Ottieni le coordinate di tutti i cerchi già piazzati
  319.                             Genera un nuovo path dai cerchi già piazzati
  320.  
  321.         (Per controllare se è valido)
  322.             Unisce la matrice con il path in una nuova matrice
  323.                 Clona la matrice
  324.                 Piazza coordinate prese dal path solo se la casella è vuota
  325.             Conta per ogni riga/colonna/diagonale se ci sono 2 cerchi e nessuna X
  326.             Se ci sono almeno due "corrispondenze" riguardo a quello che si cercava sopra, il path è valido
  327.  
  328.         (Per rigenerare un path)
  329.             Trova tutti i cerchi piazzati
  330.             Se è stato piazzato un solo cerchio genera la seconda posizione a caso
  331.             Se sono stati piazzati 2 cerchi usali come le prime due posizioni
  332.             Se sono stati piazzati più di 2 cerchi prendine due a caso e usali come prime due posizioni
  333.             Genera la terza posizione
  334.     */
  335.     srand(time(NULL));
  336.     if (!*pathStatus) {
  337.         //cout << "Generating new path\n";
  338.         *pathStatus = newPath(m, path);
  339.         if (*pathStatus) {
  340.             //cout << "Path generated successfully\n";
  341.             m[path[*pathIndex][0]][path[*pathIndex][1]] = c;
  342.             (*pathIndex)++;
  343.         } else placeRandomPoint(m, c);
  344.     } else {
  345.         if (pathIsValid(m, path)) {
  346.             bool b;
  347.             do {
  348.                 b = verifyCoor(path[*pathIndex][0], path[*pathIndex][1], m);
  349.                 if(b) m[path[*pathIndex][0]][path[*pathIndex][1]] = c;
  350.                 (*pathIndex)++;
  351.             } while (!b && (*pathIndex < 3));
  352.             if (!b) placeRandomPoint(m, 'O');
  353.         } else {
  354.             if (regeneratePath(m, path, c)) {
  355.                 if (*pathIndex > 3) *pathIndex = 3;
  356.                 //cout << "Path regenerated successfully\n";
  357.                 m[path[*pathIndex][0]][path[*pathIndex][1]] = c;
  358.             } else placeRandomPoint(m, c);
  359.         }
  360.     }
  361. }
  362.  
  363. int getR() {
  364.     //lettura riga e assegnazione valore posizione
  365.     int input;
  366.     do {
  367.         cout << "Inserisci la riga: ";
  368.         cin >> input;
  369.     } while (oob(input));
  370.     return input;
  371. }
  372. int getC() {
  373.     //lettura colonna e assegnazione valore posizione
  374.     int input;
  375.     do {
  376.         cout << "Inserisci la colonna: ";
  377.         cin >> input;
  378.     } while (oob(input));
  379.     return input;
  380. }
  381.  
  382. void turno_giocatore(char **m, int l, char ch) {
  383.     int r, c;
  384.     cout << endl << endl << "Dove vuoi inserire una '" << ch << "'?" << endl;
  385.  
  386.     do{
  387.         r = getR();
  388.         c = getC();
  389.     }while (!verifyCoor(r, c, m)); 
  390.    
  391.     m[r][c] = ch;
  392.     cout << endl << endl;
  393.     clear_screen ();
  394.     stampa_matrice (m, l);
  395. }
  396.  
  397. bool getPlayerWin(char **m, char c) {
  398.     bool win = false;
  399.     for (int i = 0; (i < 3) && !win; i++) {
  400.         win = win || (numero_c(m, 3, i, c) == 3);
  401.         win = win || (numero_r(m, 3, i, c) == 3);
  402.     }
  403.     win = win || (numero_cp(m, 3, c) == 3);
  404.     return win || (numero_cs(m, 3, c) == 3);
  405. }
  406.  
  407. int partita_IA(char **m, int l) {
  408.     //dichiarazione variabili necessarie
  409.     bool turni = true, pathStatus = false;
  410.     int risultato = 0, caselle_libere = 9, pathIndex = 0;
  411.     int **path = allocateInt(3, 2);
  412.    
  413.     while ((caselle_libere > 0) && (risultato == 0)){
  414.         turni = !turni;
  415.  
  416.         if (turni) { //turno del giocatore
  417.             cout << endl;
  418.             stampa_matrice ( m, l );
  419.             turno_giocatore ( m, l, 'X' );
  420.             if (getPlayerWin(m, 'X')) risultato = 2;
  421.  
  422.         } else { //turno dell'IA
  423.             cout << endl << "Ora tocca alla IA" << endl;
  424.             if (!fillLine(m, l, 'O')) { //he attacc
  425.                 if (!fillLine(m, l, 'X')) //he defense
  426.                     attacco(m, l, 'O', path, &pathStatus, &pathIndex); //but most importantly: he do some doppi giocc
  427.             } else risultato = 1;
  428.         }
  429.         caselle_libere--;
  430.     }
  431.     stampa_matrice(m, l);
  432.     return risultato;  
  433. }
  434.  
  435. // partita 2 giocatori
  436. int partita_G(char **m, int l) {
  437.     bool turno = true;
  438.     int caselle_libere = 9, vittoria = 0;
  439.     stampa_matrice (m, l);
  440.    
  441.     while ((vittoria == 0) && (caselle_libere > 0)){
  442.         turno = !turno;
  443.         cout << "Turno del giocatore: " << turno << endl;
  444.         char c = 'X';
  445.         if (turno) c = 'O';
  446.         turno_giocatore(m, l, c);
  447.         if (getPlayerWin(m, c)) vittoria = turno + 1;
  448.         caselle_libere--;
  449.     }
  450.     return vittoria;
  451. }
  452.  
  453. void main() {
  454.     /*int **d = allocateInt(6, 2);
  455.     getDiagonalCoordinate(0, 1, d);
  456.     return;*/
  457.     //dichiarazione di tutte le variabili necessarie   
  458.     int l = 3, risposta;
  459.     char **m = allocateChar(l, l);
  460.     bool risultato;
  461.     fillCharMatrix(m, l, '-');
  462.  
  463.     //lettura e controllo delle opzioni di gioco
  464.     cout << "Partita a Tris? Contro chi vuoi giocare?" << endl << endl;    
  465.     do{
  466.         cout << "[0] IA" << endl << "[1] Amico" << endl << endl;
  467.         cin >> risposta;
  468.     } while ((risposta != 0) && (risposta != 1));
  469.  
  470.     //stampa della matrice e tutorial
  471.     clear_screen();
  472.     tutorial_matrice();
  473.  
  474.     //in base alla scelta si gioca contro l'avversario scelto      
  475.     switch(risposta) {
  476.         case 0: {
  477.             switch (partita_IA(m, l)) {
  478.                 case 0: {
  479.                     cout << "Parità!\n";
  480.                     break;
  481.                 }
  482.                 case 1: {
  483.                     cout << "Hai perso!\n";
  484.                     break;
  485.                 }
  486.                 case 2: {
  487.                     cout << "Hai vinto!\n";
  488.                     break;
  489.                 }
  490.             }
  491.             break;
  492.         }
  493.         case 1: {
  494.             int result = partita_G(m, l);
  495.             if (result > 0)
  496.                 cout << "Vince giocatore: " << result << endl;
  497.             else
  498.                 cout << "Parità!" << endl;
  499.             break;
  500.         }
  501.     }
  502. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement