test
This commit is contained in:
parent
9862082bf2
commit
f92959247b
81
MiniMax.java
81
MiniMax.java
@ -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;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
BIN
MiniMaxOptiCarnet.class
Normal file
BIN
MiniMaxOptiCarnet.class
Normal file
Binary file not shown.
95
MiniMaxOptiCarnet.java
Normal file
95
MiniMaxOptiCarnet.java
Normal file
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
68
MiniMaxPetiteOpti.java
Normal file
68
MiniMaxPetiteOpti.java
Normal file
@ -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;
|
||||||
|
}
|
||||||
|
}
|
70
MiniMaxSansOpti.java
Normal file
70
MiniMaxSansOpti.java
Normal file
@ -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<min){
|
||||||
|
min = v;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return min;
|
||||||
|
}
|
||||||
|
}
|
36
RapportNim.md
Normal file
36
RapportNim.md
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
# Rapport Jeu de Nim
|
||||||
|
**Membres du groupe :** Axel Pietrois et Simon Saye Babu</br>
|
||||||
|
|
||||||
|
## Avancement
|
||||||
|
La **version de base de Minimax** a été implémentée pour rappel voici son fonctionnement :</br>
|
||||||
|
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. </br>
|
||||||
|
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)
|
Binary file not shown.
@ -1,13 +0,0 @@
|
|||||||
public class AbreNim {
|
|
||||||
|
|
||||||
private Noeud root;
|
|
||||||
|
|
||||||
public AbreNim(int valeur) {
|
|
||||||
this.root = new Noeud(valeur);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Noeud getRoot() {
|
|
||||||
return root;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
Binary file not shown.
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
@ -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;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user