Correction 5:
Modularisation


Exercice 1: Reprise du calcul des moyennes (Modularisation, Niveau 0)

Cet exercice ne nécessite pas de corrigé


Exercice 2: Quiz du MOOC (MOOC, Niveau 1)

Cet exercice ne nécessite pas de corrigé

Exercice 3: Rectangle (Modularisation, Niveau 1)

Les méthodes complétées sont commentées dans le code ci-dessous:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
import java.util.Scanner;

class Rectangle {

    private static Scanner scanner = new Scanner(System.in);

    public static void main(String[] args) {
        double largeur = lireDonnee("largeur");
        double hauteur = lireDonnee("hauteur");

        boolean donneesOk = testerDonnees(largeur,hauteur);

        if (donneesOk) {
            calculer(largeur, hauteur);
        } else {
            afficherErreur();
        }
    }

    /**
     * La String passée en paramètre et qui prendra
     * pour valeur effective "largeur" ou "hauteur", permet
     * d'afficher un message plus explicite lorsque l'on demande
     * à l'utilisateur d'entrer ses données.
     * @return un double lu depuis le clavier
     */
    static double lireDonnee(String text) {
        System.out.print("Entrez la " + text + ": ");
        return (scanner.nextDouble());
    }

    /**
     * Permet de calculer un perimètre ou une surface selon le souhait 
     * de l'utilisateur.
     * Cette méthode prend pour arguments la hauteur et la largeur
     * du rectangle nécessaires au calcul. Notez qu'il n'est absolument pas
     * nécessaire que les paramètres de la méthode aient le même nom que
     * les variables passées en paramètre effectifs dans la méthode main
     * @param l longeur du rectangle
     * @param h hauteur du rectangle
     */
    static void calculer(double l, double h) {
        System.out.print("Surface ('s/S') ou perimètre ('p/P')? ");
        char typeCalcul = scanner.next().charAt(0);
        switch (typeCalcul) {
        case 's':
        case 'S':
            double surface = l * h;
            System.out.println("La surface est " + surface);
            break;
        case 'p':
        case 'P':
            double perimetre = 2 * (l + h);
            System.out.println("Le perimetre est    est " + perimetre);
            break;
        default:
            System.out.println("Introduire un 'p' ou un 's' s.v.p");
            break;
        }
    }

    /**
     * Méthode pour tester les données fournies par l'utilisateur
     * @return true si les données sont toutes deux strictement positives
     */
    static boolean testerDonnees(double largeur, double hauteur) {
        return ((largeur > 0) && (hauteur > 0));
    }

    /**
     * Affiche simplement un message d'erreur à l'écran.
     **/
    static void afficherErreur() {
        System.out.println("Erreur: vous avez introduit une largeur " +
                    "ou une hauteur négative!");
    }

}


Exercice 4: Portée d'une variable (Modularisation, portée, Niveau 1)

Le programme illustre le fait que chaque variable est locale au bloc où elle a été déclarée. Cela veut dire que la portée (en anglais scope) de la variable est limitée à ce bloc et que la variable n'est pas visible ou utilisable ailleurs dans le programme. Notamment les variables déclarées dans une méthode sont locales à la méthode en question et ne peuvent pas être accédées depuis d'autres méthodes. Pour communiquer une valeur d'une méthode à une autre, il faut l'envoyer comme argument dans l'appel.
Exécution du programme Portee:
1. x = 11
2. y = 22

3. x = 878
4. y = 23
5. x = 11
6. y = 22

7. x = 33
8. y = 44
9. a = 66
10. b = 88
11. x = 11
12. y = 22

13. object [0] = 5
14. object [0] = 37
15. object [0] = 37

Exercice 5: Erreurs fréquentes dans les méthodes (Modularisation, Niveau 1)

  • methode1: Même s'il n'y a pas d'arguments à envoyer à la méthode, il doit y avoir une liste de paramètres dans l'en-tête. Dans ce cas, il faut ajouter des parenthèses vides.

  • methode2: Il y a une référence à la variable i1 qui n'est pas visible dans la méthode methode2. La portée d'une variable est limitée à son bloc de déclaration, dans le cas de i1, à la méthode main.

  • methode3: La dernière instruction exécutée n'est pas return. Cette instruction est obligatoire pour toutes les méthodes qui retournent une valeur, i.e. qui n'ont pas le type void dans l'en-tête.

  • methode4: Le type de la valeur retournée n'est pas le même que le type specifié dans l'en-tête de la méthode.

  • methode5: La méthode essaie de retourner une valeur avec return. Cela n'est pas possible si l'en-tête de la méthode est void.

  • methode6: La méthode n'a pas de type pour la valeur retournée. Si la méthode ne retourne pas de valeur, il faut indiquer void dans l'en-tête.

  • methode7: La méthode methodeSansErreur est appelée avec 1 argument tandis qu'elle en demande 2. Le nombre d'arguments doit toujours correspondre au nombre de paramètres.

  • methode8: La méthode methodeSansErreur est maintenant appelée avec 2 arguments, ce qui est correct, mais le type des arguments ne correspond pas au type des paramètres.
  •  1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    class ErreursMethodesCorrige {
    
        public static void main(String[] args) {
            int i1 = methode1();
            int i2 = methode2();
            int i3 = methode3();
            int i4 = methode4();
            methode5();
            methode6();
            methode7();
            methode8();
        }
    
        static int methode1() {
            int a = 0;
            System.out.println("Méthode 1");
            return a;
        }
    
        static int methode2() {
            int a = 0;
            // i1 = 10;
            System.out.println("Méthode 2");
            return a;
        }
    
        static int methode3() {
            int a = 0;
            System.out.println("Méthode 3");
            return a;
        }
    
        static int methode4() {
            // String a = "0";
            int a = 0;
            System.out.println("Méthode 4");
            return a;
        }
    
        static void methode5() {
            double a = 0;
            System.out.println("Méthode 5");
            // return a;
        }
    
        static double methode6() {
            double a = 0;
            System.out.println("Méthode 6");
            return a;
        }
    
        static void methode7() {
            int a = 0;
            double b = 5.5;
            methodeSansErreur(a, b);
            System.out.println("Méthode 7");
        }
    
        static void methode8() {
            int a = 0;
            // String b = "5.5";
            double  b = 5.5;
            methodeSansErreur(a, b);
            System.out.println("Méthode 8");
        }
    
        static void methodeSansErreur(int a, double b) {
            // Cette méthode ne fait rien du tout
        }
    }


    Exercice 6: Passage par valeur (Passage de parametres, Niveau 1)

    Les explications et la correction sont données dans le code ci-dessous :

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    class ConcatIncorrecte {
    
        public static void main(String[] args) {
            String s = "China Blue";
            System.out.println(s);
            //version incorrecte
            //concatener(s, " Express");
    
            // version correcte:
            s = concatener(s, " Express");
            System.out.println(s);
        }
    
        /*
         * les raisons du comportement incorrect sont que:
         * 1. les opérations sur les chaines sont non destructives
         *(créent une autre chaine au lieu d'agir sur la chaine originale)
         * 2. l'objet s est une référence, mais les référence sont passées
         * par valeur (on peut altérer l'objet référencé, mais pas la référence
         * elle même):
         * + crée une nouvelle chaine
         * la référence de cette nouvelle chaine est affectée  s
         * (on essaie de changer la référence s et l'effet de cette modification n'est que local)
         * (revoir l'exemple du cours "méthode auxilliaires et réutilisabilité" avec
         * les tableaux)
         */
    
        /*
         * version incorrecte
        public static void concatener(String s,String s2 )
            {
                s += s2;
            }
        */
        
        // version corrigée
        public static String concatener(String s,String s2 ) {
            s += s2;
            return s;
        }
    }


    Exercice 7: Opération sur les tableaux (tableaux, Modularisation, Niveau 1)

    Les méthodes à compléter ne posent pas de difficultés particulières. Elles sont commentées dans le code ci-dessous:

      1
      2
      3
      4
      5
      6
      7
      8
      9
     10
     11
     12
     13
     14
     15
     16
     17
     18
     19
     20
     21
     22
     23
     24
     25
     26
     27
     28
     29
     30
     31
     32
     33
     34
     35
     36
     37
     38
     39
     40
     41
     42
     43
     44
     45
     46
     47
     48
     49
     50
     51
     52
     53
     54
     55
     56
     57
     58
     59
     60
     61
     62
     63
     64
     65
     66
     67
     68
     69
     70
     71
     72
     73
     74
     75
     76
     77
     78
     79
     80
     81
     82
     83
     84
     85
     86
     87
     88
     89
     90
     91
     92
     93
     94
     95
     96
     97
     98
     99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    class Operations {
        public static void main(String args[]) {
            // Construction d'un tableau:
            int[] tableau = {3, 7, 1, 9, 2, 8, 9, 1, 2, 5};
            // Opérations sur le tableau:
            operations(tableau);
    
            // La même chose pour d'autres tableaux:
            int[] tableau1 = remplir1(5);
            operations(tableau1);
    
            int[] tableau2 = remplir2(10);
            operations(tableau2);
    
            int[] tableau3 = remplir3(5);
            operations(tableau3);
        }
    
        /**
         * Cette méthode retourne un tableau int[] de nb éléments
         * initialisés en ordre croissant de 0 à nb-1.
         * @param nb La taille du tableau (nombre d'élements).
         * @return tableau Le tableau correctement rempli.
         */
        static int[] remplir1(int nb) {
            int[] tableau = new int[nb];
            for (int i = 0; i < nb; i++) {
                tableau[i] = i;
            }
            return tableau;
        }
    
        /**
         * Cette méthode retourne un tableau int[] de nb éléments
         * initialisés en ordre croissant à partir de 5.
         * @param nb La taille du tableau (nombre d'élements).
         * @return tableau Le tableau correctement rempli.
         */
        static int[] remplir2(int nb) {
            int[] tableau = new int[nb];
            for (int i = 0; i < nb; i++) {
                tableau[i] = i + 5;
            }
            return tableau;
        }
    
        /**
         * Cette méthode retourne un tableau int[] de nb éléments
         * initialisés en ordre décroissant de nb à 1.
         * @param nb La taille du tableau (nombre d'élements).
         * @return tableau Le tableau correctement rempli.
         */
        static int[] remplir3(int nb) {
            int[] tableau = new int[nb];
            for (int i = 0; i < nb; i++) {
                tableau[i] = nb - i;
            }
            return tableau;
        }
    
        /**
         * Affiche le tableau puis effectue les opérations 1 à 5 sur le tableau.
         * @param tableau Le tableau à traiter.
         */
        static void operations(int[] tableau) {
            afficher(tableau);
            operation1(tableau);
            operation2(tableau);
            operation3(tableau);
            operation4(tableau);
            operation5(tableau);
        }
    
        /**
         * Cette méthode affiche tous les éléments du tableau reçu en
         * paramètre sur une meme ligne. Les éléments sont séparés par
         * deux espaces.
         * @param tableau Le tableau à afficher.
         */
        static void afficher(int[] tableau) {
            for (int i = 0; i < tableau.length; i++) {
                System.out.print(tableau[i]);
                System.out.print("  ");
            }
            // Saut de ligne à la fin de l'affichage
            System.out.println();
        }
    
        /**
         * Cette méthode calcule et affiche le nombre d'éléments de valeur
         * 9 dans le tableau. La variable count sert à compter les éléments
         * trouvés. Elle est initialisée à 0 et incrémentée dans la boucle
         * qui parcourt le tableau chaque fois que l'on trouve un 9.
         * @param tableau Le tableau à traiter.
         */
        static void operation1(int[] tableau) {
            int count = 0;
            for (int i = 0; i < tableau.length; i++) {
                if (tableau[i] == 9) {
                    count++;
                }
            }
            System.out.println("Il y a " + count + " elements de valeur 9 dans le tableau");
        }
    
        /**
         * Cette méthode calcule et affiche le nombre d'éléments qui sont
         * plus grands que 4 OU plus petits que 2.
         * @param tableau Le tableau à traiter.
         */
        static void operation2(int[] tableau) {
            int count = 0;
            for (int i = 0; i < tableau.length; i++) {
                if ((tableau[i] > 4) || (tableau[i] < 2)) {
                    count++;
                }
            }
            System.out.println("Il y a " + count + " elements plus grands que 4 ou plus petits que 2");
        }
    
        /**
         * Cette méthode calcule et affiche le somme de tous les éléments du tableau.
         * @param tableau Le tableau à traiter.
         */
        static void operation3(int[] tableau) {
            int somme = 0;
            for (int i = 0; i < tableau.length; i++) {
                somme = somme + tableau[i];
            }
            System.out.println("La somme des elements est " + somme);
        }
    
        /**
         * Cette méthode calcule et affiche la moyenne arithmétique de
         * tous les éléments du tableau.
         * @param tableau Le tableau à traiter.
         */
        static void operation4(int[] tableau) {
            double somme = 0.0;
            for (int i = 0; i < tableau.length; i++) {
                somme = somme + tableau[i];
            }
    
            double moyenne = somme / tableau.length;
            System.out.println("La moyenne arithmetique des elements est " + moyenne);
        }
    
        /**
         * Cette méthode calcule et affiche le plus grand élément du tableau.
         * @param tableau Le tableau à traiter.
         */
        static void operation5(int[] tableau) {
            int max = tableau[0];
            for (int i = 1; i < tableau.length; i++) {
                if (tableau[i] > max) {
                    max = tableau[i];
                }
            }
            System.out.println("Le plus grand element vaut " + max);
        }
    }


    Exercice 8: Loi de Benford (Modularisation, algorithme, Niveau 1)

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    class Benford {
    
        /* METHODES UTILTAIRES FOURNIES*/
        // affichage  d'un tableau d'entiers
        public static void print(int[] tab) {
            for (int i = 0; i < tab.length; ++i) {
                System.out.print(tab[i] + " ");
            }
            System.out.println();
        }
    
        // affichage  d'un tableau de doubles
        public static void print(double[] tab) {
            for (int i = 0; i < tab.length; ++i) {
                System.out.print(tab[i] + " ");
            }
            System.out.println();
        }
    
        public static void main(String[] args) {
    
            int[] frequencies = new int[9];
            double[] numbers = new double[25];
    
            //  TEST 1.1
            System.out.println("Test 1.1 : ");
            fillWithSquare(numbers);
            print(numbers);
            System.out.println();
            // FIN TEST 1.1 
    
            //TEST 1.2
            System.out.println("Test 1.2 : ");
            System.out.println(extractMaxDigit(0));
            System.out.println(extractMaxDigit(632));
            System.out.println(extractMaxDigit(-221));
            System.out.println(extractMaxDigit(-554.15));
            System.out.println(extractMaxDigit(0.00421));
            System.out.println();
            // FIN TEST 1.2
    
            //  TEST 1.3
            System.out.println("Test 1.3 : ");
            analyze(numbers, frequencies);
            print(frequencies);
            System.out.println();
            // FIN TEST 1.3
    
            // TEST 1.4
            System.out.println("Test 1.4 : ");
            // NE DECOMMENTEZ CETTE PARTIE
            // QUE SI VOUS N'AVEZ PAS REUSSI LA PARTIE PRECEDENTE
            // int tab = {7, 4, 3,  5,  2,  2, 0, 1, 1}
            //frequencies  = tab;
            testBenford(frequencies, numbers.length);
            // FIN TEST 1.4
        }
    
        public static int extractMaxDigit(double number) {
            if (number == 0) {
                return 0;
            } else if (number < 0) {
                number = -number;
            }
    
            while (number < 1) {
                number *= 10;
            }
    
            while (number >= 10) {
                number /= 10;
            }
    
            return (int)number;
        }
    
        public static void fillWithSquare(double[] numbers) {
            for (int i = 0, j = 0; i < numbers.length; ++i) {
                j = i + 1;
                numbers[i] = j * j / 100.0;
            }
        }
    
        public static void analyze(double[] numbers, int[] frequencies) {
            for (int i = 0; i < numbers.length; ++i) {
                int j = extractMaxDigit(numbers[i]);
                ++frequencies[j-1];
            }
        }
    
        public static void testBenford(int[] frequencies, int size) {
            System.out.println("Comparaison des frequences avec les predictions de la loi de Benford :");
            for (int i = 0; i < 9; ++i){
                System.out.print( (i+1) + " : " + 100*(frequencies[i]/(double)size) + "%, ");
                System.out.println( "Benford : "  + Math.log10(1 + 1.0/(i+1))*100 + "%");
            }
        }
    }


    Exercice 9: Nombres amicaux (Modularisation, algorithme, Niveau 2)

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    class Amical {
    
        public static void main(String[] args) {
            int[] nombres = {1210, 45, 27, 220, 54, 284, 9890, 120, 1184};
            System.out.println("Les paires de nombres amicaux sont : ");
            afficherAmicaux(nombres);
        }
    
        /**
         * Vérifie si les deux nombres donnés (nb1 et nb2) sont amicaux.
         */
        public static boolean amical(int nb1, int nb2) {
            int somme = sommeDiviseur(nb1);
            return (nb1 + nb2 == somme
                        && sommeDiviseur(nb2) == somme);
        }
    
        /**
         * Calcule la somme des diviseurs du nombre passé en paramètre (nb1).
         */
        public static int sommeDiviseur(int nb1) {
            int somme = 0;
            for (int i = 1; i <= nb1; ++i){
                if ((nb1 % i) == 0){
                    somme += i;
                }
            }
            return somme;
        }
    
        /**
         * Affiche tous les nombres amicaux contenus dans un tableau d'entiers.
         */
        public static void afficherAmicaux(int[] nombres){
            for (int i = 0; i < nombres.length; ++i){
                for (int j = i+1; j < nombres.length; ++j)
                    if (amical(nombres[i],nombres[j])){
                        System.out.println(nombres[i] + " " + nombres[j]);
                    }
            }
        }
    }


    Exercice 10: Devoir du MOOC (MOOC, Niveau 2)

    Cet exercice ne nécessite pas de corrigé

    Exercice 11: Césure (String, Modularisation, algorithme, Niveau 2)

      1
      2
      3
      4
      5
      6
      7
      8
      9
     10
     11
     12
     13
     14
     15
     16
     17
     18
     19
     20
     21
     22
     23
     24
     25
     26
     27
     28
     29
     30
     31
     32
     33
     34
     35
     36
     37
     38
     39
     40
     41
     42
     43
     44
     45
     46
     47
     48
     49
     50
     51
     52
     53
     54
     55
     56
     57
     58
     59
     60
     61
     62
     63
     64
     65
     66
     67
     68
     69
     70
     71
     72
     73
     74
     75
     76
     77
     78
     79
     80
     81
     82
     83
     84
     85
     86
     87
     88
     89
     90
     91
     92
     93
     94
     95
     96
     97
     98
     99
    100
    101
    102
    103
    104
    import java.util.Scanner;
    
    class Cesure {
    
        public static void main(String[] args) {
            String[] phrase = lirePhrase();
            System.out.println("Le résultat est : ");
            for (int i = 0; i < phrase.length; i++) {
                cesure(phrase[i]);
            }
        }
    
        /**
         * Lit une phrase depuis le terminal.
         * @return un tableau de Strings où chaque entrée
         * est un mot de la phrase lue.
         */ 
        static String[] lirePhrase() {
            Scanner scanner = new Scanner(System.in);
            
            int number = 0;
            while (number <= 0) {
                System.out.print("Donnez le nombre de mots de votre phrase : ");
                number = scanner.nextInt();
                if (number <= 0) {
                    System.out.println("Entrez une valeur plus grande que 0");
                }
            }
    
            String[] phrase = new String [number];
    
            // se debarasser du \n 
            scanner.nextLine();
            for (int i = 0; i < number; i++) {
                System.out.print("Donnez le mot " + (i + 1) + " : ");
                phrase[i] = scanner.nextLine();
            }
    
            scanner.close();
            
            return phrase;
        }
    
        /**
         * Réalise la césure pour un mot donné.
         * Pour ce faire, examine les différentes façons de couper
         * le mot: entre l'indice debut et l'indice i et entre i et 
         * la longueur du mot (i variant de 1 à la longueur du mot et 
         * debut étant initialisé à 0).
         * Si la régle de césure s'applique à ces deux parties
         * afficher le "-" et passer à la ligne suivante.
         * Puis, faire le même traitement en considérant la portion de mot
         * entre i et longueur du mot (debut prend la valeur de i)
         * @param mot une String représentant un mot de la phrase
         */ 
        static void cesure(String mot) {
            int debut = 0;
            for (int i = 1; i < mot.length(); i++) {
                char c1 = mot.charAt(i - 1);
                char c2 = mot.charAt(i);
                if ((voyelle(c1) && !voyelle(c2))) {
                    String s1 = mot.substring(debut, i);
                    String s2 = mot.substring(i, mot.length());
                    if ((s1.length() > 1) && (s2.length() > 1)) {
                        if (!(queVoyelles(s1) || queVoyelles(s2))) {
                            System.out.println(s1 + "-");
                            debut = i;
                        }
                    }
                }
            }
    
            String s1 = mot.substring(debut, mot.length());
            System.out.println(s1);
        }
    
        /**
         * Teste si un caractère est une voyelle.
         * @param c le caractère à tester
         * @return true si c est une voyelle et false sinon
         */ 
        static boolean voyelle(char c) {
            return ((c == 'a') ||
                        (c == 'e') ||
                        (c == 'i') ||
                        (c == 'o') ||
                        (c == 'u') ||
                        (c == 'y'));
        }
    
        /**
         * Teste si une chaîne de caractères ne contient que des voyelles.
         * @param s la chaîne à tester
         * @return true si s ne contient que des voyelles et false sinon
         */ 
        static boolean queVoyelles(String s) {
            for (int i = 0; i < s.length(); i++) {
                if (!voyelle(s.charAt(i))) {
                    return false;
                }
            }
            return true;
        }
    }


    Exercice 12: Master-Mind(tm) (Modularisation, algorithme, Niveau 3)

      1
      2
      3
      4
      5
      6
      7
      8
      9
     10
     11
     12
     13
     14
     15
     16
     17
     18
     19
     20
     21
     22
     23
     24
     25
     26
     27
     28
     29
     30
     31
     32
     33
     34
     35
     36
     37
     38
     39
     40
     41
     42
     43
     44
     45
     46
     47
     48
     49
     50
     51
     52
     53
     54
     55
     56
     57
     58
     59
     60
     61
     62
     63
     64
     65
     66
     67
     68
     69
     70
     71
     72
     73
     74
     75
     76
     77
     78
     79
     80
     81
     82
     83
     84
     85
     86
     87
     88
     89
     90
     91
     92
     93
     94
     95
     96
     97
     98
     99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    import java.util.Scanner;
    
    class Mastermind {
    
        private static Scanner scanner = new Scanner(System.in);
    
        /**
         * Lancement du Master-Mind(tm).
         * @param args Inutilisé dans ce programme
         */
        public static void main(String[] args) {
            mastermind(4, 6, 10);
        }
    
        /**
         * Tirage d'un entier au hasard entre 1 et max.
         * @param max La valeur maximale pouvant être retournée
         * @return Un entire aléatoire entre 1 et max
         */
        static int hasard(int max) {
            return (1 + (int) (Math.random() * max));
        }
    
        /**
         * Tire une combinaison à deviner. 
         * C'est la référence du tableau qui est passée
         * en paramètre. La méthode tirerCombinaison pourra directement
         * modifier la combinaison en mémoire.
         * Ici, on suppose que n < combinaison.length.
         * @param combinaison Référence vers le tableau à modifier
         * @param n Longueur de la combinaison.
         * @param m Valeur maximale à tirer aléatoirement
         */ 
        static void tirerCombinaison(int[] combinaison, int n, int m) {
            for (int i = 0; i < n; i++) {
                combinaison [i] = hasard(m);
                }
        }
    
        /**
         * Permet de lire la combinaison proposée
         * par le joueur.
         * @param combinaison Tableau dans lequel stocker les valeurs entrées par le
         * joueur
         * @param n Longueur de la combinaison
         */ 
        static void demanderCoup(int[] combinaison, int n) {
            System.out.print("Entrez les ");
            System.out.print(n);
            System.out.print(" chiffres de votre proposition ");
            System.out.println("(terminés par un retour chariot) :");
            for (int i = 0; i < n; i++) {
                combinaison[i] = scanner.nextInt();
            }
        }
    
        /**
         * Permet de comparer la combinaison à deviner avec la 
         * combinaison proposée par le joueur.
         * Dans reponse[0] sera stocké le nombre d'éléments bien devinés 
         * et correctement placés.
         * Dans reponse[1] sera stocké le nombre d'éléments bien devinés
         * mais mal placés.
         * @param n Longueur de la combinaison
         * @param combinaison1 Combinaison proposée par le joueur
         * @param combinaison2 Combinaison à deviner
         * @param reponse Tableau de deux int contenant le nombre de bien placés
         * (index 0) et le nombre de mal placés (index 1)
         * @return true si la bonne combinaison est trouvée et false sinon
         */ 
        static boolean compare(int n, int[] combinaison1, int[] combinaison2,
                    int[] reponse) {
            // nombre de bien placés
            int nbOk = 0;
            // nombre de mal placés
            int nbCol = 0;
            boolean [] marque = new boolean[n];
            boolean trouve = true;
            // cette première boucle sert à trouver 
            // les éléments bien devinés et correctement placés.
            // Le tableau marque permet de marquer de tels
            // éléments pour qu'ils ne soient pas considérés
            // plusieurs fois.
            for (int i = 0; i < n; i++) {
                if (combinaison1 [i] == combinaison2 [i]) {
                    nbOk++;
                    marque[i] = true;
                } else {
                    trouve = false;
                    marque[i] = false;
                }
            }
            // la deuxième boucle suivante sert à identifier les
            // éléments bien devinés mais mal placés.
            for (int i = 0; i < n; i++) {
                if (combinaison1[i] != combinaison2[i]) {
                    int j = 0;
                    boolean trouveMalPlace = false;
                    while ((j < n) && !trouveMalPlace) {
                        if (!marque[j] && (combinaison1[i] == combinaison2[j])) {
                            nbCol++;
                            marque[j] = true;
                            trouveMalPlace = true;
                        }
                        j++;
                    }
                }
            }
    
            reponse[0] = nbOk;
            reponse[1] = nbCol;
            return trouve;
        }
    
        /**
         * Affichage d'une combinaison.
         * @param combinaison Combinaison à afficher
         * @param n Longueur de la combinaison
         */ 
        static void afficheCombinaison(int[] combinaison, int n) {
            for (int i = 0; i < n; i++)
                System.out.print(combinaison[i]);
            System.out.println(" ");
        };
    
        /**
         * Affichage des indications destinées au joueur.
         * @param reponse Tableau de deux int contenant le nombre de bien placés
         * (index 0) et le nombre de mal placés (index 1)
         */ 
        static void afficheReponse(int[] reponse) {
            for (int i = 0; i < reponse[0]; i++)
                System.out.print('#');
            for (int i = 0; i < reponse[1]; i++)
                System.out.print('O');
            System.out.println();
        }
    
        /**
         * Affichage du texte d'acceuil.
         * @param n Longueur du code
         * @param m Valeur maximale permise dans la combinaison
         * @param maxCoups limite de coups autorisée
         */ 
        static void bienvenue(int n, int m, int maxCoups) {
            System.out.print("Pouvez vous trouver ma combinaison de ");
            System.out.print(n);
            System.out.print(" chiffres [compris entre 1 et ");
            System.out.print(m);
            System.out.print(" avec répétitions possibles]\n en moins de ");
            System.out.print(maxCoups);
            System.out.println(" coups ?");
        }
    
        /**
         * Jeu du Master-Mind.
         * Le programme tire une combinaison au hasard.
         * Le joueur cherche à la deviner et fait des propositions de 
         * combinaisons.
         * Le programme indique à chaque coup au joueur combien d'éléments
         * sont bien devinés et correctement placé ou bien devinés mais
         * mal placés.
         * Le jour a droit à <maxCoups> tentatives.
         * @param size Longueur du code à deviner
         * @param maxDigit Valeur maximale pouvant se trouver dans le code
         * @param maxCoups Limite de coups pour trouver la réponse
         */ 
        static void mastermind(int size, int maxDigit, int maxCoups) {
            int[] solution = new int[size];
            int[] proposition = new int[size];
            int nbCoups = 0;
            boolean trouve = false;
            int[] reponse = new int[2];
    
            bienvenue(size, maxDigit, maxCoups);
            tirerCombinaison(solution, size, maxDigit);
    
            do {
                demanderCoup(proposition, size);
                nbCoups++;
                trouve = compare(size, solution, proposition, reponse);
                afficheReponse(reponse);
            } while (!trouve && (nbCoups < maxCoups));
    
            if (trouve) {
                System.out.print("Bravo ! Vous avez trouvé en ");
                System.out.print(nbCoups);
                System.out.println(" coups");
            } else {
                System.out.println("Désolé vous n'avez pas trouvé...");
                System.out.println("La bonne réponse était ");
                afficheCombinaison(solution, size);
                System.out.println(".");
            }
        }
    
    }


    Dernière mise à jour: 13/10/2023  (Revision: 1.2)