Commit f3a350ca authored by Le noob du 53's avatar Le noob du 53
parents 6374560e 0015d4b3
#Project Monitoring : TicTacToe groupe 3 #Project Monitoring :
=====================
Projet : TicTacToe
N° Groupe : 3
Groupe : Louis Bahrman, Bruce Hersemeule, Timothy Laird, Théo Delbecq
#Briques fonctionelles #Briques fonctionelles
----------------------
|Nom |Description |Séance |Responsable |Commit |Nom |Description |Séance |Responsable |Commit |Etat |Commentaires
|:--- |:--- |:--- |:--- |:--- |:--- |:--- |:--- |:--- |:--- |:--- |:---
|Fraction |Structure de fraction pour les arbres MCTS|20/04/2020|Louis|f159fbc27aafe0f3e7fd85a7e53024dbe748e191 |Prise en main |Formation du groupe, choix du projet, lecture des documents, installation des environnements java requis, découverte du code fourni et tests de ses fonctionnalités |30/03/2020 |Tous | |Fini |
|Arbre générique|Structure d'arbre commune aux 2 algorithmes|20/04/2020|Bruce|3415d259df15dea293f5d45a6541a75b5c690c27 |Mise en place du dépôt |Création du dépôt, clonage en local et création de branches individuelles |30/03/2020 |Louis |7b8fed5436e8048c51c02041374defd4c5022e32 |Fini |[url du dépôt](https://gvipers.imt-lille-douai.fr/louis.bahrman/groupe3-tictactoe/tree/master)
|Arbre MCTS | |Apprentissage git |Apprentissage des commandes et des méthodes d'utilisation de git |31/03/2020 |Tous | |En cours |
|Arbre MinMax |Structure d'arbre pour MinMax|21/04/2020|Bruce|b599e9988c324c551aa4e4cdb9a95cd327db1b99 |Fraction |Structure de fraction pour les arbres MCTS|20/04/2020|Louis|f159fbc27aafe0f3e7fd85a7e53024dbe748e191 |Fini |
\ No newline at end of file |Arbre générique|Structure d'arbre commune aux 2 algorithmes|20/04/2020|Bruce|3415d259df15dea293f5d45a6541a75b5c690c27 |Fini |
|Arbre MCTS |Structure d'abre et méthodes spécifiques à l'algo MCTS |20/04/2020 |Louis, Timothy | |En cours |
|Generator |Générateur de fin de partie aléatoire permettant d'estimer la valeur d'un coup par estimation statistique |20/04/2020 |Théo |ad4f63446c6a351028d7fd923a379fc4dc327715 |Fini |
|Arbre MinMax |Structure d'arbre pour MinMax et algo de remontée|21/04/2020|Bruce|b599e9988c324c551aa4e4cdb9a95cd327db1b99 |Fini |
|AlgoRechercheMinMax |Algo de recherche créant un arbre des coups de la profondeur souhaitée pour un joueur et attribuant une valeur à chaque coup selon l'algo du MinMax |21/04/2020 |Théo |60b5f5a77e617c392e1c855ffaa64c557606c6a0 |A tester |
|AlgoRechercheMCTS |Algo de création et parcours d'arbre des coups et recherche selon l'algo de Monte-Carlo |21/04/2020 |Louis, Timothy | |En cours |
|Monitoring |Création du monitoring, plannification et enregistrement des briques fonctionnelles du projet dans le fichier monitoring |21/04/2020 |Tous |22e9f32af8ad851db7a0deedb1c0299fe471ecfd |En cours |
|Tests locaux et correction |Tests des performances des différents algo en local et correction en commun |27/04/2020 |Tous | |A venir |
|Mise en place CodinGame |Conversion du code et mise en place des tests sur la plateforme CodinGame |27/04/2020 |Tous | |A venir |
\ No newline at end of file
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package tictactoecodingame;
import java.util.ArrayList;
/**
*
* @author senda
public class AlgoRecherMinMax1 extends AlgoRecherche {
ArrayList ListCoup;
/*public AlgoRecherMinMax1() {
}
@Override
public Coup meilleurCoup(Plateau _plateau, Joueur _joueur, boolean _ponder) {
ListCoup = _plateau.getListeCoups(_joueur);
return ;
}
}*/
/* L'idée c'est :
- Créer un arbre de coups :
On récupère les coups dispo
On fait toutes les possibilités d'enchaînement de coups (<N, <MaxCoupsRestants)
- On applique MinMax
- On rend le meilleur coup selon notre algorythme
*/
\ No newline at end of file
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package tictactoecodingame;
import java.util.ArrayList;
/**
*
* @author Théo
*/
public class AlgoRechercheMinMax extends AlgoRecherche{
/*La profondeur de recherche demandée doit être supérieure à 1 et inférieure
à 98 (On commence à 0 et l'emplacement 99 est utilisée par le générateur),
en pratique la croissance est factorielle en mémoire donc en ne dépassera pas 10*/
private int depth;
private Plateau plateau;
private Joueur target;
private Joueur opponent;
private int d_gen;
public AlgoRechercheMinMax(int depth, int d_gen, Joueur joueur1, Joueur joueur2){
this.depth = depth;
this.d_gen = d_gen;
//Cet algo ne marche qu'avec des jeux à deux joueurs
target = joueur1;
opponent = joueur2;
}
public void setRandGenDepth(int d_gen){
this.d_gen = d_gen;
}
public void setDepth(int depth){
this.depth = depth;
}
public void setPlayers(Joueur joueur1, Joueur joueur2){
target = joueur1;
opponent = joueur2;
}
public int getRandGenDepth(int d_gen){
return d_gen;
}
public int getDepth(int depth){
return depth;
}
public Joueur[] getPlayers(Joueur joueur1, Joueur joueur2){
Joueur[] players = {target, opponent};
return players;
}
public Coup meilleurCoup( Plateau _plateau , Joueur _joueur , boolean _ponder ){
//On part du principe que la partie n'est pas terminée donc qu'il reste au moins un coup
plateau = _plateau;
plateau.sauvegardePosition(0);
if(target != _joueur){
opponent = target;
target = _joueur;
}
ArbreMinMax explore = new ArbreMinMax();
builder(explore, target, 0);
explore.MinMax(0);
int m = Integer.MIN_VALUE;
Coup c = null;
for(int i = 0; i < explore.getfils().size() ; i++){
int n = explore.getfils().get(i).getvalue();
if(n > m){
m = n;
c = explore.getfils().get(i).getcoup();
}
}
plateau.restaurePosition(0);
return c;
}
//Fonction auxiliaire récursive de création de l'arbre des coups possibles
private void builder(ArbreMinMax t,Joueur currentJoueur, int currentDepth){
//On commence par mettre le plateau à jour en fonction du coup théorique joué
if(currentDepth == 0){
plateau.restaurePosition(0);
}
else{
plateau.restaurePosition(currentDepth-1);
plateau.joueCoup(t.getcoup());
plateau.sauvegardePosition(currentDepth);
}
//On crée les nouveau noeuds à partir des coups disponible du point de vue du joueur à ce niveau de l'arbre
ArrayList<Coup> coups = plateau.getListeCoups(currentJoueur);
if(plateau.partieTerminee()){
Joueur winner = plateau.vainqueur();
if(winner == target){
t.setvalue(1);
}
else if(winner == opponent){
t.setvalue(-1);
}
else {
t.setvalue(0);
}
}
else if (currentDepth == depth){
int c = Generator.random_tests(plateau, d_gen, target);
t.setvalue(c);
}
else{
ArrayList<ArbreMinMax> fils = new ArrayList<ArbreMinMax>();
for(int i=0; i<coups.size();i++){
ArbreMinMax a = new ArbreMinMax(coups.get(i));
if(currentJoueur == target){
builder(a, opponent,currentDepth + 1);
}
else {
builder(a, target,currentDepth + 1);
}
fils.add(a);
}
t.setfils(fils);
}
}
}
...@@ -11,61 +11,63 @@ import java.util.ArrayList; ...@@ -11,61 +11,63 @@ import java.util.ArrayList;
* *
* @author senda * @author senda
*/ */
public class Arbre { public class ArbreMCTS {
public static int N = 5;
protected Fraction value;
protected ArrayList<Coup> coups;
protected ArrayList<Arbre> fils;
// Les constructeurs : private Fraction value;
private ArrayList<Coup> coups;
public Arbre(){ private ArrayList<ArbreMCTS> fils;
}
public Arbre (Fraction value, ArrayList coups, ArrayList fils){ // Les constructeurs :
public ArbreMCTS (Fraction value, ArrayList coups, ArrayList fils){
this.value = value; this.value = value;
this.fils = fils; this.fils = fils;
this.coups = coups; this.coups = coups;
} }
public Arbre (int num, int den, ArrayList coups, ArrayList fils){
public ArbreMCTS (int den, int num, ArrayList coups, ArrayList fils){
this.value.den = den; this.value.den = den;
this.value.num = num; this.value.num = num;
this.fils = fils; this.fils = fils;
this.coups = coups; this.coups = coups;
} }
public Arbre (Fraction value, Plateau _plateau, Joueur _joueur){ public ArbreMCTS (Fraction value, Plateau _plateau, Joueur _joueur){
this.value = value; this.value = value;
this.coups = _plateau.getListeCoups(_joueur) ; this.coups = _plateau.getListeCoups(_joueur) ;
int a = coups.size(); int a = coups.size();
fils = new ArrayList(); fils = new ArrayList();
for(int i = 0; i < a ; i++){ for(int i = 0; i < a ; i++){
Arbre Arbre_i = new Arbre(new Fraction()); // Attention ! Ce constructeur initialise donc avec des valeurs nulles en racine ! ArbreMCTS Arbre_i = new ArbreMCTS(new Fraction()); // Attention ! Ce constructeur initialise donc avec des valeurs nulles en racine !
fils.add(Arbre_i); fils.add(Arbre_i);
} }
} }
public Arbre (Fraction value){ public ArbreMCTS (Fraction value){
this.value = value; this.value = value;
} }
public Arbre (int num, int den){
public ArbreMCTS (int den, int num){
this.value.den = den; this.value.den = den;
this.value.num = num; this.value.num = num;
} }
// Les accesseurs : // Les accesseurs :
public Fraction getFraction(){
return value;
}
public double getvalue(){ public double getvalue(){
return(value.getNote()); return(value.getNote());
} }
public ArrayList<Arbre> getfils(){ public ArrayList<ArbreMCTS> getfils(){
return(fils); return(fils);
} }
public ArrayList getcoups(){ public ArrayList<Coup> getcoups(){
return(coups); return(coups);
} }
...@@ -101,10 +103,10 @@ public class Arbre { ...@@ -101,10 +103,10 @@ public class Arbre {
} }
else{ else{
int a = this.fils.size(); int a = this.fils.size();
Arbre fils0 = this.fils.get(0); ArbreMCTS fils0 = this.fils.get(0);
int maxfils = fils0.hauteur(); int maxfils = fils0.hauteur();
for (int i = 1; i < a; i++){ for (int i = 1; i < a; i++){
Arbre next = this.fils.get(i); ArbreMCTS next = this.fils.get(i);
maxfils = Math.max(next.hauteur(),maxfils); maxfils = Math.max(next.hauteur(),maxfils);
} }
return(1 + maxfils); return(1 + maxfils);
......
...@@ -15,6 +15,8 @@ import static tictactoecodingame.Generator.random_tests; ...@@ -15,6 +15,8 @@ import static tictactoecodingame.Generator.random_tests;
public class ArbreMinMax { public class ArbreMinMax {
protected int value; protected int value;
//Coup théorique joué à ce noeud
protected Coup coup;
protected ArrayList<Coup> coups; protected ArrayList<Coup> coups;
protected ArrayList<ArbreMinMax> fils; protected ArrayList<ArbreMinMax> fils;
...@@ -23,6 +25,10 @@ public class ArbreMinMax { ...@@ -23,6 +25,10 @@ public class ArbreMinMax {
public ArbreMinMax(){ public ArbreMinMax(){
} }
public ArbreMinMax(Coup coup){
this.coup = coup;
}
public ArbreMinMax(int value, ArrayList coups, ArrayList fils){ public ArbreMinMax(int value, ArrayList coups, ArrayList fils){
this.value = value; this.value = value;
this.fils = fils; this.fils = fils;
...@@ -61,7 +67,11 @@ public class ArbreMinMax { ...@@ -61,7 +67,11 @@ public class ArbreMinMax {
} }
} }
public ArrayList getcoups(){ public Coup getcoup(){
return coup;
}
public ArrayList<Coup> getcoups(){
return(coups); return(coups);
} }
...@@ -105,7 +115,7 @@ public class ArbreMinMax { ...@@ -105,7 +115,7 @@ public class ArbreMinMax {
} }
public int Min(){ public int Min(){
int m = 2147483640; int m = Integer.MAX_VALUE;
int a = this.getfils().size(); int a = this.getfils().size();
for(int i = 0; i < a ; i++){ for(int i = 0; i < a ; i++){
int n = this.getfils().get(i).getvalue(); int n = this.getfils().get(i).getvalue();
...@@ -117,7 +127,7 @@ public class ArbreMinMax { ...@@ -117,7 +127,7 @@ public class ArbreMinMax {
} }
public int Max(){ public int Max(){
int m = 0; int m = Integer.MIN_VALUE;
int a = this.getfils().size(); int a = this.getfils().size();
for(int i = 0; i < a ; i++){ for(int i = 0; i < a ; i++){
int n = this.getfils().get(i).getvalue(); int n = this.getfils().get(i).getvalue();
...@@ -132,23 +142,22 @@ public class ArbreMinMax { ...@@ -132,23 +142,22 @@ public class ArbreMinMax {
// c = compteur // c = compteur
// Le compteur doit être initialisé à 0 donc pair -> Max, impair -> Min // Le compteur doit être initialisé à 0 donc pair -> Max, impair -> Min
if(this.getfils() != null){ if(!this.estFeuille()){
int a = this.getfils().size(); int a = this.getfils().size();
for(int i = 0; i < a ; i++){ for(int i = 0; i < a ; i++){
this.getfils().get(i).MinMax(c+1); this.getfils().get(i).MinMax(c+1);
} }
} if(c%2 == 0){
//On attribue le max
if(c%2 == 0){ int m = this.Max();
//On attribue le Min this.setvalue(m);
int m = this.Min();
this.setvalue(m);
} }
else{ else{
//On attribue le max //On attribue le min
int m = this.Max(); int m = this.Min();
this.setvalue(m); this.setvalue(m);
} }
} }
} }
}
...@@ -10,7 +10,7 @@ package tictactoecodingame; ...@@ -10,7 +10,7 @@ package tictactoecodingame;
* @author Théo * @author Théo
*/ */
public class Generator { public class Generator {
public static int random_tests(Plateau plateau, int nb_tests) { public static int random_tests(Plateau plateau, int nb_tests,Joueur target) {
int c = 0; int c = 0;
JoueurOrdi player = new JoueurOrdi("player"); JoueurOrdi player = new JoueurOrdi("player");
JoueurOrdi opponent = new JoueurOrdi("oppo"); JoueurOrdi opponent = new JoueurOrdi("oppo");
...@@ -23,7 +23,7 @@ public class Generator { ...@@ -23,7 +23,7 @@ public class Generator {
opponent.forceId(i); opponent.forceId(i);
Coup coup; Coup coup;
plateau.sauvegardePosition(0); plateau.sauvegardePosition(99);
for(i=0; i<nb_tests;i++){ for(i=0; i<nb_tests;i++){
while (!plateau.partieTerminee()) { while (!plateau.partieTerminee()) {
coup = currentPlayer.joue(plateau); coup = currentPlayer.joue(plateau);
...@@ -39,11 +39,13 @@ public class Generator { ...@@ -39,11 +39,13 @@ public class Generator {
} }
Joueur vainqueur = plateau.vainqueur(); Joueur vainqueur = plateau.vainqueur();
if ( vainqueur == player ) if(vainqueur != null){
c++; if ( vainqueur.getIdJoueur() == target.getIdJoueur() )
else if ( vainqueur == player ) c++;
c--; else if ( vainqueur.getIdJoueur() != target.getIdJoueur() )
plateau.restaurePosition(0); c--;
}
plateau.restaurePosition(99);
} }
return c; return c;
} }
......
...@@ -81,8 +81,7 @@ public class GrilleTicTacToe3x3 extends Plateau { ...@@ -81,8 +81,7 @@ public class GrilleTicTacToe3x3 extends Plateau {
return false; return false;
} }
Joueur dernierJoueur = dernierCoup.getJeton() Joueur dernierJoueur = dernierCoup.getJeton().getJoueur();
.getJoueur();
/* Regarde si le dernier coup est gagnant */ /* Regarde si le dernier coup est gagnant */
for (int d = 0; d < 4; d++) { for (int d = 0; d < 4; d++) {
......
...@@ -12,22 +12,23 @@ public class Player { ...@@ -12,22 +12,23 @@ public class Player {
public static void main(String args[]) { public static void main(String args[]) {
JoueurHumain humain = new JoueurHumain("Humain");
JoueurOrdi joueurOrdi = new JoueurOrdi("Ordi"); //JoueurHumain humain = new JoueurHumain("Humain");
JoueurOrdi joueurOrdi1 = new JoueurOrdi("Ordi1");
JoueurOrdi joueurOrdi2 = new JoueurOrdi("Ordi2");
//Il faut deux joueurs car l'id fixe le jeton
AlgoRechercheMinMax minmax = new AlgoRechercheMinMax(3, 10, joueurOrdi1, joueurOrdi2);
// Remplacer ici l'algorithme aléatoire par votre algorithme. joueurOrdi1.setAlgoRecherche(minmax);
// Créer une nouvelle classe qui hérite de la class AlgoRecherche joueurOrdi2.setAlgoRecherche(minmax);
AlgoRechercheAleatoire alea = new AlgoRechercheAleatoire( ); // L'ordinateur joue au hasard
joueurOrdi.setAlgoRecherche(alea);
GrilleTicTacToe3x3 grille = new GrilleTicTacToe3x3(); GrilleTicTacToe9x9 grille = new GrilleTicTacToe9x9();
//Arbitre a = new Arbitre(grille, joueurOrdi , joueurOrdi ); Arbitre a = new Arbitre(grille, joueurOrdi1 , joueurOrdi2);
//Arbitre a = new Arbitre(grille, joueurOrdi , humain );
Arbitre a = new Arbitre(grille, joueurOrdi , humain );
a.startNewGame(true); // Demarre une partie en affichant la grille du jeu a.startNewGame(true); // Demarre une partie en affichant la grille du jeu
// Pour lancer un tournooi de 100 parties en affichant la grille du jeu // Pour lancer un tournooi de 100 parties en affichant la grille du jeu
......
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package tictactoecodingame;
import java.util.ArrayList;
/**
*
* @author louis
*/
public class Selection {
ArrayList<Integer> chemin;
public Selection(){
chemin=new ArrayList<>();
}
public Selection(double c, ArbreMCTS a){
Selection s=new Selection();
chemin=SelectionAux(c, a, s, 0).chemin;
}
private Selection SelectionAux(double c, ArbreMCTS a, Selection s, int nbSimulPere){
if (a.estFeuille()){
return s;
}
else {
double coefMax=0;
int indiceSelection=0;
ArrayList<ArbreMCTS> f=a.getfils();
for(int i=0;i<f.size();i++){
ArbreMCTS arbreTeste = f.get(i);
double coef =arbreTeste.getvalue()+c*Math.sqrt(Math.log(nbSimulPere)/arbreTeste.getFraction().getDenominateur());
if (coef>coefMax){
indiceSelection=i;
coefMax=coef;
}
}
ArbreMCTS arbreSelectionne=f.get(indiceSelection);
int nbSimulPereNew=arbreSelectionne.getFraction().getDenominateur();
s.chemin.add(indiceSelection);
return SelectionAux(c,arbreSelectionne,s,nbSimulPereNew);
}
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment