This commit is contained in:
Axel PIETROIS 2024-09-20 14:07:50 +02:00
parent 2230b9cd64
commit 2b114b3d51
19 changed files with 286 additions and 18 deletions

3
.idea/.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
# Default ignored files
/shelf/
/workspace.xml

6
.idea/misc.xml Normal file
View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectRootManager" version="2" project-jdk-name="21" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/out" />
</component>
</project>

8
.idea/modules.xml Normal file
View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/BUT3JeuR5.5.iml" filepath="$PROJECT_DIR$/BUT3JeuR5.5.iml" />
</modules>
</component>
</project>

6
.idea/vcs.xml Normal file
View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="" vcs="Git" />
</component>
</project>

11
BUT3JeuR5.5.iml Normal file
View File

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$" isTestSource="false" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

BIN
MiniMax.class Normal file

Binary file not shown.

View File

@ -1,52 +1,95 @@
public class MiniMax { public class MiniMax {
/*
Variable donnant le nombre d'allumettes au départ du jeu
*/
public static int depart = 5;
// 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 depart = 9099;
private static int[] J1;
private static int[] J2;
private static int compteur;
private static int limite;
public static void main(String[] args) { public static void main(String[] args) {
System.out.println(Nim(depart)); limite = depart;
compteur = 0;
//int n = depart;
J1 = new int[limite + 1];
J2 = new int[limite + 1];
int s = Nim(limite);
System.out.print(limite+" ");
if (s == 1){
System.out.print("Gagné");
} else {
System.out.print("Perdu");
}
System.out.println(" Compteur = "+compteur);
/*
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+" ; ");
*/
} }
/*
Fonction de démarrage du jeu, donner un nombre d'allumettes de démarrage
*/
public static int Nim(int n){ public static int Nim(int n){
return exploreMax(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 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) { 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++){ for (int i=0;allumette>1&&i<3;i++){
allumette--; allumette--;
int v=exploreMin(allumette); int v=exploreMin(allumette);
if (v==1){ if (v > max){
return v; max = v;
} }
} }
return -1; 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 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){ 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++){ for (int i=0;allumette>1&&i<3;i++){
allumette--; allumette--;
int v=exploreMax(allumette); int v=exploreMax(allumette);
if (v==-1){ if (v < min){
return v; min = v;
} }
} }
return 1; J2[n] = min;
return min;
} }
} }

BIN
MiniMaxOptiCarnet.class Normal file

Binary file not shown.

104
MiniMaxOptiCarnet.java Normal file
View File

@ -0,0 +1,104 @@
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 depart = 10000;
private static int[] J1;
private static int[] J2;
private static int compteur;
private static int limite;
public static void main(String[] args) {
limite = 0;
try {
while (true) {
limite++;
compteur = 0;
//int n = depart;
J1 = new int[limite + 1];
J2 = new int[limite + 1];
int s = Nim(limite);
System.out.print(limite+" ");
if (s == 1){
System.out.print("Gagné");
} else {
System.out.print("Perdu");
}
System.out.println(" Compteur = "+compteur);
/*
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+" ; ");
*/
}
} 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;
}
}

22
MiniMaxPetiteOpti.java Normal file
View File

@ -0,0 +1,22 @@
public class MiniMaxPetiteOpti {
public static int depart = 5;
private static int compteur;
public static void main(String[] args) {
int n = depart;
compteur = 0;
int s = Nim(n);
if (s == 1){
System.out.print("Gagné");
} else {
System.out.print("Perdu");
}
System.out.println(" Compteur = "+compteur);
}
public static int Nim(int n){
return exploreMax(n);
}
}

View File

@ -10,3 +10,13 @@ ExplorationMax -> Tour du joueur 1, vérifie si il a un coup permettant de gagne
ExplorationMin -> Tour du joueur 2, vérifie si le joueur 2 perd à coup sûr ExplorationMin -> Tour du joueur 2, vérifie si le joueur 2 perd à coup sûr
Optimisations faites : Si le joueur 1 possède un coup permettant de gagner à coup sûr, la fonction remontera directement pour finir la fonction. Optimisations faites : Si le joueur 1 possède un coup permettant de gagner à coup sûr, la fonction remontera directement pour finir la fonction.
## Optimisation en utilisant le systeme de cahier (MiniMaxOptiCarnet.java)
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, étant à 9099 (sur ma machine).
Cette limite est causée par la limite de récursivité de Java, causant une StackOverflowError.

View File

@ -0,0 +1,3 @@
# Default ignored files
/shelf/
/workspace.xml

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectRootManager" version="2" project-jdk-name="21" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/out" />
</component>
</project>

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/BUT3JeuR5.5.iml" filepath="$PROJECT_DIR$/BUT3JeuR5.5.iml" />
</modules>
</component>
</project>

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="" vcs="Git" />
</component>
</project>

View File

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$" isTestSource="false" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,21 @@
# BUT3JeuR5.5
## Jeu de Nim : MiniMax
Utilisation de deux fonctions récursives pour dire si le premier joueur peut gagner à coup sûr au jeu de Nim
+1 = J1 peut Gagner à coup sur
-1 = J1 peut perdre à coup sur
ExplorationMax -> Tour du joueur 1, vérifie si il a un coup permettant de gagner à coup sûr
ExplorationMin -> Tour du joueur 2, vérifie si le joueur 2 perd à coup sûr
Optimisations faites : Si le joueur 1 possède un coup permettant de gagner à coup sûr, la fonction remontera directement pour finir la fonction.
## Optimisation en utilisant le systeme de cahier (MiniMaxOptiCarnet.java)
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,