[JAVA] Algorithme Min-Max
Répondre à la discussion
Affichage des résultats 1 à 13 sur 13

[JAVA] Algorithme Min-Max



  1. #1
    Aenonis

    Question [JAVA] Algorithme Min-Max


    ------

    Bonjour à toutes et à tous !

    J'ai un soucis avec l'algo Min-Max exécuté sur un jeu de Puissance 4.

    En effet, celui-ci ne fait pas ce que j'attends d'un algo en solution complète.

    J'ai appris, lors de mes nombreuses recherches sur Internet que le premier joueur qui met son pion (X dans mon programme) dans la colonne du milieu gagne à tous les coups s'il fait le meilleur coup à chaque fois.

    Pour tester mon algo, je fais combattre deux IA de puissance égales (la profondeur de l'arbre est identique chez les deux ordinateurs), et j'aperçois quelques ennuis.

    En profondeur 5, le X joue bien la colonne du milieu mais c'est le O qui gagne.
    En profondeur 6, le X ne joue pas la colonne du milieu (il joue la colonne la plus à gauche) et le O se plante royalement, X peut gagner et O ne bouche pas le trou, ce qui fait que X fait puissance 4 au tour d'après.

    J'ai testé différentes valeurs de départ pour initialiser les variables min et max. Aucun des résultats n'est convaincant.

    Pire encore : je mets le X et profondeur 5 et le O en profondeur 4 et devinez quoi, c'est le O qui gagne... Je vais devenir fou ! C'est celui qui fait le moins de calculs qui gagne, je trouve ça absurde.

    J'aimerai une petite aide de ceux qui se sont déjà penchés sur la question.

    Voici mon code :
    Code:
    public final class Ordinateur extends Joueur
    {
        public static final int PROFONDEUR=5;
        
        private final int profondeur;
        
        Ordinateur(Pion pion, int profondeur) //package
        {
            super(pion);
            this.profondeur=profondeur;
        }
    
        @Override
        public final int jouer()
        {
            return min_max();
        }
    
        private final int min_max()
        {
            int max_val=-10000; //TO_MODIFY
            int meilleur_coup=-1;
            for (int colonne=0; colonne<jeu.getPlateau().getColonnes(); ++colonne)
            {
                int ligne=jeu.getLigne(colonne);
                if (ligne!=-1)
                {
                    jeu.jouer(colonne, pion); //WARNING
                    int val=min(profondeur);
                    if (val>max_val)
                    {
                        max_val=val;
                        meilleur_coup=colonne;
                    }
                    jeu.remove(colonne);
                }
            }
            return meilleur_coup;
         }
        
        private final int min(int profondeur)
        {
            if (profondeur==0 || jeu.isFinished())
                return eval(pion.getOpposite()); //WARNING
    
            int min_val=10000; //TO_MODIFY
            for (int colonne=0; colonne<jeu.getPlateau().getColonnes(); ++colonne)
            {
                int ligne=jeu.getLigne(colonne);
                if (ligne!=-1)
                {
                    jeu.jouer(colonne, pion.getOpposite()); //WARNING
                    int val=max(profondeur-1);
                    if (val<min_val) min_val=val;
                    jeu.remove(colonne);
                }
            }
            return min_val;
        }
        
        private final int max(int profondeur)
        {
            if (profondeur==0 || jeu.isFinished())
                return eval(pion); //WARNING
    
            int max_val=-10000; //TO_MODIFY
            for (int colonne=0; colonne<jeu.getPlateau().getColonnes(); ++colonne)
            {
                int ligne=jeu.getLigne(colonne);
                if (ligne!=-1)
                {
                    jeu.jouer(colonne, pion); //WARNING
                    int val=min(profondeur-1);
                    if (val>max_val) max_val=val;
                    jeu.remove(colonne);
                }
            }
            return max_val;
        }
    }
    J'aimerai savoir premièrement si je n'ai pas fait d'erreur dans la retranscription de l'algo min-max que j'ai trouvé sur le site du zéro.

    Ensuite, j'aimerai savoir si je ne me suis pas gourré pour le passage du paramètre "pion" ou "pion.getOpposite()" là où j'ai placé des "//WARNING".

    Et enfin, me donner des idées pour écrire une méthode eval qui satisferait les conditions suivantes:
    - Le premier joueur met son pion au milieu
    - Celui qui met son pion au milieu gagne d'office en jouant le meilleur coup à chaque fois

    Cette classe fait partie d'un ensemble mais les appels de méthodes parlent d'eux-même donc, comprendre mon code ne devrait pas être fort compliqué. S'il vous faut le code des autres classes du projet, je peux vous les transmettre sans aucun problème .

    En vous remerciant d'avance,

    Aenonis

    -----
    Dernière modification par Aenonis ; 24/05/2015 à 04h28.
    Aenonis

  2. #2
    Aenonis

    Re : [JAVA] Algorithme Min-Max

    Je me permets de up ce sujet

    Merci d'avance,

    Aenonis
    Aenonis

  3. #3
    Aenonis

    Re : [JAVA] Algorithme Min-Max

    Je me re-permets de re-up ce sujet

    Re-merci d'avance,

    Re-Aenonis
    Aenonis

  4. #4
    Arzhur

    Re : [JAVA] Algorithme Min-Max

    Bonjour,


    Dans quel cas est-ce que "ligne" est égale à -1 ?

    Que fait ta fonction eval(pion)...parce que c'est un peu elle qui est importante ici.

  5. A voir en vidéo sur Futura
  6. #5
    Aenonis

    Re : [JAVA] Algorithme Min-Max

    Coucou,

    Merci de ta réponse .

    La ligne vaut -1 quand la colonne est pleine.

    Et la méthode eval(pion) évalue le plateau en fonction du pion. Positive si la situation est avantageuse pour le pion et négative si elle est désavantageuse. Mais l'IA joue n'importe comment...

    Merci

    Aenonis
    Aenonis

  7. #6
    Arzhur

    Re : [JAVA] Algorithme Min-Max

    Et la méthode eval(pion) évalue le plateau en fonction du pion. Positive si la situation est avantageuse pour le pion et négative si elle est désavantageuse. Mais l'IA joue n'importe comment...
    Certes, mais de manière plus précise : c'est quoi l'implémentation ? Je me demande si l'erreur n'est pas dans cette fonction plutôt que dans l'algo.

  8. #7
    Aenonis

    Re : [JAVA] Algorithme Min-Max

    Merci de ta réponse

    Voici l'implémentation de la fonction et des sous-fonctions de "eval":
    Code:
        private final int eval(Pion joueur)
        {
            return evalGrille(joueur);
        }
        
        private final int evalGrille(Pion joueur)
        {
            int valeur=0;
            for (int row=0; row<jeu.getPlateau().getLignes(); ++row)
            {
                for (int col=0; col<jeu.getPlateau().getColonnes(); ++col)
                {
                    if (jeu.getPlateau().getPion(row, col)==null) //pourquoi uniquement les cases vides ?
                        valeur+=evalCase(row, col, joueur);
                }
            }
            return valeur;
        }
    
        private final int evalCase(int row, int col, Pion joueur)
        {
                int valeur;
                valeur=nbAlignVertic(row, col, joueur)
                        +nbAlignHoriz(row, col, joueur)
                        +nbAlignSlash(row, col, joueur)
                        +nbAlignAntiSlash(row, col, joueur);
    
                Pion otherJ=joueur.getOpposite();
                valeur=valeur
                        -nbAlignVertic(row, col, otherJ)
                        -nbAlignHoriz(row, col, otherJ)
                        -nbAlignSlash(row, col, otherJ)
                        -nbAlignAntiSlash(row, col, otherJ);
    
                double d=Math.pow(2, jeu.getPlateau().getLignes()-row); //je ne comprends pas la raison d'être de ce calcul
                valeur=valeur*(int)Math.floor(d);
    
                return valeur;
        }
    
        private final int nbAlignVertic(int row, int col, Pion joueur)
        {
                int val=0;
                boolean b=true;
                while (row+1<jeu.getPlateau().getLignes() && b)
                {
                    ++row;
                    if (jeu.getPlateau().getPion(row, col)==joueur)
                        ++val;
                    else
                        b=false;
                }
                val=modifierVal(val);
                return val;
        }
    
        private final int nbAlignHoriz(int row, int col, Pion joueur)
        {
            int val=0;
            int c=col;
            boolean b=true;
            while (c-1>= 0 && b)
            {
                --c;
                if (jeu.getPlateau().getPion(row, c)==joueur)
                    ++val;
                else
                    b=false;
            }
    
            b=true;
            c=col;
            while (c+1<jeu.getPlateau().getColonnes() && b)
            {
                ++c;
                if (jeu.getPlateau().getPion(row, c)==joueur)
                    ++val;
                else
                    b=false;
            }
            val=modifierVal(val);
            return val;
        }
    
        private final int nbAlignSlash(int row, int col, Pion joueur)
        {
            int val=0;
            int c=col;
            int r=row;
            boolean b=true;
            while (c-1>=0 && r+1<jeu.getPlateau().getLignes() && b)
            {
                --c;
                ++r;
                if (jeu.getPlateau().getPion(r, c)==joueur)
                    ++val;
                else
                    b=false;
            }
    
            b=true;
            c=col;
            r=row;
            while (c+1<jeu.getPlateau().getColonnes() && r-1> 0 && b)
            {
                ++c;
                --r;
                if (jeu.getPlateau().getPion(r, c)==joueur)
                    ++val;
                else
                    b=false;
            }
            val=modifierVal(val);
            return val;
        }
    
        private final int nbAlignAntiSlash(int row, int col, Pion joueur)
        {
            int val=0;
            int c=col;
            int r=row;
            boolean b=true;
            while (c+1<jeu.getPlateau().getColonnes() && r+1<jeu.getPlateau().getLignes() && b)
            {
                ++c;
                ++r;
                if (jeu.getPlateau().getPion(r, c)==joueur)
                    ++val;
                else
                    b=false;
            }
    
            b=true;
            c=col;
            r=row;
            while (c-1>=0 && r-1>=0 && b)
            {
                --c;
                --r;
                if (jeu.getPlateau().getPion(r, c)==joueur)
                    ++val;
                else
                     b=false;
            }
            val=modifierVal(val);
            return val;
        }
    
        private static int modifierVal(int a)
        {
            switch(a)
            {
                case 0: return 0;
                case 1: return 1;
                case 2: return 10;
                case 3: return 100;
                default: return 1000;
            }
        }
    J'ai mis du temps à mettre ce code en ligne parce que ce code ne m'appartient pas, je l'ai récupéré sur un projet de puissance 4 que j'ai trouvé sur Internet.

    J'ai mis deux questions dans le code.

    En gros, il pèse le pour et le contre de toutes les cases vides en calculant le nombre de jetons qu'on peut aligner en jouant sur cette colonne.

    Aenonis

    PS : l'algo min-max et le reste du projet m'appartient, ce n'est que le code de ce post qui ne m'appartient pas.
    Aenonis

  9. #8
    Arzhur

    Re : [JAVA] Algorithme Min-Max

    Bonjour,


    //pourquoi uniquement les cases vides ?
    Surement parce qu'au coup d'après le joueur va mettre un pion dans une case vide

    //je ne comprends pas la raison d'être de ce calcul
    Moi non plus mais ça a pour effet de donner plus d'importance à une position en bas du plateau.....je connais pas assez le puissance 4 pour savoir si c'est idiot ou pas

    En gros il compare entre les somme du nombre de pion alignés avec une case vide et les cases du bas pèsent plus lourd....ca me parait pas trop mal, mais est-ce la même évaluation que le fameux algo suprême qui gagne à tout les coup ?


    Dans ton code d'avant :

    return eval(pion.getOpposite());
    J'ai quand même un doute : je vois pas pourquoi t'évalues la position de l'adversaire, tu devrais n'evaluer la position que du point de vue du joueur courant....non ?

  10. #9
    Aenonis

    Question Re : [JAVA] Algorithme Min-Max

    Merci de ta réponse .

    Je ne sais pas pourquoi l'auteur initial de ce code a estimé que les cases en bas pèsent plus lourd...

    Et pour ce qui est du pion.getOpposite(), tu as peut-être raison, en fait, dans la fonction "min", j'ai mis qu'on jouait l'adversaire et dans la fonction max, j'ai mis qu'on jouait le PC. Donc, pour moi, il me semble logique que dans la fonction min, j'évalue le pion.getOpposite()... Mais tu as raison, je ne sais pas trop en fait.

    Et concernant l'algo qui gagne à tous les coups, je ne sais pas comment l'implémenter...

    Merci d'avance,

    Aenonis
    Aenonis

  11. #10
    Aenonis

    Re : [JAVA] Algorithme Min-Max

    Je demande un petit up

    Merci d'avance,

    Aenonis
    Aenonis

  12. #11
    Arzhur

    Re : [JAVA] Algorithme Min-Max

    C'est quoi ta question ?

  13. #12
    Aenonis

    Re : [JAVA] Algorithme Min-Max

    Coucou,

    Ma question est : pourquoi est-ce que ce mon IA joue comme une clinche ?

    J'ai fait les changements que tu m'as conseillé de faire mais elle joue toujours n'importe comment...

    Je ne comprends pas pourquoi...

    Merci d'avance,

    Aenonis
    Aenonis

  14. #13
    Arzhur

    Re : [JAVA] Algorithme Min-Max

    Hello,


    ben comme ca, je dirais que l'algo en lui même est pas hyper balèze....

    Je te conseille de faire passer une batterie de tests à ton programme : Tu le fais jouer qu'un seul coup à partir d'une position que tu as déterminé (et ce pour plusieurs positions) .


    Tu verras bien ce qu'il choisit, et tu pourras mieux voir là ou il joue mal (enfin dans quel cas l'algo choisi une position pas adaptée).

Discussions similaires

  1. java qui fait la java
    Par vanos dans le forum Logiciel - Software - Open Source
    Réponses: 3
    Dernier message: 14/10/2014, 16h31
  2. [Java] Installation Java
    Par AdelineJ dans le forum Programmation et langages, Algorithmique
    Réponses: 6
    Dernier message: 05/06/2014, 20h00
  3. Graphes et Arc [Java ou en Algorithme]
    Par Kreg dans le forum Programmation et langages, Algorithmique
    Réponses: 0
    Dernier message: 12/04/2012, 20h51
  4. java et sas
    Par invitea93cf986 dans le forum Logiciel - Software - Open Source
    Réponses: 4
    Dernier message: 27/05/2009, 10h35
  5. Java, java, java, where are you, there's a mission for you !
    Par invite1237a629 dans le forum Logiciel - Software - Open Source
    Réponses: 35
    Dernier message: 16/03/2008, 22h10