ajout TP1 presque finis
This commit is contained in:
95
README.md
Normal file
95
README.md
Normal file
@@ -0,0 +1,95 @@
|
||||
# 📘 README – Minimax pour le jeu de Nim
|
||||
|
||||
## 🎯 Objectif
|
||||
Ce TP a pour but d’implémenter l’algorithme **Minimax** dans le jeu de **Nim** (variante à 1 tas où l’on peut retirer 1, 2 ou 3 objets).
|
||||
On développe plusieurs versions de l’algorithme pour comprendre ses optimisations possibles.
|
||||
|
||||
---
|
||||
|
||||
## 📂 Fichiers
|
||||
Le projet contient **4 fichiers Java**, correspondant chacun à une variante de Minimax :
|
||||
|
||||
1. **`MinimaxSimple.java`**
|
||||
- Version de base.
|
||||
- Explore toutes les possibilités jusqu’à la fin de la partie.
|
||||
- Pas d’optimisation → explore parfois plus que nécessaire.
|
||||
|
||||
2. **`MinimaxEarlyStop.java`**
|
||||
- Optimisation par **arrêt anticipé** .
|
||||
- Si un coup gagnant (pour Max) ou perdant (pour Min) est trouvé, la recherche s’arrête immédiatement.
|
||||
- Même résultat que la version simple, mais plus rapide.
|
||||
```bash
|
||||
boutaric@MacBook-James TP1 % time java MinimaxSimple
|
||||
Résultat pour n=8 → -1
|
||||
java MinimaxSimple 0,03s user 0,03s system 49% cpu 0,136 total
|
||||
```
|
||||
```bash
|
||||
boutaric@MacBook-James TP1 % time java MinimaxStop
|
||||
Résultat pour n=7 → 1
|
||||
java MinimaxStop 0,04s user 0,02s system 93% cpu 0,062 total
|
||||
```
|
||||
|
||||
|
||||
3. **`MinimaxProfondeur.java`**
|
||||
- Variante avec **profondeur maximale fixée**.
|
||||
- Quand la profondeur limite est atteinte, on utilise une **fonction d’évaluation heuristique**.
|
||||
- Heuristique utilisée : une position est perdante si `n % 4 == 0`, sinon gagnante.
|
||||
|
||||
4. **`MinimaxMemo.java`**
|
||||
- Optimisation par **mémoïsation**.
|
||||
- Utilise deux tableaux (`memoMax` et `memoMin`) pour stocker les résultats déjà calculés.
|
||||
- Évite les recalculs et accélère l’algorithme pour des valeurs de `n` plus grandes.
|
||||
|
||||
---
|
||||
|
||||
## ▶️ Exécution
|
||||
Compiler et lancer chaque fichier séparément :
|
||||
|
||||
```bash
|
||||
javac MinimaxSimple.java
|
||||
java MinimaxSimple
|
||||
```
|
||||
|
||||
```bash
|
||||
javac MinimaxEarlyStop.java
|
||||
java MinimaxEarlyStop
|
||||
```
|
||||
|
||||
```bash
|
||||
javac MinimaxProfondeur.java
|
||||
java MinimaxProfondeur
|
||||
```
|
||||
|
||||
```bash
|
||||
javac MinimaxMemo.java
|
||||
java MinimaxMemo
|
||||
```
|
||||
|
||||
Chaque programme affiche le résultat pour une valeur donnée de `n` (taille initiale du tas).
|
||||
- `+1` → Position gagnante pour Max (le joueur qui commence).
|
||||
- `-1` → Position perdante pour Max.
|
||||
|
||||
---
|
||||
|
||||
## 📊 Exemple de résultats
|
||||
Pour les premières positions de Nim (1 tas) :
|
||||
|
||||
| n | Résultat | Commentaire |
|
||||
|----|----------|-------------|
|
||||
| 1 | +1 | Max peut tout prendre et gagne |
|
||||
| 2 | +1 | Max peut tout prendre et gagne |
|
||||
| 3 | +1 | Max peut tout prendre et gagne |
|
||||
| 4 | -1 | Position perdante (Min gagne) |
|
||||
| 5 | +1 | Max enlève 1 → reste 4 (perdant pour Min) |
|
||||
| 6 | +1 | Max enlève 2 → reste 4 |
|
||||
| 7 | +1 | Max enlève 3 → reste 4 |
|
||||
| 8 | -1 | Position perdante |
|
||||
| ...| ... | ... |
|
||||
|
||||
---
|
||||
|
||||
## 🧠 Conclusion
|
||||
- Le **Minimax simple** permet de comprendre la logique de base.
|
||||
- Le **Minimax stop** améliore la performance sans changer le résultat.
|
||||
- La **profondeur fixe + heuristique** est utile si l’arbre est trop grand.
|
||||
- La **mémoïsation** accélère énormément le calcul pour des valeurs de `n` élevées.
|
@@ -1,44 +0,0 @@
|
||||
|
||||
public class Minimax {
|
||||
|
||||
public static int pire;
|
||||
public static int res;
|
||||
public static int meilleurRes;
|
||||
|
||||
public static void main(String[] args) {
|
||||
System.out.println(ExploreMin(1));
|
||||
|
||||
}
|
||||
|
||||
public static int ExploreMin(int n){
|
||||
if(n <= 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
pire = 2;
|
||||
|
||||
for (int coups = 1; coups <= 3; coups++) {
|
||||
res = ExploreMax(n - coups);
|
||||
if(res < pire){
|
||||
pire = res;
|
||||
}
|
||||
}
|
||||
|
||||
return pire;
|
||||
}
|
||||
|
||||
public static int ExploreMax(int n){
|
||||
if(n <= 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (int coups = 1; coups <= 3; coups++) {
|
||||
res = ExploreMin(n - coups);
|
||||
if(res > meilleurRes){
|
||||
meilleurRes = res;
|
||||
}
|
||||
}
|
||||
|
||||
return meilleurRes;
|
||||
}
|
||||
}
|
BIN
TP1/MinimaxMemo.class
Normal file
BIN
TP1/MinimaxMemo.class
Normal file
Binary file not shown.
43
TP1/MinimaxMemo.java
Normal file
43
TP1/MinimaxMemo.java
Normal file
@@ -0,0 +1,43 @@
|
||||
public class MinimaxMemo {
|
||||
|
||||
// Minimax avec mémo (on évite de recalculer les mêmes positions)
|
||||
public static Integer[] memoMax;
|
||||
public static Integer[] memoMin;
|
||||
|
||||
public static int exploreMax(int n) {
|
||||
if (n <= 0) return -1;
|
||||
if (memoMax[n] != null) return memoMax[n];
|
||||
|
||||
int meilleur = Integer.MIN_VALUE;
|
||||
for (int coups = 1; coups <= 3; coups++) {
|
||||
int res = exploreMin(n - coups);
|
||||
meilleur = Math.max(meilleur, res);
|
||||
}
|
||||
|
||||
memoMax[n] = meilleur;
|
||||
return meilleur;
|
||||
}
|
||||
|
||||
public static int exploreMin(int n) {
|
||||
if (n <= 0) return +1;
|
||||
if (memoMin[n] != null) return memoMin[n];
|
||||
|
||||
int pire = Integer.MAX_VALUE;
|
||||
for (int coups = 1; coups <= 3; coups++) {
|
||||
int res = exploreMax(n - coups);
|
||||
pire = Math.min(pire, res);
|
||||
}
|
||||
|
||||
memoMin[n] = pire;
|
||||
return pire;
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
int n = 25; // taille du tas initial
|
||||
memoMax = new Integer[n + 1];
|
||||
memoMin = new Integer[n + 1];
|
||||
|
||||
int resultat = exploreMax(n);
|
||||
System.out.println("Résultat pour n=" + n + " → " + resultat);
|
||||
}
|
||||
}
|
BIN
TP1/MinimaxProfondeur.class
Normal file
BIN
TP1/MinimaxProfondeur.class
Normal file
Binary file not shown.
41
TP1/MinimaxProfondeur.java
Normal file
41
TP1/MinimaxProfondeur.java
Normal file
@@ -0,0 +1,41 @@
|
||||
public class MinimaxProfondeur {
|
||||
|
||||
// Minimax avec profondeur fixe
|
||||
public static int PROFONDEUR_MAX = 4;
|
||||
|
||||
public static int exploreMax(int n, int profondeur) {
|
||||
if (n <= 0) return -1;
|
||||
if (profondeur == 0) return evaluer(n);
|
||||
|
||||
int meilleur = Integer.MIN_VALUE;
|
||||
for (int coups = 1; coups <= 3; coups++) {
|
||||
int res = exploreMin(n - coups, profondeur - 1);
|
||||
meilleur = Math.max(meilleur, res);
|
||||
}
|
||||
return meilleur;
|
||||
}
|
||||
|
||||
public static int exploreMin(int n, int profondeur) {
|
||||
if (n <= 0) return +1;
|
||||
if (profondeur == 0) return evaluer(n);
|
||||
|
||||
int pire = Integer.MAX_VALUE;
|
||||
for (int coups = 1; coups <= 3; coups++) {
|
||||
int res = exploreMax(n - coups, profondeur - 1);
|
||||
pire = Math.min(pire, res);
|
||||
}
|
||||
return pire;
|
||||
}
|
||||
|
||||
// Fonction hsimple : perdant si n % 4 == 0
|
||||
public static int evaluer(int n) {
|
||||
return (n % 4 == 0) ? -1 : +1;
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
int n = 8;
|
||||
int profondeur = PROFONDEUR_MAX;
|
||||
int resultat = exploreMax(n, profondeur);
|
||||
System.out.println("Résultat (profondeur fixe) pour n=" + n + " → " + resultat);
|
||||
}
|
||||
}
|
BIN
TP1/MinimaxSimple.class
Normal file
BIN
TP1/MinimaxSimple.class
Normal file
Binary file not shown.
33
TP1/MinimaxSimple.java
Normal file
33
TP1/MinimaxSimple.java
Normal file
@@ -0,0 +1,33 @@
|
||||
public class MinimaxSimple {
|
||||
|
||||
// Max = moi, Min = adversaire
|
||||
// Retourne +1 si Max gagne, -1 si Max perd
|
||||
|
||||
public static int exploreMax(int n) {
|
||||
if (n <= 0) return -1; // défaite pour Max
|
||||
int meilleur = Integer.MIN_VALUE;
|
||||
|
||||
for (int coups = 1; coups <= 3; coups++) {
|
||||
int res = exploreMin(n - coups);
|
||||
meilleur = Math.max(meilleur, res);
|
||||
}
|
||||
return meilleur;
|
||||
}
|
||||
|
||||
public static int exploreMin(int n) {
|
||||
if (n <= 0) return +1; // victoire pour Max
|
||||
int pire = Integer.MAX_VALUE;
|
||||
|
||||
for (int coups = 1; coups <= 3; coups++) {
|
||||
int res = exploreMax(n - coups);
|
||||
pire = Math.min(pire, res);
|
||||
}
|
||||
return pire;
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
int n = 8; // tas initial
|
||||
int resultat = exploreMax(n);
|
||||
System.out.println("Résultat pour n=" + n + " → " + resultat);
|
||||
}
|
||||
}
|
BIN
TP1/MinimaxStop.class
Normal file
BIN
TP1/MinimaxStop.class
Normal file
Binary file not shown.
34
TP1/MinimaxStop.java
Normal file
34
TP1/MinimaxStop.java
Normal file
@@ -0,0 +1,34 @@
|
||||
public class MinimaxStop {
|
||||
|
||||
// Minimax avec détection de victoire immédiate
|
||||
|
||||
public static int exploreMax(int n) {
|
||||
if (n <= 0) return -1;
|
||||
int meilleur = Integer.MIN_VALUE;
|
||||
|
||||
for (int coups = 1; coups <= 3; coups++) {
|
||||
int res = exploreMin(n - coups);
|
||||
if (res == +1) return +1; // victoire immédiate
|
||||
meilleur = Math.max(meilleur, res);
|
||||
}
|
||||
return meilleur;
|
||||
}
|
||||
|
||||
public static int exploreMin(int n) {
|
||||
if (n <= 0) return +1;
|
||||
int pire = Integer.MAX_VALUE;
|
||||
|
||||
for (int coups = 1; coups <= 3; coups++) {
|
||||
int res = exploreMax(n - coups);
|
||||
if (res == -1) return -1; // défaite immédiate pour Max
|
||||
pire = Math.min(pire, res);
|
||||
}
|
||||
return pire;
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
int n = 7;
|
||||
int resultat = exploreMax(n);
|
||||
System.out.println("Résultat pour n=" + n + " → " + resultat);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user