1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168
| #include <conio2.h>
#include <vector>
#define MIN(a, b) a < b ? a : b
#define MAX(a, b) a > b ? a : b
#define MAX_VAL 2
using namespace std;
void printGame(vector<int> game);
int findWinner(vector<int> game);
int humanChoice(vector<int> game);
vector<int> minimax(vector<int> game);
int mini(vector<int> game);
int maxi(vector<int> game);
int possibleChoices(vector<int> game);
vector<int> play(vector<int> game, int choice);
int value(vector<int> game);
int main()
{
int player = 1, winner = 0; // L'humain commence et il n'y a aucun gagnant
vector<int> game(9, 0); // On a un jeu vide au départ
printGame(game); // On affiche le jeu
do
{
if(player == 1) game[humanChoice(game)] = 1; // On récupère le coup de l'humain si c'est à lui de jouer
else game = minimax(game); // On récupère le coup de l'IA si c'est à elle de jouer
printGame(game); // On actualise l'affichage du jeu
player = player == 1 ? 2 : 1; // C'est maintenant à l'autre de jouer
}
while(!(winner = findWinner(game))); // On boucle tant que le jeu n'est pas fini
switch(winner) // Affichage des résultats
{
case -1 : cputsxy(1, 5, "NUL"); break;
case 1 : cputsxy(1, 5, "!1!"); break;
case 2 : cputsxy(1, 5, "!2!"); break;
}
getch();
return 0;
}
void printGame(vector<int> game) // Affiche le jeu
{
for(int i = 0; i < 9; i++) gotoxy(i % 3 + 1, i / 3 + 1), putch(game[i] == 0 ? i + 49 : game[i] == 1 ? 'X' : 'O');
}
int findWinner(vector<int> game) // Détermine si l'humain gagne, si l'IA gagne, si le jeu est fini ou en cours
{
for(int i = 1; i <= 2; i++)
{
if(game[0] == i && game[1] == i && game[2] == i) return i;
if(game[3] == i && game[4] == i && game[5] == i) return i;
if(game[6] == i && game[7] == i && game[8] == i) return i;
if(game[0] == i && game[3] == i && game[6] == i) return i;
if(game[1] == i && game[4] == i && game[7] == i) return i;
if(game[2] == i && game[5] == i && game[8] == i) return i;
if(game[0] == i && game[4] == i && game[8] == i) return i;
if(game[2] == i && game[4] == i && game[6] == i) return i;
}
for(int i = 0; i < 9; i++) if(game[i] == 0) return 0;
return -1;
}
int humanChoice(vector<int> game) // Récupère le coup de l'humain
{
while(1)
{
int c = getch();
if(c > 48 && c < 58) if(game[c - 49] == 0) return c - 49;
}
}
vector<int> minimax(vector<int> game)
{
vector<int> bestChoice(9, 0); // Futur jeu choisis
int maxime = -MAX_VAL; // Valeur minimale au départ
for(int i = 0; i < possibleChoices(game); i++) // Pour tous les coups suivants possibles
{
vector<int> choice = play(game, i); // On représente le coup possible
int val = mini(choice); // On calcul sa valeur
if(val > maxime) maxime = val, bestChoice = choice; // Si sa valeur est supérieure à l'anciene, on enregistre le coup comme étant le meilleur
}
return bestChoice; // On retourne le meilleur coup déterminé
}
int mini(vector<int> game)
{
int finished = 1;
for(int i = 0; i < 9; i++) if(game[i] == 0) { finished = 0; break; } // On détermine si le coup est terminal
if(finished) return value(game); // Si le coup est terminali, on retourne sa valeur
int valMin = MAX_VAL; // Sinon on initie sa valeur au maximum
for(int i = 0; i < possibleChoices(game); i++) // Pour tous les coups suiants possibles
{
vector<int> choice = play(game, i); // On représente le coup possible
int valChoice = maxi(choice); // On calcul sa valeur
valMin = min(valMin, valChoice); // On enregistre sa valeur si elle est inférieure à l'ancienne
}
return valMin; // On retourne la valeur mini du coup
}
int maxi(vector<int> game)
{
int finished = 1;
for(int i = 0; i < 9; i++) if(game[i] == 0) { finished = 0; break; } // On détermine si le coup est terminal
if(finished) return value(game); // Si le coup est terminali, on retourne sa valeur
int valMax = -MAX_VAL; // Sinon on initie sa valeur au maximum
for(int i = 0; i < possibleChoices(game); i++) // Pour tous les coups suiants possibles
{
vector<int> choice = play(game, i); // On représente le coup possible
int valChoice = mini(choice); // On calcul sa valeur
valMax = max(valMax, valChoice); // On enregistre sa valeur si elle est inférieure à l'ancienne
}
return valMax; // On retourne la valeur maxi du coup
}
int possibleChoices(vector<int> game) // Compte le nombres de coups suivants possibles à jouer
{
int count = 0;
for(int i = 0; i < 9; i++) if(game[i] == 0) count++;
return count;
}
vector<int> play(vector<int> game, int choice) // Donne une représentation du jeu avec le coup suivant joué dans la case choisie (choice)
{
int a = 0, b = 0, count = -1;
vector<int> newGame(9, 0);
for(int i = 0; i < 9; i++)
{
if(game[i] == 1) a++;
if(game[i] == 2) b++;
}
for(int i = 0; i < 9; i++)
{
newGame[i] = game[i];
if(game[i] == 0)
{
count++;
if(count == choice) newGame[i] = (a == b ? 1 : 2);
}
}
return newGame;
}
int value(vector<int> game) // Retourne 1 si le dernier joueur qui a joué a gagné, -1 si il a perdu, 0 si il y a nul
{
int a = 0, b = 0, winner = findWinner(game);
if(winner == -1) return 0;
for(int i = 0; i < 9; i++)
{
if(game[i] == 1) a++;
if(game[i] == 2) b++;
}
if(a == b)
{
if(winner == 1) return 1;
else return -1;
}
else
{
if(winner == 1) return -1;
else return 1;
}
} |
Partager