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

Lazarus Pascal Discussion :

Tirage aléatoire des éléments d'une liste [Lazarus]


Sujet :

Lazarus Pascal

  1. #1
    Membre à l'essai
    Homme Profil pro
    retraité
    Inscrit en
    Août 2017
    Messages
    30
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : retraité
    Secteur : Service public

    Informations forums :
    Inscription : Août 2017
    Messages : 30
    Points : 17
    Points
    17
    Par défaut Tirage aléatoire des éléments d'une liste
    Dans un edit, je voudrais lire une cellule de tableau Excel de manière aléatoire mais je ne veux pas que le même champ s'affiche 2 fois.
    Aussi, j'ai eu l'idée de recourir à un StringList :
    - génération d'une liste reprenant la numérotation des champs (à partir de la ligne 2),
    - tirage d'un nombre aléatoire,
    - affichage de champ (ligne-n° tiré).

    Or, le programme me tire plusieurs fois le même n° (on pourrait penser qu'il a mis en mémoire chaque champ).
    Où est l'erreur ?
    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
    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
     
     
    public
        ExcelApplication1:variant;
     
     
    procedure TForm1.FormShow(Sender: TObject);
    var
      path:variant;
      i, NbQ:integer;
    begin
       path := ExtractFilePath(Application.ExeName);  // chemin de l'application
       path := path+'\QR.xlsx';
       ExcelApplication1:= CreateOleObject('Excel.Application');
       ExcelApplication1.visible:=false;
       ExcelApplication1.Workbooks.Open(path);
       NbQ:=strtoint(string(ExcelApplication1.Cells[2,10].Value))+1; // Nb enr
       {création liste}
       Str := TStringList.Create;
       For i := 2 To NbQ Do
         begin
             Str.Add(inttostr(i));
             listbox1.Items.Add(Str.Strings[i-2]);
         end;
        //randomize;
    end; 
     
     
    procedure TForm1.BtnQClick(Sender: TObject);
    var
     l: integer;
     tir, i:integer;
    begin
      randomize;
      tir:=Random(Str.Count-1);
      edit4.Text:='tir : '+inttostr(tir);
      edit5.Text:='reste : '+inttostr(Str.Count);
      {-------MàJ de la liste-------}
      Str.Delete(tir);
      listbox1.Clear;
      For i := 1 To Str.Count-1 Do
        listbox1.Items.Add(Str.Strings[i-1]);
      {-------Affichage des valeurs-------}
      if Str.count<>0 then
         begin
           l:= strtoint(Str.Strings[tir]);
           listbox2.Items.Add(inttostr(l-1));
           edit3.Text:=string(ExcelApplication1.Cells[l,3].Value);  // l,c
         end
      else BtnQ.Enabled:=false;
    end;
     
    procedure TForm1.FormClose(Sender: TObject); //var CloseAction: TCloseAction);
    begin
       ExcelApplication1.DisplayAlerts := False; //mess enregistrer fichier
       ExcelApplication1.quit;
       ExcelApplication1:= Unassigned;
       Str.Free;
    end;

  2. #2
    Expert éminent sénior
    Avatar de Jipété
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    10 729
    Détails du profil
    Informations personnelles :
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 10 729
    Points : 15 133
    Points
    15 133
    Par défaut
    Bonsoir,

    Citation Envoyé par bern59 Voir le message
    - génération d'une liste reprenant la numérotation des champs (à partir de la ligne 2),
    - tirage d'un nombre aléatoire,
    - affichage de champ (ligne-n° tiré).
    Dans cette suite de trois instructions, il n'y a rien qui dit, entre 2 et 3, while déjà_tiré(n° tiré) do tire_à_nouveau.

    Quand tu joues à la roulette, le même numéro peut sortir plusieurs fois, idem en jouant aux dés, etc.
    Il a à vivre sa vie comme ça et il est mûr sur ce mur se creusant la tête : peutêtre qu'il peut être sûr, etc.
    Oui, je milite pour l'orthographe et le respect du trait d'union à l'impératif.
    Après avoir posté, relisez-vous ! Et en cas d'erreur ou d'oubli, il existe un bouton « Modifier », à utiliser sans modération
    On a des lois pour protéger les remboursements aux faiseurs d’argent. On n’en a pas pour empêcher un être humain de mourir de misère.
    Mes 2 cts,
    --
    jp

  3. #3
    Membre chevronné

    Homme Profil pro
    Retraité
    Inscrit en
    Juin 2012
    Messages
    1 035
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Retraité
    Secteur : Biens de consommation

    Informations forums :
    Inscription : Juin 2012
    Messages : 1 035
    Points : 2 053
    Points
    2 053
    Par défaut
    J'ai du mal à suivre l'ensemble mais un truc me titille:
    Cette fonction ne fait que supprimer une entrée selon l'index donné. Ex:
    str.delete (4) va supprimer la cinquième ligne ( L'index commence à 0 ) dans la liste et c'est tout. Si il s'agit de supprimer plusieurs entrées en fonction d'une valeur donnée il faut le faire dans une boucle.

  4. #4
    Membre à l'essai
    Homme Profil pro
    retraité
    Inscrit en
    Août 2017
    Messages
    30
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : retraité
    Secteur : Service public

    Informations forums :
    Inscription : Août 2017
    Messages : 30
    Points : 17
    Points
    17
    Par défaut stringlist
    Citation Envoyé par mm_71 Voir le message
    J'ai du mal à suivre l'ensemble mais un truc me titille:
    Cette fonction ne fait que supprimer une entrée selon l'index donné. Ex:
    str.delete (4) va supprimer la cinquième ligne ( L'index commence à 0 ) dans la liste et c'est tout. Si il s'agit de supprimer plusieurs entrées en fonction d'une valeur donnée il faut le faire dans une boucle.
    ll s'agit de supprimer le n°tiré du stringlist puis de procéder à un nouveau tirage par appui sur le bouton (affichage aléatoire sur demande).

  5. #5
    Rédacteur/Modérateur

    Avatar de Roland Chastain
    Homme Profil pro
    Enseignant
    Inscrit en
    Décembre 2011
    Messages
    4 072
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Décembre 2011
    Messages : 4 072
    Points : 15 462
    Points
    15 462
    Billets dans le blog
    9
    Par défaut
    Bonjour !

    C'est peut-être un détail mais Randomize est mal placé. Il ne doit être appelé qu'une fois, au lancement de l'application (et non pas à chaque appui sur le bouton).
    Mon site personnel consacré à MSEide+MSEgui : msegui.net

  6. #6
    Modérateur
    Avatar de tourlourou
    Homme Profil pro
    Biologiste ; Progr(amateur)
    Inscrit en
    Mars 2005
    Messages
    3 858
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Biologiste ; Progr(amateur)

    Informations forums :
    Inscription : Mars 2005
    Messages : 3 858
    Points : 11 299
    Points
    11 299
    Billets dans le blog
    6
    Par défaut
    Une technique pourrait être de peupler une liste de chaînes sans doublons (TStringList.Duplicates := dupIgnore) par des tirages aléatoires entre les bornes choisies, jusqu'à ce que le Count soit celui voulu (cad la largeur de l'intervalle, par exemple, mais pas plus !). Cette liste sera une succession aléatoire des questions de x à Nb, il suffira d'en retire le 1er ou le dernier élément à chaque fois qu'on a besoin d'une question au hasard.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    List.Duplicates := dupIgnore;
    while List.Count < NbQ-2+1 do 
     List.Add( IntToStr( RandomRange(2, NbQ) ) );
     
    while List.Count > 0 do
    begin
      Q := List[0];
      List.Delete(0);
      // dosomething with Q
    end;
    Delphi 5 Pro - Delphi 11.3 Alexandria Community Edition - CodeTyphon 6.90 sous Windows 10 ; CT 6.40 sous Ubuntu 18.04 (VM)
    . Ignorer la FAQ Delphi et les Cours et Tutoriels Delphi nuit gravement à notre code !

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

    Informations forums :
    Inscription : Septembre 2008
    Messages : 5 693
    Points : 13 126
    Points
    13 126
    Par défaut
    L'erreur est ici : tir:=Random(Str.Count-1).

    Ce que tu veux est récupérer le contenu d'un élément en fonction d'un nombre aléatoire. Random(Str.Count-1) est l'indice de l'élément.

    Ce qui donne :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    i   := Random(Str.Count-1);
    tir := StrToInt(Str[i]);
     
    Str.Delete(i);
    La suite ne joue pas non plus. Str.Delete(tir) suivi d'un Str.Strings[tir] (qui pourrait simplement s'écrire str[tir]). Dans le meilleur des cas (!) la valeur est fausse puisque l'élément a déjà été supprimé (on pointe sur un autre) et dans le pire, si tir vallait Count-1, une erreur "indice hors limite" est générée. Bref, que du malheur !

  8. #8
    Rédacteur/Modérateur

    Avatar de Roland Chastain
    Homme Profil pro
    Enseignant
    Inscrit en
    Décembre 2011
    Messages
    4 072
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Décembre 2011
    Messages : 4 072
    Points : 15 462
    Points
    15 462
    Billets dans le blog
    9
    Par défaut
    Bonsoir !

    Citation Envoyé par Andnotor Voir le message
    Bref, que du malheur !
    J'ajouterai que toutes ces conversions, de nombre en chaîne, puis de de chaîne en nombre ne facilitent pas l'attention.

    Autrement l'idée de la liste était bonne, mais alors pourquoi pas (par exemple) un simple tableau dynamique de nombres entiers, avec une fonction qui pioche dans le tableau et se charge de supprimer l'élément ?

    Voici un exemple qui renvoie dans un ordre aléatoire les dix nombres de 0 à 9.

    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
    type
      TBytes = array of byte;
     
    function RandomPick(var a: TBytes): byte;
    var
      r: integer;
    begin
      r := Random(Length(a)) + Low(a);
      result := a[r];
      a[r] := a[High(a)];
      SetLength(a, Length(a) - 1);
    end;
     
    var
      a: TBytes;
      i: integer;
     
    begin
      Randomize;
     
      SetLength(a, 10);
     
      for i := 0 to 9 do a[i] := i;
     
      while Length(a) > 0 do
        WriteLn(RandomPick(a));
    end.
    "randompick.exe"
    Process started (PID=7008) >>>
    9
    1
    2
    7
    8
    3
    5
    0
    4
    6
    <<< Process finished (PID=7008). (Exit code 0)
    Mon site personnel consacré à MSEide+MSEgui : msegui.net

  9. #9
    Rédacteur/Modérateur

    Avatar de Roland Chastain
    Homme Profil pro
    Enseignant
    Inscrit en
    Décembre 2011
    Messages
    4 072
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Décembre 2011
    Messages : 4 072
    Points : 15 462
    Points
    15 462
    Billets dans le blog
    9
    Par défaut
    Citation Envoyé par tourlourou Voir le message
    Une technique pourrait être de peupler une liste de chaînes sans doublons (TStringList.Duplicates := dupIgnore) par des tirages aléatoires entre les bornes choisies, jusqu'à ce que le Count soit celui voulu
    Bonsoir tourlourou !

    C'est barbare comme méthode.
    Mon site personnel consacré à MSEide+MSEgui : msegui.net

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

    Informations forums :
    Inscription : Septembre 2008
    Messages : 5 693
    Points : 13 126
    Points
    13 126
    Par défaut
    @Roland

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    function RandomPick(var a: TBytes): byte;
    var
      r: integer;
    begin
      r := Random(High(a));
      result := a[r];
      a[r] := a[High(a)];
      SetLength(a, High(a));
    end;

  11. #11
    Membre à l'essai
    Homme Profil pro
    retraité
    Inscrit en
    Août 2017
    Messages
    30
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : retraité
    Secteur : Service public

    Informations forums :
    Inscription : Août 2017
    Messages : 30
    Points : 17
    Points
    17
    Par défaut stringlist
    Merci à tous, j'ai rectifié mon code, en autre le Str.Delete était mal placé.
    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
     
    tir:=Random(Str.Count);  
     
      {-------MàJ de la liste-------}
      listbox1.Clear;
      For i := 1 To Str.Count Do    
        listbox1.Items.Add(Str.Strings[i-1]);
      {-------Affichage des valeurs-------}
      if Str.count<>0 then
         begin
           l:= strtoint(Str.Strings[tir]);
           if l=53 then showmessage('ok');
           listbox2.Items.Add(inttostr(l)); 
           Str.Delete(tir);       
           edit3.Text:=string(ExcelApplication1.Cells[l,3].Value);  // l,c
         end
      else BtnQ.Enabled:=false;

  12. #12
    Modérateur
    Avatar de tourlourou
    Homme Profil pro
    Biologiste ; Progr(amateur)
    Inscrit en
    Mars 2005
    Messages
    3 858
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Biologiste ; Progr(amateur)

    Informations forums :
    Inscription : Mars 2005
    Messages : 3 858
    Points : 11 299
    Points
    11 299
    Billets dans le blog
    6
    Par défaut
    Citation Envoyé par Roland Chastain Voir le message
    C'est barbare comme méthode.
    Bonsoir Roland, la barbarie a parfois du bon !

    [EDIT] La preuve : http://www.grildesbarbares.com/
    Delphi 5 Pro - Delphi 11.3 Alexandria Community Edition - CodeTyphon 6.90 sous Windows 10 ; CT 6.40 sous Ubuntu 18.04 (VM)
    . Ignorer la FAQ Delphi et les Cours et Tutoriels Delphi nuit gravement à notre code !

  13. #13
    Rédacteur/Modérateur

    Avatar de Roland Chastain
    Homme Profil pro
    Enseignant
    Inscrit en
    Décembre 2011
    Messages
    4 072
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Décembre 2011
    Messages : 4 072
    Points : 15 462
    Points
    15 462
    Billets dans le blog
    9
    Par défaut
    Citation Envoyé par tourlourou Voir le message
    Bonsoir Roland, la barbarie a parfois du bon !

    [EDIT] La preuve : http://www.grildesbarbares.com/
    Certainement.

    Ah, Senlis... Quelle belle petite ville ! C'est là que j'ai fait mes classes. Je me croyais dans une histoire de Gérard de Nerval, à cause des noms de lieux.

    Citation Envoyé par Andnotor Voir le message
    @Roland

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    function RandomPick(var a: TBytes): byte;
    var
      r: integer;
    begin
      r := Random(High(a));
      result := a[r];
      a[r] := a[High(a)];
      SetLength(a, High(a));
    end;
    Oui, d'accord. Euh, sauf pour la partie en rouge. Là je pense que c'est bien Length(). En revanche, nous sommes d'accord que Low() ne sert à rien.
    Mon site personnel consacré à MSEide+MSEgui : msegui.net

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

    Informations forums :
    Inscription : Septembre 2008
    Messages : 5 693
    Points : 13 126
    Points
    13 126
    Par défaut
    Citation Envoyé par Roland Chastain Voir le message
    Oui, d'accord. Euh, sauf pour la partie en rouge. Là je pense que c'est bien Length(). En revanche, nous sommes d'accord que Low() ne sert à rien.
    Pour 10 éléments, le tirage sera de 0 à 9, donc de 0 à High

  15. #15
    Rédacteur/Modérateur

    Avatar de Roland Chastain
    Homme Profil pro
    Enseignant
    Inscrit en
    Décembre 2011
    Messages
    4 072
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Décembre 2011
    Messages : 4 072
    Points : 15 462
    Points
    15 462
    Billets dans le blog
    9
    Par défaut
    Citation Envoyé par Andnotor Voir le message
    Pour 10 éléments, le tirage sera de 0 à 9, donc de 0 à High
    Mais justement pour faire un tirage de 0 à 9, il faut appeler Random(10), non ? Enfin c'est ce que j'ai toujours cru.
    Mon site personnel consacré à MSEide+MSEgui : msegui.net

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

    Informations forums :
    Inscription : Septembre 2008
    Messages : 5 693
    Points : 13 126
    Points
    13 126
    Par défaut
    Tu as raison, au temps pour moi

  17. #17
    Rédacteur/Modérateur

    Avatar de Roland Chastain
    Homme Profil pro
    Enseignant
    Inscrit en
    Décembre 2011
    Messages
    4 072
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Décembre 2011
    Messages : 4 072
    Points : 15 462
    Points
    15 462
    Billets dans le blog
    9
    Par défaut
    Citation Envoyé par Andnotor Voir le message
    Tu as raison, au temps pour moi
    Même le grand Homère somnole quelquefois.
    Mon site personnel consacré à MSEide+MSEgui : msegui.net

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 6
    Dernier message: 08/03/2012, 15h40
  2. affichage erroné d'une chaîne de caractères sous FF
    Par laurentSc dans le forum Langage
    Réponses: 4
    Dernier message: 27/02/2011, 22h45
  3. [PHP 5.3] Affichage erroné après modification de fichier hosts
    Par Hoder dans le forum Langage
    Réponses: 0
    Dernier message: 15/11/2010, 13h00
  4. affichage erronée dans textbox
    Par saffff dans le forum Windows Forms
    Réponses: 0
    Dernier message: 18/06/2010, 22h05

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