Nombre aleatoire sans répitition en java

imenenw Messages postés 13 Statut Membre -  
 danimo -
Bonjour à tous,

voilà je veux faire un petit programme en java qui permet de choisir un nombre de 0 à 20 aleatoire sans que celui-ci ne se répete.
pouvez vous m'aider svp?! :(
merci d'avance.

2 réponses

  1. blux Messages postés 2058 Date d'inscription   Statut Modérateur Dernière intervention   3 455
     
    Salut,

    s'il est aléatoire, alors il peut se répéter...

    Par contre, si c'est un "tirage de loto", alors tu dois gérer une chaine de 20 bits, dans lequel tu mettras un bit quand le nombre sort, et lorsque tu tires un nouveau nombre, tu vas vérifier la valeur de ce bit.
    0
    1. KX Messages postés 19031 Statut Modérateur 3 020
       
      La manipulation des bits n'est pas super aisée en Java, et puis 20 bits ça va, mais s'il fallait choisir un nombre 0 et 100000 ça deviendrait compliqué à gérer. De toute façon il est nécessaire de conserver l'ordre dans lequel les valeurs ont été récupérées, donc on peux tester si la valeur tirée au sort a été déjà prise et recommencer si nécessaire. Par contre ce n'est pas très pertinent si la densité est élevée (si on tire beaucoup de valeurs parmi les 20) parce qu'il y aurait beaucoup de conflits. Dans ce cas précis il vaut mieux créer une liste avec toutes les valeurs possibles, en choisir une aléatoirement, et la retirer des possibilités quand on l'a choisit pour recommencer.
      0
    2. imenenw Messages postés 13 Statut Membre
       
      merci blux pour ta réponse mais je ne sais pas comment faire!!! :(
      0
    3. blux Messages postés 2058 Date d'inscription   Statut Modérateur Dernière intervention   3 455
       
      La manipulation des bits n'est pas super aisée en Java,
      Et bien, un tableau a 20 cellules suffira, dans ce cas...

      De toute façon il est nécessaire de conserver l'ordre dans lequel les valeurs ont été récupérées,
      ???

      Par contre ce n'est pas très pertinent si la densité est élevée (si on tire beaucoup de valeurs parmi les 20) parce qu'il y aurait beaucoup de conflits.
      Tu as mal lu l'énoncé : on ne tire pas des valeurs parmi 20... On veut juste des valeurs entre 0 et 20...

      Dans ce cas précis il vaut mieux créer une liste avec toutes les valeurs possibles, en choisir une aléatoirement, et la retirer des possibilités quand on l'a choisit pour recommencer.
      On fait la même chose en topant une case d'un tableau à 20 cellules sans gérer la 'suppression des possibilités quand on l'a choisie'...
      0
    4. KX Messages postés 19031 Statut Modérateur 3 020
       
      "De toute façon il est nécessaire de conserver l'ordre dans lequel les valeurs ont été récupérées"
      Je ne vois pas l'intérêt de tirer successivement des valeurs si on ne conserve pas le résultat.

      "On veut juste des valeurs entre 0 et 20"
      Oui, ça j'ai bien compris, mais si on en a besoin de 20, il va y avoir beaucoup de conflits pour ne pas trouver de doublons, puisqu'on risque à chaque fois retrouver un nombre déjà tiré (il peut être nécessaire de faire une centaine de tirages aléatoires pour avoir les 20 valeurs différentes).

      La "suppression" des possibilités permet de maintenir une durée connue à l'avance du programme, indépendante du tirage aléatoire, puisqu'on aura exactement autant de tirages aléatoires que de valeurs à récupérer (mais avec certes le coût mémoire supplémentaire du deuxième tableau).

      /** Choix de k valeurs entre 0 et n-1 */
      public static int[] alea1(int k, int n)
      {
          boolean[] val = new boolean[n];
          
          int[] tab = new int[k];
          int cpt = 0;
          
          for (int i=0; i<k; i++)
          {
              int r = rand.nextInt(n);
              
              tab[i] = r;
              cpt++;
              
              if (val[r])
                  i--;
              else
                  val[r]=true;
          }
          
          System.out.printf("Nombre de 'random' : %d\n",cpt);
          return tab;
      }
      
      /** Choix de k valeurs entre 0 et n-1 */
      public static int[] alea2(int k, int n)
      {
          int[] val = new int[n];
          for (int i=0; i<n; i++)
              val[i]=i;
          
          int[] tab = new int[k];    
          int cpt = 0;
          
          for (int i=0; i<k; i++)
          {
              int r = rand.nextInt(n-i);
              cpt++;
              
              tab[i] = val[r];
              val[r] = val[n-i-1];
          }
          
          System.out.printf("Nombre de 'random' : %d\n",cpt);
          return tab;
      }
      
      private static void afficher(int[] tab)
      {
          for (int i : tab)
              System.out.printf("%d,",i);
          System.out.println();
      }
      
      public static void main(String...args)
      {
          afficher(alea1(20,20));
          afficher(alea2(20,20));
      }
      0
    5. blux Messages postés 2058 Date d'inscription   Statut Modérateur Dernière intervention   3 455
       
      Je ne vois pas l'intérêt de tirer successivement des valeurs si on ne conserve pas le résultat.
      Tu parles de conserver l'ordre des résultats et ensuite de conserver les valeurs, avoue que ce n'est pas la même chose...

      (il peut être nécessaire de faire une centaine de tirages aléatoires pour avoir les 20 valeurs différentes).
      Sûrement, mais en durée, ça fait combien de microsecondes ?

      Ton code est quand même sacrément compliqué pour une demande aussi simple...
      0
  2. danimo
     
    Salut,

    Tu peux tester cette méthode ( nombresAlea(int mini, int maxi) ), volontairement détaillée, et dans ce petit programme de test.

       import java.util.Random;
       import java.util.Arrays; // pour trier le tableau tab
    
       
       public class TestNombresAleatoirs
       {
          private static int tab[];
       
          //public static int[] nombresAlea(int mini, int maxi)
          public static void nombresAlea(int mini, int maxi)
          {
          // min et max devront être dans les limites ci-dessous
             int miniInteger = Integer.MIN_VALUE;
             int maxiInteger = Integer.MAX_VALUE;
             //System.out.println("miniInteger/maxiInteger = " + miniInteger + "/" + maxiInteger);
          
             int min = mini;
             int max = maxi;
             
             int nbreVal = ((max - min) +1); // sera la taille du tableau.
          
             tab = new int[nbreVal]; // est initialisé a 0 par défaut
             
          // Il faut initialiser le tableau à une valeur hors min/max
             int valInit = min -1; // ou bien max +1
             
          // on l'initialise à min -1 (ou à max +1) sinon le num. éventuel 0 serait un doublon   
             for (int i = 0; i <nbreVal; i++)
                tab[i] = valInit;
          
             int i1 = 0;
             int i2 = 0;
             boolean encore = true;
          
             while(encore)
             {
                for (i1 = 0; i1 <nbreVal; i1++)
                {
                   encore = false; // sera forcé true si doublon
                   Random r = new Random();
                   int aI = min + r.nextInt(nbreVal);
                   
                   for (i2 = 0; i2 <nbreVal; i2++)
                   {
                      if (aI == tab[i2]) // doublon ?
                      {
                         encore = true;
                         //System.out.println("Le nouveau num. obtenu:\n" + aI
                            //+ " est un doublon, on ne le prend pas.(i2 = " + i2 + ")\n");
                         i1--;
                         break;
                      }
                   }
                   
                   if (encore == false)
                      tab[i1] = aI;   // ou bien, utilisation immédiate
                }
             }
            //return tab; // si la méthode nombresAlea(...) est dans une classe externe
          }
       
          public static void main(String args[])
          {
             int mini = 0;
             int maxi = 20;
             nombresAlea(mini, maxi); // prévoir la saisie de mini et maxi
              
             //Arrays.sort(tab);
             // Le tri ci-dessus est fait pour contrôler facilement qu'on a bien tous les nombres attendus
             // surtout s'il sont nombreux puisqu'ils sont rangés dans tab[] dans un ordre ... aléatoire
          	// Ne pas trier en utilisation normale
             
             for (int i = 0; i <tab.length; i++)
             {
                System.out.println("num. " + (i +1) + ": " + tab[i]);
             }
          }
       }
    

    -1