Programme Jeu de Dames

Mopade Messages postés 2 Date d'inscription mercredi 10 janvier 2007 Statut Membre Dernière intervention 15 janvier 2007 - 12 janv. 2007 à 16:38
cs_jojolemariole Messages postés 519 Date d'inscription mercredi 21 mars 2007 Statut Membre Dernière intervention 19 décembre 2016 - 19 juil. 2007 à 12:23
Voila avec un ami nous sommes en train de créer un jeu de Dames malheureusement nous avons un problème :(

En effet lors de l'intervention de la machine ( lorsqu'elle doit jouer ) le programme plante, il y a donc un problème au niveau de l'IA de l'ordinateur

Voici le code et j'espère de tout coeur que vous pourrez nous aider, au bout d'une semaine dans la situation on commence à désespérer  

class LeJeu {

    // Constantes
    final int NB_COL = 8;               // Nbre de colonnes du damier
    final int NB_LGN = 8;               // Nbre de lignes du damier
    final char VIDE = '#';                 // Caractère affiché pour une case sans pion
    final char N = 'N';                 // Caractere affiche pour une case avec pion Noir
    final char B = 'B';                 // Caractere affiche pour une case avec pion Blanc
    final String NO = new String("no"); // Direction Nord/Ouest
    final String NE = new String("ne"); // Direction Nord/Est
    final String SO = new String("so"); // Direction Sud/Ouest
    final String SE = new String("se"); // Direction Sud/Est
    
    /*********************/
    /** Bloc principal  **/
    /*********************/
    void principal() {
    
        char[][] damier = new char[NB_LGN][NB_COL]; // la matrice contenant chaque case du damier
        
        // Initialisation
        initialiserJeu( damier );
        afficherDamier( damier );
        
        // Jouer
        jouer( damier );
    }
    
    /************************************/
    /** Methode qui lance la partie en faisant alternativement jouer    **/
    /** le joueur puis la machine jusqu'a ce que l'un des 2 gagne         **/
    void jouer( char[][] dam ) {
    
        boolean ret, finPartie = false;
        String coordP;              // les coordonnees d'un pion dans une seule chaine "hXvY"
        int[] les2C;                // les 2 coordonnees entieres d'un pion
        String manoeuvre;           // la chaine de caracteres qui designe la manoeuvre
        
        // Convention de départ : les pions noirs appartiennent au joueur et progressent vers le nord
        while ( !finPartie ) {
        
            // 1/ D'abord le joueur
            
           
            
            // 1.1/ Designer le pion noir qui va manoeuvrer
            coordP = SimpleInput.getString("Quel pion noir ? hXvY X et Y entre 1 et " + NB_COL);
            les2C = string2entiers( coordP );
            
            // Est-ce un pion noir ?
            if ( dam[les2C[0]-1][les2C[1]-1] == N ) {
            
                // 1.2/ Pour ce pion donner, la manoeuvre : capture ou deplacement en 
                // diagonale. Directions possibles : no(NordOuest), ne(NordEst), so(SudOuest), se(SudEst).
                // Le joueur rentre une chaine de caracteres enregistree dans "manoeuvre" : 
                //      - soit deplacement : "d/no (ou ne)" (so ou se non autorises)
                //      - soit capture : "c/no (et/ou ne et/ou so et/ou se)"
                manoeuvre = SimpleInput.getString("Quelle manoeuvre ? d/[no ou ne] c/[no/ne/so/se]");
                ret = manoeuvrer( manoeuvre, les2C, dam );
                
                // 2/ La machine joue... a ecrire !!
                if ( ret ){ 
                        afficherMessage( "La machine joue maintenant !!" );
                        ManIA(dam);
                }
                
            }
            else afficherMessage( "Erreur : il ne s'agit pas d'un pion noir" );
            
            afficherDamier( dam );
        }
   
    }
    
    /************************************/
    /** Methode de mise en place des pions sur le damier **/
    void initialiserJeu( char[][] mat ) {
    
        int i, j;
        int zoneBlancs = 3;
        int zoneNoirs = 6;
    
        // Par convention, la coordonnee (0, 0) correspond a la case du coin 
        // superieur gauche du damier. Il s'agit d'une case dans le camp 
        // des pions blancs (B). Les noirs (N) progressent de bas en haut.
        
        // Pour chaque ligne
        for ( i=1; i<=NB_LGN; i++ ) {
            // Pour chaque colonne
            for ( j=1; j<=NB_COL; j++ ) {
                // si ligne pair et colonne pair => case sans pion                if ( (i%2 0)&amp;&amp;(j%2 0) ) { mat[i-1][j-1]=VIDE; }
                // si ligne pair et colonne impair => pion B ou N
                else if ( (i%2 == 0)&amp;&amp;(j%2 != 0) ) {
                    if ( i <= zoneBlancs ) mat[i-1][j-1]=B;
                    else if ( i >= zoneNoirs ) mat[i-1][j-1]=N;
                    else mat[i-1][j-1]=VIDE;
                }
                // si ligne impair et colonne pair => pion B ou N                else if ( (i%2 !0)&amp;&amp;(j%2 0) ) {
                    if ( i <= zoneBlancs ) mat[i-1][j-1]=B;
                    else if ( i >= zoneNoirs ) mat[i-1][j-1]=N;
                    else mat[i-1][j-1]=VIDE;
                }
                // si ligne impair et colonne impair => case sans pion
                else { mat[i-1][j-1]=VIDE; }                                              
            }                
        }    
    }
   
    /************************************/
    /** Methode d'affichage du damier a l'ecran **/
    void afficherDamier( char[][] mat ) {
    
        int i, j;
        
        // Affichage egalement des numeros de cases en horizontal et vertical
        // pour ameliorer la lisibilite.
        System.out.println("\n");
        // Pour chaque ligne
        for ( i=1; i<=(NB_LGN+1); i++ ) {
            // Pour chaque colonne
            for ( j=1; j<=(NB_COL+1); j++ ) {
            
                // la premiere inscription en haut a gauche est vide
                if ( i==1 &amp;&amp; j==1 ) System.out.print("\t");
                // la premiere colonne affiche les numeros des lignes horizontales
                else if ( i>1 &amp;&amp; j==1 ) System.out.print((i-1) + "\t");
                // la premiere ligne affiche les numeros des colonnes
                else if ( i==1 &amp;&amp; j>1 &amp;&amp; j<(NB_COL+1) ) System.out.print((j-1) + "\t");
                // le dernier element de la premiere ligne doit etre suivi de 2 retours chariot
                else if ( i==1 &amp;&amp; j==(NB_COL+1) ) System.out.print((j-1) + "\n\n");
                // idem mais pour une ligne du damier (differente de la premiere ligne)
                else if ( i>1 &amp;&amp; j==(NB_COL+1) ) System.out.print(mat[i-2][j-2] + "\n\n");
                // sinon, on affiche une ligne du damier
                else System.out.print(mat[i-2][j-2] + "\t");            
            }   
        }
        
        System.out.println("\n");
    }
    
    /************************************/
    /** Methode de traduction entre coordonnees String vers int **/
    int[] string2entiers( String coordP ) {
    
        int[] les2C = new int[2];
        String s;
        
        // la coordonnee s'ecrit "hXvY" et on veut recuperer separement X et Y
        // premiere coordonnee X juste apres "h"
        s = coordP.substring(1,2);
        les2C[0] = Integer.parseInt(s);
        // deuxieme coordonnee Y juste apres "v"
        s = coordP.substring(3,4);
        les2C[1] = Integer.parseInt(s);
    
        return les2C;
    }
    
    /************************************/
    /** Methode qui decode la manoeuvre (deplacement ou capture) pour le pion sur le damier **/
    boolean manoeuvrer( String man, int[] les2C, char[][] dam ) {
    
        String dOUc, dir;
        boolean ret = true;
        
        // La commande "man" a la structure suivante : d/[no ou ne] ou bien c/[no/ne/so/se].
        
        // la commande commence par "d" (deplacement) ou "c" (capture)
        dOUc = man.substring(0,1);
        // s'il s'agit d'un deplacement
        if ( dOUc.equals("d") ) {
            // la direction "no" ou "ne" est donnee juste apres les caracteres "d/"
            dir = man.substring(2,4);
            ret = deplacerPion( dam, les2C, dir );       
        }
        // s'il s'agit d'une capture
        else {
            dir = man.substring(2,4);
        ret = capturerPion( dam, les2C, dir );
        }
        
        return ret;
    }

    /************************************/
    /** Methode qui deplace le pion sur le damier **/
    boolean deplacerPion( char[][] dam, int[] les2C, String dir ) {
          
        int newH, newV;     // nouvelles coordonnees du pion apres deplacement
        boolean ret = true;
        
        // si le deplacement se fait bien vers le nord
        if ( !dir.equals(SO) &amp;&amp; !dir.equals(SE) ) {
        
           if ( dir.equals(NO) ) {       
                newH = les2C[0] - 1;
                newV = les2C[1] - 1;       
           }        
           else {
                newH = les2C[0] + 1;
                newV = les2C[1] - 1;
           }
           // sort-on du damier ou la case est-elle deje  occupee ?
           if ( deplPossible( newH, newV, dam ) ) {        
                dam[newH-1][newV-1] = N;
                dam[les2C[0]-1][les2C[1]-1] = VIDE;                
           }
           else {          
                ret = false;
                afficherMessage("Deplacement en dehors du damier ou case deja occupee !!");           
           }                   
        }
        
        else {
           ret = false;
           afficherMessage("Deplacement vers le sud non autorise !!");
        }
        
        return ret;       
    }

    /************************************/
    /** Méthode qui verifie que les nouvelles coordonnees restent dans les bornes du damier **/
    /** et qu'il n'y a pas de pion a l'endroit de destination                               **/
    boolean deplPossible( int h, int v, char[][] dam ) {
    
        boolean ret = true;
    
        if ( (h < 1) || (h > NB_LGN) || (v < 1) || (v > NB_COL) || (dam[h-1][v-1] != VIDE) ) ret = false;        
        return ret;
    }
    
    /************************************/
    /** Methode qui affiche un message a l'ecran selon format ci-dessous **/
    void afficherMessage( String leMes ) {
    
        System.out.println("\n********************\n" + leMes + "\n********************\n");    
    }

/***********************************************/
/**Methode qui permet à un pion de capturer un pion ennemi**/
boolean capturerPion( char[][] dam, int[] les2C, String dir ) {
    
    int newH, newV;  //nouvelles coordonnees du pion apres capture
    boolean ret = true;
    
    if ( !dir.equals(SO) &amp;&amp; !dir.equals(SE) ) {
        
        if ( dir.equals(NO) ) {
            newH = les2C[0] - 2;
            newV = les2C[1] - 2;
        }
        else {
                newH = les2C[0] + 2;
                newV = les2C[1] - 2;
        }
        //la capture et le deplacement sont-ils possibles ?
        if ( captPossible( newH, newV, dam, dir ) ) {
            dam[newH-1][newV-1] = N;
            dam[les2C[0]-1][les2C[1]-1] = VIDE;
            if ( dir.equals(NO) ) {
                dam[newH][newV] = VIDE;
            }
            else {
                dam[newH-2][newV] = VIDE;
            }
        }
            else {
                ret = false;
                afficherMessage("Pas de pion a capturer, ou déplacement impossible !!");
            }
        }
        else {
            ret = false;
            afficherMessage("Capture vers le Sud non implementee dans cette version du jeu !!");
        }
        
        return ret;
    }

/*********************************************/
/**Methode qui détecte le pion à capturer si il y en a un
    et si le déplacement est possible**/
    boolean captPossible( int h, int v, char[][] dam, String dir ) {
        
        boolean ret = true;
        
        if ( (h < 1) || (h > NB_LGN) || (v < 1) || (v > NB_COL) || (dam[h-1][v-1] != VIDE) ) {
        ret = false;
        }
        if ( dir.equals(NE)){
            if (dam[h][v-2] != B) { 
            ret = false;
            }
        }
        if ( dir.equals(NO)){ 
                    if (dam[h][v] != B) {
            ret = false;
                    }
        }
        return ret;
        }

/****************************************************/
/**Methode qui détermine qu'elle manoeuvre peut effectuer la machine et l'execute**/
    void ManIA( char[][] dam ) {

    int COL = 8;
    int LGN = 8;
    int i = 0;
    int j = 0;
    boolean captureSEposs = false;
    boolean captSO = false;
    String TypeCapt;

    // Pour chaque ligne    
            for ( i=2; i<=(LGN+1); i++ ){
        //Si il s'agit d'une ligne paire        
                if (i%2 != 0) {
            // Pour chaque colonne
                    for ( j=3; j<=(COL+1); j++ ) {
                        if ( dam[i-1][j-1] == B) {
                            if ((i+1<=LGN) &amp;&amp; (j+1<=COL) &amp;&amp; (dam[i][j] == N) &amp;&amp; (dam[i+1][j+1] == VIDE)) {
                            captureSEposs = true;
                            }
                        }
                    }
                }
        //S'il s'agit d'une ligne impaire
                else {
            //Pour chaque colonne
                    for (j=2;j<=(COL+1);j++) {
                        if (dam[i-1][j-1] == B) {
                            if ((i+1<=LGN) &amp;&amp; (j+1<=COL) &amp;&amp; (dam[i][j] == N) &amp;&amp; (dam[i+1][j+1] == VIDE)) {
                            captureSEposs = true;
                            }
                        }
                    }
                }
            }
        
        if (captureSEposs) {
        TypeCapt = "SE";
        ManCapt(i,j,dam, TypeCapt );
        }
        else {
        captSO=captSO(dam);
            }
        if(captSO) {
        TypeCapt = "SO";
        ManCapt(i,j,dam,TypeCapt);
                }
            
        }
    
    
/*************************************************************/
/**Methode qui détermine si la machine peut effectuer une capture au Sud-Ouest,et s'il est possible **/
   boolean captSO( char[][] dam ) {   
   
    boolean captureSOposs = true;
    int COL = 8;
    int LGN = 8;
    int i = 0;
    int j = 0;

    
    // Pour chaque ligne    
            for ( i=2; i<=(LGN+1); i++ ) {
        //Si il s'agit d'une ligne paire        
                if (i%2 != 0) {
            // Pour chaque colonne
                    for ( j=3; j<=(COL+1); j++ ) {
                        if ( dam[i-1][j-1] == B) {
                            if ((i+1<=LGN) &amp;&amp; (j+1<=COL) &amp;&amp; (dam[i][j-2] == N) &amp;&amp; (dam[i+1][j-3] == VIDE)) {
                            captureSOposs = true;
                            }
                        }
                    }
                }
        //S'il s'agit d'une ligne impaire
                else {
            //Pour chaque colonne
                    for (j=2;j<=(COL+1);j++) {
                        if (dam[i-1][j-1] == B) {
                            if ((i+1<=LGN) &amp;&amp; (j+1<=COL) &amp;&amp; (dam[i][j-2] == N) &amp;&amp; (dam[i+1][j-3] == VIDE)) {
                            captureSOposs = true;
                            }
                        }
                    }
                }
            }
        
        return captureSOposs;
    }

/*********************************************************************/
/**Methode qui effectue la capture de la machine**/
        void ManCapt(int i,int j, char[][]dam ,String TypeCapt ) {
        
        if (TypeCapt.equals("SE")){
            dam[i][j] = VIDE;
            dam[i+1][j+1] = B;
            }
        else {
            dam[i][j-2] = VIDE;
            dam[i+1][j-3] = B;
            }
        }
        
}
        
        
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            


Merci d'avance

5 réponses

sheorogath Messages postés 2448 Date d'inscription samedi 21 février 2004 Statut Modérateur Dernière intervention 29 janvier 2010 17
12 janv. 2007 à 17:59
donner le message d'erreur serait un bon debut ... la perso je n'ai pas envie de lire tout le code pour essayer de detecter une faute je prefere savoir quoi cherhcer

"n'est pas mort ce qui semble a jamais dormir et en d'etrange temps meme la mort peut mourrir"
0
Mopade Messages postés 2 Date d'inscription mercredi 10 janvier 2007 Statut Membre Dernière intervention 15 janvier 2007
15 janv. 2007 à 16:48
Désolé, en fait le programme plante au moment du test qui vérifie que la case ciblée contient bien un pion blanc. cela se situe à la ligne 338 :
Le message d'erreur est :

Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 8
        at LeJeu.ManIA(LeJeu.java:338)
        at LeJeu.jouer(LeJeu.java:74)
        at LeJeu.principal(LeJeu.java:36)
        at Lanceur.main(lanceur.java:6)

Voilà si vous pouvez me débloquer de cette situation un peu inquiétante nous vous en serions très reconnaissant ...
0
sheorogath Messages postés 2448 Date d'inscription samedi 21 février 2004 Statut Modérateur Dernière intervention 29 janvier 2010 17
16 janv. 2007 à 18:57
j'ai pas regarder le code mais a un endroit tu essai de metre plus d'element que ne peu en contenir ton tableau et ca a la ligne LeJeu.java:338

"n'est pas mort ce qui semble a jamais dormir et en d'etrange temps meme la mort peut mourrir"
0
cs_jojolemariole Messages postés 519 Date d'inscription mercredi 21 mars 2007 Statut Membre Dernière intervention 19 décembre 2016 25
19 juil. 2007 à 12:18
alors là, je dois avouer que ça me laisse perplexe

1) apparemment t'essaies de faire de l'intelligence artificielle

ce que tu as fait ne vaut rien, il ne jouera pas bien comme ça, rien qu'à voir la gueule de ton programme. Pour les dames, un simple algo de minimax donnera de bons résultats.

2) l'interface, bon on en parle même pas

3) ton problème indexOutOfBoundsException

bon alors là, c'est le ponpon : un tableau de taille 8 peut être indexé de 0 à 7 !!
en gros, si tu veux parcourir un tableau de taille 8, tu fais :

for(int i = 0 ; i < 8 ; i++)

alors que moi je vois ça dans ton code :

                for ( j=3; j<=(COL+1); j++ ) {
                 donc j varie de 3 à 9, ok

                if ( dam[i-1][j-1] == B) {
                 ici on accède donc potentiellement à l'index 8 du tableau : erreur, normal


   
                        if ((i+1< =LGN) && (j+1<=COL)
&& (dam[i][j-2] == N) && (dam[i+1][j-3] == VIDE)) {

                           ici, quand même je dois admettre que tu fais des vérifications
                            sauf que tu vérifie bien que i est inférieur 8, mais tu fais dam[i+1]... ce qui , dans le cas ou i vaut 7
                            donne une erreur

                             captureSOposs = true;

                            }

                        }

                    }
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
cs_jojolemariole Messages postés 519 Date d'inscription mercredi 21 mars 2007 Statut Membre Dernière intervention 19 décembre 2016 25
19 juil. 2007 à 12:23
donc à mon avis, il te manque plusieurs choses pour programmer une IA

déjà, une phase d'analyse un peu plus poussée, on dirait que tu n'as pas prévu les promotions en Reine, car ton tableau ne contient que des 'N' ou des 'B'

ensuite plus d'expérience

mais je ne peux que vous encourager, j'ai eu moi aussi des débuts difficiles quand j'ai voulu faire un jeu d'échec

enfin, je vous conseille dès maintenant de séparer vos SimpleOutput.... (qui relève de la partie ihm) de vos calculs
en gros essayer de penser que l'on pourra greffer n'importe quel type d'interface sur votre IA
0
Rejoignez-nous