/* TP - Attracteurs du tic-tac-toe */ #include <stdio.h> #include <stdlib.h> #include <stdbool.h> #include <assert.h> /* codage des pions : vide : 0, X : 1, O : 2 */ /* Adam joue les X */ /* stockage des informations -3 : le sommet est invalide -2 : partie terminée nulle -1 : partie non terminée qui n'est pas dans l'attracteur 0, 1, 2, 3 ... : plus petit attracteur Ai contenant le sommet */ #define N 19683 // 3^9 int attractA[N]; int attractE[N]; void affiche(int ttt[3][3]){ char symb[3] = {' ', 'X', 'O'}; printf("-------\n"); for (int i = 0; i < 3; i+=1) { for (int j = 0; j < 3; j += 1) { printf("|%c", symb[ttt[i][j]]); } printf("|\n"); } printf("-------\n"); } /* PARTIE 1 - codage / décodage */ int codage(int ttt[3][3]){ // A FAIRE return 0; } void decodage(int c, int ttt[3][3]){ // A FAIRE } void testCodage(){ int ttt[3][3] = {{0,1,1}, {2,0,2}, {0,1,2}}; affiche(ttt); assert(codage(ttt) == 3461); int t[3][3]; decodage(3461, t); affiche(t); for (int i = 0; i < 3; i += 1){ for (int j = 0; j < 3; j += 1){ assert(t[i][j] == ttt[i][j]); } } } /* PARTIE 2 - information sur les plateaux */ bool etatGagnant(int ttt[3][3], int J) { // teste les lignes for (int i = 0; i < 3; i += 1) { if ((ttt[i][0] == J) && (ttt[i][1] == J) && (ttt[i][2] == J)) { return true; } } // teste les colonnes for (int j = 0; j < 3; j += 1) { if ((ttt[0][j] == J) && (ttt[1][j] == J) && (ttt[2][j] == J)) { return true; } } // teste les diagonales if ((ttt[0][0] == J) && (ttt[1][1] == J) && (ttt[2][2] == J)) { return true; } else if ((ttt[0][2] == J) && (ttt[1][1] == J) && (ttt[2][0] == J)) { return true; } else { return false; } } // compte le nombre de 0/1/2 dans la grille void comptage(int ttt[3][3], int* n0, int* n1, int* n2){ // A FAIRE } // initialisation des tableaux attractA et attractE void init(){ // valide les états, et indique les grilles gagnantes for (int i = 0; i < N; i += 1){ int ttt[3][3]; decodage(i, ttt); int n0, n1, n2; // A COMPLETER // ... } } /* PARTIE 3 - calcul des attracteurs */ // calcule l'attracteur Ak : renvoie true si de nouveaux états attracteurs ont été trouvés bool attracK(int attract[N], int J, int K) { bool nouv = false; // nouvel etat détecté ? for (int i = 0; i < N; i += 1) { if (attract[i] == -1){ // A COMPLETER : attract[i] = k ?? } } return nouv; } void attracteurs(){ // A FAIRE } /* PARTIE 4 - Jeu humain vs IA */ void joueIA(int ttt[3][3], int J) { // si on est dans l'attracteur J, on cherche à descendre strictement (position gagnante) // si on est dans l'attracteur adverse, normalement, impossible d'en sortir // si on n'est pas dans un attracteur, normalement, on ne peut pas entrer dans le sien, et il ne faut pas aller dans celui de l'adversaire int c = codage(ttt); int* attract = J == 1 ? attractA : attractE; int* attractAdv = J == 1 ? attractE : attractA; int att = attract[c]; int attv = attractAdv[c]; if (att >= 0) { printf("IA : je vais vous battre en moins de %d coups !\n", att); /* A compléter */ } else if (attv >= 0) { printf("IA : hmm, vous êtes bien parti ... \n"); /* A compléter */ } else { assert((att == -1) && (attv == -1)); printf("IA : c'est serré ... \n"); /* A compléter */ } } /* joue à l'emplacement lig / col */ bool joue(int ttt[3][3], int lig, int col, int J) { if ((lig >= 0) && (lig < 3) && (col >= 0) && (col < 3) && ttt[lig][col] == 0){ ttt[lig][col] = J; return true; } else { return false; } } void joueHumain(int ttt[3][3], int J){ bool ok = false; while (!ok) { int lig, col; printf("A vous : ligne, colonne\n"); if (scanf("%d,%d", &lig, &col) == 2) { ok = joue(ttt, lig, col, J); } else { while (getchar() != EOF); } if (!ok) { printf("Erreur de saisie\n"); } } } void tictactoe() { int ttt[3][3] = {{0,0,0},{0,0,0},{0,0,0}}; int n = 0; // nombre de coups joués int IA = 1; // identité de l'IA printf("Voulez-vous commencer ? (o/n)\n"); char rep; if (scanf("%c", &rep) == 1) { if (rep == 'o') IA = 2; // l'IA joue Eve } int J = 1; // joueur courant while (n < 9) { affiche(ttt); if (J == IA) { joueIA(ttt, J); } else { joueHumain(ttt, J); } if (etatGagnant(ttt, J)) break; J = 3 - J; n += 1; } // fin de partie affiche(ttt); if (etatGagnant(ttt, J)) { if (J == IA) { printf("Victoire IA !\n"); } else { printf("Victoire Humain !\n"); } } else { printf("Match nul ... \n"); } } // fonction principale int main(){ printf("TicTacToe\n"); testCodage(); // Initialisation de attractA et attractE init(); // Statistiques sur les états finaux int nGA = 0; // gagnant pour A int nGE = 0; // gagnant pour E int nN = 0; // partie nulle int nT = 0; // partie valide for (int i = 0; i < N; i += 1){ if (attractA[i] != -3) { nT += 1; } if (attractA[i] == 0) { nGA += 1; } else if (attractE[i] == 0) { nGE += 1; } else if (attractA[i] == -2) { nN += 1; } } printf("N:%d GA:%d GE:%d TOT:%d\n", nN, nGA, nGE, nT); printf("Calcul attracteurs\n"); attracteurs(); // Statistiques sur les attracteurs int cA = 0; // dans l'attracteur de A int cE = 0; // dans l'attracteur de E int cN = 0; // partie valide d'issue incertaine // A COMPLETER printf("N:%d A:%d E:%d TOT:%d\n", cN, cA, cE, cN + cA + cE); // jeu humain / IA // tictactoe(); return 0; }