diff --git a/MiniMax.java b/MiniMax.java deleted file mode 100644 index 68d815c..0000000 --- a/MiniMax.java +++ /dev/null @@ -1,81 +0,0 @@ - -public class MiniMax { - - /* - Variable donnant le nombre d'allumettes au départ du jeu (remplacée par un argument en ligne de commande) - */ - public static int depart = 5000; - - private static int[] J1; - private static int[] J2; - - private static int compteur; - - public static void main(String[] args) { - compteur = 0; - int n = depart; - //int n = Integer.parseInt(args[0]); - J1 = new int[n+1]; - J2 = new int[n+1]; - System.out.println(Nim(n)); - System.out.println("J1 : "); - for (int nb: J1) { - System.out.print(nb+" ; "); - } - System.out.println(); - System.out.println("J2 : "); - for (int nb: J2) { - System.out.print(nb+" ; "); - } - System.out.println(); - System.out.println("Compteur : "+compteur); - } - - public static int Nim(int n){ - return exploreMax(n); - } - - /* - Vérifie les issues des coups jouables par le J1 et renvoie 1 si le J1 a une opportunité de gagner a coup sur - */ - public static int exploreMax(int allumette) { - compteur++; - if (J1[allumette] != 0){ - return J1[allumette]; - } - int n = allumette; - for (int i=1;allumette>1&&i<3;i++){ - allumette--; - int v=exploreMin(allumette); - if (v == 1){ - J1[n]=1; - return 1; - } - } - J1[n] = -1; - return -1; - } - - - /* - Vérifie les issues possibles des coups du J2 et renvoie -1 si le J2 a une opportunité de gagner a coup sur - */ - public static int exploreMin(int allumette){ - compteur++; - if (J2[allumette] != 0){ - return J2[allumette]; - } - int n = allumette; - for (int i=0;allumette>1&&i<3;i++){ - allumette--; - int v=exploreMax(allumette); - if (v == -1){ - J2[n]=-1; - return v; - } - } - J2[n] = 1; - return 1; - } - -} \ No newline at end of file diff --git a/MiniMaxOptiCarnet.class b/MiniMaxOptiCarnet.class new file mode 100644 index 0000000..9807dde Binary files /dev/null and b/MiniMaxOptiCarnet.class differ diff --git a/MiniMaxOptiCarnet.java b/MiniMaxOptiCarnet.java new file mode 100644 index 0000000..e132a15 --- /dev/null +++ b/MiniMaxOptiCarnet.java @@ -0,0 +1,95 @@ + +public class MiniMaxOptiCarnet { + + + // J'aime bien les majuscules + public static boolean True = true; + public static boolean False = false; + + /* + Variable donnant le nombre d'allumettes au départ du jeu (remplacée par un argument en ligne de commande) + */ + public static int[] tests = {5,11,17,42,100}; + + private static int[] J1; + private static int[] J2; + + static long debut; + private static int compteur; + private static int limite; + + public static void main(String[] args) { + limite = 0; + try { + for(int n: tests) { + J1 = new int[limite + 1]; + J2 = new int[limite + 1]; + compteur = 0; + debut = System.nanoTime(); + compteur = 0; + System.out.print(n + " allumettes : "); + int s = Nim(n); + if (s == 1) { + System.out.print("Gagné ;"); + } else { + System.out.print("Perdu ;"); + } + long fin = System.nanoTime(); + System.out.print(" Temps écoulé (ms) : "+((fin-debut)/1000000)+" ;"); + System.out.println(" Compteur = " + compteur); + } + } catch (StackOverflowError e){ + } + System.out.println(limite-1); + } + + public static int Nim(int n){ + return exploreMax(n); + } + + /* + Vérifie les issues des coups jouables par le J1 et renvoie 1 si le J1 a une opportunité de gagner a coup sur + Vérifie si le coup a déjà été joué avant de continuer l'arbre, si il verifie l'arbre il ajoute au tableau + */ + public static int exploreMax(int allumette) { + compteur++; + if (J1[allumette] != 0){ + return J1[allumette]; + } + int n = allumette; + int max = -1; + for (int i=0;allumette>1&&i<3;i++){ + allumette--; + int v=exploreMin(allumette); + if (v > max){ + max = v; + } + } + J1[n] = max; + return max; + } + + + /* + Vérifie les issues possibles des coups du J2 et renvoie -1 si le J2 a une opportunité de gagner a coup sur + Vérifie si le coup a déjà été joué avant de continuer l'arbre, si il verifie l'arbre il ajoute au tableau + */ + public static int exploreMin(int allumette){ + compteur++; + if (J2[allumette] != 0){ + return J2[allumette]; + } + int n = allumette; + int min = 1; + for (int i=0;allumette>1&&i<3;i++){ + allumette--; + int v=exploreMax(allumette); + if (v < min){ + min = v; + } + } + J2[n] = min; + return min; + } + +} \ No newline at end of file diff --git a/MiniMaxPetiteOpti.java b/MiniMaxPetiteOpti.java new file mode 100644 index 0000000..92e2c31 --- /dev/null +++ b/MiniMaxPetiteOpti.java @@ -0,0 +1,68 @@ +public class MiniMaxPetiteOpti { + + public static int[] tests = {5,11,17,42,100}; + + private static int compteur; + + static long debut; + + public static void main(String[] args) { + + for(int n: tests) { + debut = System.nanoTime(); + compteur = 0; + System.out.print(n + " allumettes : "); + int s = Nim(n); + if (s == 1) { + System.out.print("Gagné ;"); + } else { + System.out.print("Perdu ;"); + } + long fin = System.nanoTime(); + System.out.print(" Temps écoulé (ms) : "+((fin-debut)/1000000)+" ;"); + System.out.println(" Compteur = " + compteur); + } + } + + public static int Nim(int n){ + return exploreMax(n); + } + + + + /* + Vérifie les issues des coups jouables par le J1 et renvoie 1 si le J1 a une opportunité de gagner a coup sur + */ + public static int exploreMax(int allumette) { + compteur++; + if ((System.nanoTime()-debut)/1000000 > 100000 ){ + System.out.println("TimeOut au bout de 100 secondes"); + System.exit(-1); + } + for (int i=0;allumette>1&&i<3;i++){ + allumette--; + int v=exploreMin(allumette); + if (v==1){ + return v; + } + + } + return -1; + } + + + /* + Vérifie les issues possibles des coups du J2 et renvoie -1 si le J2 a une opportunité de gagner a coup sur + */ + public static int exploreMin(int allumette){ + compteur++; + for (int i=0;allumette>1&&i<3;i++){ + allumette--; + int v=exploreMax(allumette); + if (v==-1){ + return v; + } + } + return 1; + } +} \ No newline at end of file diff --git a/MiniMaxSansOpti.java b/MiniMaxSansOpti.java new file mode 100644 index 0000000..5fec3f4 --- /dev/null +++ b/MiniMaxSansOpti.java @@ -0,0 +1,70 @@ +public class MiniMaxSansOpti { + + public static int[] tests = {5,11,17,42,100}; + + private static int compteur; + + static long debut; + + public static void main(String[] args) { + + for(int n: tests) { + debut = System.nanoTime(); + compteur = 0; + System.out.print(n + " allumettes : "); + int s = Nim(n); + if (s == 1) { + System.out.print("Gagné ;"); + } else { + System.out.print("Perdu ;"); + } + long fin = System.nanoTime(); + System.out.print(" Temps écoulé (ms) : "+((fin-debut)/1000000)+" ;"); + System.out.println(" Compteur = " + compteur); + } + } + + public static int Nim(int n){ + return exploreMax(n); + } + + + + /* + Vérifie les issues des coups jouables par le J1 et renvoie 1 si le J1 a une opportunité de gagner a coup sur + */ + public static int exploreMax(int allumette) { + compteur++; + if ((System.nanoTime()-debut)/1000000 > 100000 ){ + System.out.println("TimeOut au bout de 100 secondes"); + System.exit(-1); + } + int max = -1; + for (int i=0;allumette>1&&i<3;i++){ + allumette--; + int v=exploreMin(allumette); + if (v > max){ + max = v; + } + + } + return max; + } + + + /* + Vérifie les issues possibles des coups du J2 et renvoie -1 si le J2 a une opportunité de gagner a coup sur + */ + public static int exploreMin(int allumette){ + compteur++; + int min = 1; + for (int i=0;allumette>1&&i<3;i++){ + allumette--; + int v=exploreMax(allumette); + if (v + +## Avancement +La **version de base de Minimax** a été implémentée pour rappel voici son fonctionnement :
+Le joueur1 va faire un *exploreMax* de ces coups possible, pour chaque coup, si celui ci n'est pas final la fonction *exploreMin* est lancé sur celui ci. Ensuite *exploreMax* sur les choix de n+1 ainsi de suite, jusqu'a que l'un des joueur tombe sur un coups final ce qui garantie la victoire/la perte de coup.
+Dans exploreMax, si il y a une possibilité de perdre dans une branche elle vaudra -1 si elle est obligatoirement victorieuse elle vaudra 1 et inversement pour exploreMin. +exploreMin represente le meilleur choix du joueur2 (qui est le pire choix pour joueur1 d'ou explore**MIN**). + +### Version avec carnet +Cette optimisation utilise le système de carnet demandé afin de vérifier qu'une seule fois chaque situation. Ainsi, l'algorithme vérifie a chaque fois exactement n*6-17 noeuds, n étant le nombre d'allumettes au démarrage du jeu. Le carnet existe sous la forme de deux tableaux d'entiers, un par joueur. Chaque joueur à n-1 situations car le Joueur 1 ne peut pas se retrouver avec n-1 allumette et le Joueur 2 ne peut pas avoir n allumettes La limite du nombre d'allumettes est de 33736 (testé grace au bloc try/catch lançant en batch). Cependant lorsque le programme est lancé avec une valeur simple, la limite est beaucoup plus basse. + +## Test et comparaison + +### Version non optimisée +5 allumettes : Perdu ; Temps écoulé (ms) : 3 ; Compteur = 15 +11 allumettes : Gagné ; Temps écoulé (ms) : 0 ; Compteur = 600 +17 allumettes : Perdu ; Temps écoulé (ms) : 0 ; Compteur = 23249 +42 allumettes : TimeOut au bout de 100 secondes + +## Version optimisée +5 allumettes : Perdu ; Temps écoulé (ms) : 4 ; Compteur = 15 +11 allumettes : Gagné ; Temps écoulé (ms) : 0 ; Compteur = 228 +17 allumettes : Perdu ; Temps écoulé (ms) : 0 ; Compteur = 5601 +42 allumettes : Gagné ; Temps écoulé (ms) : 7089 ; Compteur = 659108914 +100 allumettes : TimeOut au bout de 100 secondes + +## Version avec carnet +5 allumettes : Perdu ; Temps écoulé (ms) : 3 ; Compteur = 13 +11 allumettes : Gagné ; Temps écoulé (ms) : 0 ; Compteur = 49 +17 allumettes : Perdu ; Temps écoulé (ms) : 0 ; Compteur = 85 +42 allumettes : Gagné ; Temps écoulé (ms) : 0 ; Compteur = 235 +100 allumettes : Gagné ; Temps écoulé (ms) : 0 ; Compteur = 583 + +## Graphique +![Image du graphique](graph.png) \ No newline at end of file diff --git a/testraté/AbreNim.class b/testraté/AbreNim.class deleted file mode 100644 index 5fd7835..0000000 Binary files a/testraté/AbreNim.class and /dev/null differ diff --git a/testraté/AbreNim.java b/testraté/AbreNim.java deleted file mode 100644 index c8ebbb5..0000000 --- a/testraté/AbreNim.java +++ /dev/null @@ -1,13 +0,0 @@ -public class AbreNim { - - private Noeud root; - - public AbreNim(int valeur) { - this.root = new Noeud(valeur); - } - - public Noeud getRoot() { - return root; - } - -} diff --git a/testraté/Etat.java b/testraté/Etat.java deleted file mode 100644 index d29d93a..0000000 --- a/testraté/Etat.java +++ /dev/null @@ -1,17 +0,0 @@ -public class Etat { - private int nb_alumettes; - private int statut; - - public Etat(int nb,int statut){ - this.nb_alumettes = nb; - this.statut = statut; - } - - public int getNb_alumettes() { - return nb_alumettes; - } - - public int getStatut() { - return statut; - } -} \ No newline at end of file diff --git a/testraté/Noeud.class b/testraté/Noeud.class deleted file mode 100644 index 59507a7..0000000 Binary files a/testraté/Noeud.class and /dev/null differ diff --git a/testraté/Noeud.java b/testraté/Noeud.java deleted file mode 100644 index b4978aa..0000000 --- a/testraté/Noeud.java +++ /dev/null @@ -1,22 +0,0 @@ -public class Noeud { - private Integer valeur; - public Noeud[] child = new Noeud[3]; - private int Etat; - - public Noeud(Integer etiquette) { - this.valeur = etiquette; - } - - public int getValeur() - { - return valeur; - } - - public int getEtat(){ - return Etat; - } - - public void setEtat(int newEtat){ - this.Etat = newEtat; - } -} diff --git a/testraté/nim.java b/testraté/nim.java deleted file mode 100644 index 886309b..0000000 --- a/testraté/nim.java +++ /dev/null @@ -1,82 +0,0 @@ -import java.util.ArrayList; -import java.util.List; -import AbreNim; -import Noeud; - -public class nim { - - - public static void main(String[] args) { - AbreNim AN = AbreNim(5); - System.out.println(exploreMax(AN.getRoot())); - } - - /** - * Determine si le joueur gagne ou perd grace a exploreMin. - * @param allumette le nombre d'allumette au tour du joueur - * @return -1 si perdant ou 1 si gagnant - */ - public static boolean exploreMax(Noeud root) { - allumette = root.getValeur(); - allumette -= 3; - for(int i=0;allumette>1&&i<3;i++) { - root.child[i] = new Noeud(allumette); - if (checkEtat(root.child[i])==1) { - return true; - } - allumette++; - } - boolean childtest; - for (int i = 2; i >=0; i--) { - if (root.child[i].getEtat()==0) { - childtest = exploreMin(root.child[i]); - if (childtest) { - return true; - } - } - } - } - - - - /** - * Determine si le joueur gagne ou perd grace a exploreMax. - * @param allumette le nombre d'allumette au tour du joueur - * @return -1 si gagnant ou 1 si perdant - */ - public static boolean exploreMin(Noeud root){ - allumette = root.getValeur(); - allumette -= 3; - for(int i=0;allumette>1&&i<3;i++) { - root.child[i] = new Noeud(allumette); - if (checkEtat(root.child[i])==-1) { - return true; - } - allumette++; - } - boolean childtest = false; - for (int i = 2; i >=0; i--) { - if (root.child[i].getEtat()==0) { - childtest = exploreMax(root.child[i]); - if (childtest) { - return true; - } - } - } - } - - public static int checkEtat(Noeud node){ - if(node.getValeur()<1){ - node.setEtat(-1); - return -1; - } - else if (node.getValeur()==1) { - node.setEtat(1); - return 1; - } - node.setEtat(0); - return 0; - } - - -} \ No newline at end of file