IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

 Delphi Discussion :

Random numéro unique


Sujet :

Delphi

  1. #1
    Membre à l'essai
    Profil pro
    Inscrit en
    Janvier 2008
    Messages
    28
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Janvier 2008
    Messages : 28
    Points : 12
    Points
    12
    Par défaut Random numéro unique
    Bonsoir à tous, voilà je développe une petite appli pour simuler un loto (Bingo en France?). J'ai ma grille de 90 numéros pour le contrôle et à chaque tirage d'un numéro à partir d'une pression sur un bouton la case concernée change de couleur. Jusque là tout va bien mais j'ai un problème avec la fonction random, je n'arrive pas à faire en sorte que chaque numéro soit tiré une seule fois.
    J'imagine qu'il doit être possible de faire en sorte qu'à chaque pression du bouton le tirage aléatoire se fasse que sur les chiffres restants, mais là je sèche et j'en appelle aux pros de delphi :-)

    Merci d'avance pour tout coup de main.

  2. #2
    Rédacteur
    Avatar de evarisnea
    Homme Profil pro
    Ingénieur intégration
    Inscrit en
    Juin 2005
    Messages
    1 957
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Cameroun

    Informations professionnelles :
    Activité : Ingénieur intégration
    Secteur : Transports

    Informations forums :
    Inscription : Juin 2005
    Messages : 1 957
    Points : 4 384
    Points
    4 384
    Par défaut


    pas sûr qu'une fonction toute faite existe pour cela.
    pour avoir des nombres qui ne se répètent pas, tu dois après chaque génération de nombre aléatoire tester si celui-ci ne se trouve pas déjà dans la listes des nombres déjà générés avant de l'y ajouter !

  3. #3
    Membre à l'essai
    Profil pro
    Inscrit en
    Janvier 2008
    Messages
    28
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Janvier 2008
    Messages : 28
    Points : 12
    Points
    12
    Par défaut
    Hello,

    Je pensais bien que la solution miracle n'existerait pas :-)

    Là où je bute c'est pour mettre en mémoire les chiffres déjà dehors et les tester à chaque tirage. J'imaginais l'utilisation d'un memo avec mes 90 numéros et à chaque tirage supprimer celui qui vient de sortir, de cette manière ça évite les doublons. Ce serait une solution mais est-ce qu'un memo est fait pour ça ou il y a mieux?

  4. #4
    Membre averti Avatar de archonte
    Profil pro
    Inscrit en
    Mai 2007
    Messages
    341
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2007
    Messages : 341
    Points : 392
    Points
    392
    Par défaut
    Une piste, pour te détailler un peu le post d'evarisnea :
    - tester si un numéro est déjà sorti est différent de l'affichage : ton TMemo n'est là que pour afficher des données ...
    - si tu as les numéros de 1 à 90, un tableau Oui/Non des valeurs déjà tirées peut faire l'affaire. Par exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    var
      NumerosDejaTires : array[1..90] of boolean;
    // ne pas oublier d'initialiser les 90 valeurs à False avant le premier tirage !
    - à chaque nouveau tirage, tu obtiens un integer i, et tu testes si NumeroDejaTires[i] est vrai :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
      If NumeroDejaTires[i] Then
    - donc 2 réponses possibles :
    -- le numéro a déjà été tiré : il faut opérer un nouveau tirage;
    -- le numéro sort pour la première fois, tu peux l'afficher.

    Bon, ce bout de code demanderait a être optimisé, par exemple avec un tableau de n=90 valeurs (de 1 à 90) initialement, puis, à chaque nouveau tirage, on ne conserve que les n-1 valeurs restant à tirer et on opère un random sur n-1 valeurs, et ainsi de suite.

    Je ne sais pas, par contre si cette façon de procéder conserve l'équiprobabilité de chaque numéro tout au long du tirage (à la fonction random près) ?
    "Je n'ai jamais rencontré d'homme si ignorant qu'il n'eut quelque chose à m'apprendre."
    Galilée

  5. #5
    Membre à l'essai
    Profil pro
    Inscrit en
    Janvier 2008
    Messages
    28
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Janvier 2008
    Messages : 28
    Points : 12
    Points
    12
    Par défaut
    Citation Envoyé par archonte Voir le message
    Bon, ce bout de code demanderait a être optimisé, par exemple avec un tableau de n=90 valeurs (de 1 à 90) initialement, puis, à chaque nouveau tirage, on ne conserve que les n-1 valeurs restant à tirer et on opère un random sur n-1 valeurs, et ainsi de suite.
    Ca commence à devenir un peu plus clair pour moi mais comment je fais pour supprimer les numéros au fur et à mesure qu'ils sortent? J'ai bien compris (j'espère) le n-1 valeurs mais de cette manière au premier tirage le random se fera sur 1-90, au second 1-89, etc.... Ca va bien réduire le nombre de numéros restants mais ça ne me dira pas quels numéros sont disponibles pour la suite du tirage non?

  6. #6
    Membre averti Avatar de archonte
    Profil pro
    Inscrit en
    Mai 2007
    Messages
    341
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2007
    Messages : 341
    Points : 392
    Points
    392
    Par défaut
    Bon , par exemple, une fiche avec 1 Memo pour afficher les résultats, une StringList (MaListe) contenant les numéros à tirer et 2 boutons : RAZ et Tirer :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
     
    // penser à initialiser la StringList et à la libérer en fin d'utilisation !
    procedure TFHasard.BtnRAZClick(Sender: TObject);
    var
      i : integer;
    begin
      Randomize;
      Memo1.Clear;
      MaListe.Clear;
      for i := 1 to 90 do MaListe.Add(IntToStr(i));
      // initialement, l'item 0 vaut 1, le 1 vaut 2, etc ...
    end;
     
    procedure TFHasard.BtnTirerClick(Sender: TObject);
    var
      n : integer;
      i : integer;
    begin
      n := random(MaListe.Count);
      if ((n>=0) AND (MaListe.Count > 0)) then
      begin
        Memo1.Lines.Add(MaListe[n]);
        MaListe.Delete(n); 
      end;
    end;
    "Je n'ai jamais rencontré d'homme si ignorant qu'il n'eut quelque chose à m'apprendre."
    Galilée

  7. #7
    Membre chevronné

    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2009
    Messages
    935
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Aveyron (Midi Pyrénées)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2009
    Messages : 935
    Points : 1 765
    Points
    1 765
    Par défaut
    Citation Envoyé par archonte Voir le message
    Bon , par exemple, une fiche avec 1 Memo pour afficher les résultats, une StringList (MaListe) contenant les numéros à tirer et 2 boutons : RAZ et Tirer :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
     
    // penser à initialiser la StringList et à la libérer en fin d'utilisation !
    procedure TFHasard.BtnRAZClick(Sender: TObject);
    var
      i : integer;
    begin
      Randomize;
      Memo1.Clear;
      MaListe.Clear;
      for i := 1 to 90 do MaListe.Add(IntToStr(i));
      // initialement, l'item 0 vaut 1, le 1 vaut 2, etc ...
    end;
     
    procedure TFHasard.BtnTirerClick(Sender: TObject);
    var
      n : integer;
      i : integer;
    begin
      n := random(MaListe.Count);
      if ((n>=0) AND (MaListe.Count > 0)) then
      begin
        Memo1.Lines.Add(MaListe[n]);
        MaListe.Delete(n); 
      end;
    end;
    Salut

    Je pense que se servir d'une StringList pour ca, c'est contre-performant.
    Voila comment je verrai ca ...

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    var
      NumTirés : array [1..90] of boolean;
      NbTirés : integer = 0;
     
     
    Function TirerNouveauNombre:integer;
    var i, j : integer;
    begin
      Result:=0;
      i:=0;
      j:=random(90-NbTirés)+1;
     
      repeat
        if not NumTirés[Result+1] then inc(i);
        inc(Result);
      until i=j;
     
      NumTirés [Result]:=true;
      inc(NbTirés);
    end;
    (code non testé)

    Voila, bonne chance

  8. #8
    Membre confirmé
    Homme Profil pro
    Santé
    Inscrit en
    Septembre 2010
    Messages
    290
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Santé
    Secteur : Santé

    Informations forums :
    Inscription : Septembre 2010
    Messages : 290
    Points : 534
    Points
    534
    Par défaut
    Bonjour,

    Pour ce genre de problème, j'utilise la fonction ci-dessous dont tu peux t'inspirer ou adapter.

    Le principe est le suivant :
    - on fournit à la fonction une liste ordonnée.
    - la fonction mélange aléatoirement les éléments de la liste
    - il ne reste plus qu'à utiliser les éléments de la liste dans l'ordre des index pour avoir un tirage genre Loto.




    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
             {Mélange aléatoirement les pointeurs d'un TList.}
    procedure GetRndList(var SrcList : TList);
      var
              RndList : TList;
              i,RndIndex, Count : Integer;
      begin
      Count := SrcList.Count; //Le nombre d'entrées de la TList passée en variable.
      if Count < 2 then exit; //On n'est pas des gogos!
      RndList := TList.Create;//On crée une Tlist temporaire qui recevra les pointeurs dans le désordre.
      try
        RndList.Capacity :=  SrcList.Capacity;//Allocation de mémoire en une seule fois.
        for i := 1 to Count do begin          //Autant de fois qu'il y a d'entrées.
          RndIndex := Random(Count);          //On tire un indice au hasard.
          RndList.Add(SrcList[RndIndex]);     //On ajoute le pointeur tiré à la TList temporaire.
          Dec(Count);                         //On décrémente le nombre d'indices.
          SrcList[RndIndex] := SrcList[Count];//On élimine le pointeur tiré en le remplaçant par le dernier de la liste
        end;
        SrcList.Assign(RndList,laCopy); //Enfin on copie la liste temporaire dans la liste passée en variable.
      finally  RndList.Free;  end;      //On libère la mémoire.
    end;

  9. #9
    Membre à l'essai
    Profil pro
    Inscrit en
    Janvier 2008
    Messages
    28
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Janvier 2008
    Messages : 28
    Points : 12
    Points
    12
    Par défaut
    Merci à tous pour vos réponses, maintenant il n'y a plus qu'à arriver à mettre vos conseils en pratique et c'est pas gagné. J'ai l'impression que je vais revenir dans pas longtemps pour crier à l'aide :-)

  10. #10
    Rédacteur/Modérateur
    Avatar de Andnotor
    Inscrit en
    Septembre 2008
    Messages
    5 685
    Détails du profil
    Informations personnelles :
    Localisation : Autre

    Informations forums :
    Inscription : Septembre 2008
    Messages : 5 685
    Points : 13 097
    Points
    13 097
    Par défaut
    Même principe que Caribensila, mais en passant par un tableau:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    type
      TNumList = array [1..90] of byte;
     
    function GetList :TNumList;
    var
      b : byte;
      r : byte;
      i : Integer;
     
    begin
      //Remplissage
      for i := low(Result) to high(Result) do
        Result[i] := i;
     
      for i := low(Result) to high(Result) do
      begin
        //Dernier élément
        b := Result[high(Result)];
     
        //Index aléatoire entre Low et position courante
        r := low(Result) +Random(i -Low(Result) +1);
     
        //Décalage
        Move(Result[r], Result[r+1], high(Result) -r);
     
        //Insertion
        Result[r] := b;
      end;
    end;
    Et si vraiment il faut un TList, une petite simplification :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    procedure GetRndList(aList :TList);
    var
      r : integer;
      i : Integer;
     
    begin
      for i := 1 to aList.Count do
      begin
        r := Random(i);
        aList.Move(aList.Count -1, r);
      end;
    end;

  11. #11
    Membre confirmé
    Homme Profil pro
    Santé
    Inscrit en
    Septembre 2010
    Messages
    290
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Santé
    Secteur : Santé

    Informations forums :
    Inscription : Septembre 2010
    Messages : 290
    Points : 534
    Points
    534
    Par défaut
    @Andnotor

    Et si vraiment il faut un TList, une petite simplification ...

    Petite, mais costaude !
    (Perso, j'aurais quand même gardé le passage de paramètre par "variable", non ?)

    En tout cas, je ne regrette pas de m'être inscrit à ce forum.

  12. #12
    Rédacteur/Modérateur
    Avatar de Andnotor
    Inscrit en
    Septembre 2008
    Messages
    5 685
    Détails du profil
    Informations personnelles :
    Localisation : Autre

    Informations forums :
    Inscription : Septembre 2008
    Messages : 5 685
    Points : 13 097
    Points
    13 097
    Par défaut
    Citation Envoyé par Caribensila Voir le message
    Perso, j'aurais quand même gardé le passage de paramètre par "variable", non ?
    Inutile puisque la liste n'est pas créée dans la procédure
    Mais on aurait pu mettre const pour éviter la copie locale du pointeur.

  13. #13
    Membre à l'essai
    Profil pro
    Inscrit en
    Janvier 2008
    Messages
    28
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Janvier 2008
    Messages : 28
    Points : 12
    Points
    12
    Par défaut
    Merci à tous pour vos conseils. Grâce (une fois de plus) à ce forum j'ai eu la réponse à mon problème et je peux aller de l'avant.

  14. #14
    Expert éminent sénior
    Avatar de Paul TOTH
    Homme Profil pro
    Freelance
    Inscrit en
    Novembre 2002
    Messages
    8 964
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Freelance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2002
    Messages : 8 964
    Points : 28 430
    Points
    28 430
    Par défaut
    je suis pour le tableau

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
     
    var
      Boules : array[0..89] of Byte;
      Count  : Integer;
     
    // on a 90 boules
    procedure init;
    var
      i : Integer;
    begin
      for i := 0 to 89 do Boules[i] := i + 1;
      Count := 90;
    end;
     
    // prendre une boule au pif, et la remplacer par la dernière
    function GetBoule: Byte;
    var
      i : Integer;
    begin
      i := Random(Count);
      Result := Boules[i];
      Dec(Count);
      if Count > 0 then
      begin
        Boules[i] := Boules[Count];
        Boules[Count] := Result;  // éventuellement pour ne pas repasser par init
                                  // sans perdre la boule :)
                                  // il suffit de remettre Count à 90 pour un nouveau tirage
      end;
    end;
    Developpez.com: Mes articles, forum FlashPascal
    Entreprise: Execute SARL
    Le Store Excute Store

Discussions similaires

  1. Réponses: 1
    Dernier message: 08/01/2010, 13h18
  2. numéros unique ordinateur
    Par totofe dans le forum Ordinateurs
    Réponses: 6
    Dernier message: 03/12/2008, 21h35
  3. Réponses: 3
    Dernier message: 22/08/2008, 11h39
  4. [Système] générer numéro unique
    Par cd090580 dans le forum Langage
    Réponses: 4
    Dernier message: 17/06/2007, 17h51
  5. Numéro unique ?
    Par Oufti dans le forum SQL Procédural
    Réponses: 12
    Dernier message: 05/06/2006, 19h59

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo