Bonjour à tous,

J'aimerais vous soumettre un problème que j'ai du mal à solutionner depuis plusieurs jours.

Voici le contexte :
J'organise régulièrement des tournois de cartes et pour cela un logiciel d'enregistrement des joueurs est fourni. Le souci est qu'il ne fonctionne pas correctement, notamment sur la gestion et création des équipes : il fait jouer de nouveau des joueurs ensemble alors qu'il ne devrait pas car ils se sont déjà rencontrés.

Jei me suis donc donné comme but de développer un petit programme Delphi pour faire le travail. Le souci, cela ne fonctionne pas non plus tel que je le voudrais. Il n'arrive pas à générer tous les matches.

Si on prend comme exemple cette situation :
6 joueurs : J1, J2 , J3, etc.
Ils doivent :
- Tous se rencontrer au moins une fois
- Tous participer à chaque tour
- Ne jouer que contre une seule autre personne par tour (ils ne peuvent pas être à deux endroits en même temps).
- Générer le maximum de tours (si 6 joueurs alors 5 tours (matches) si 8 alors 7, etc.)

Donc chaque joueur participera à 5 matches.

On peut traduire les possibilités de tirage comme suit :

Nom : tableau.png
Affichages : 437
Taille : 2,4 Ko

Les croix étant les possibilités non retenues...

Le seul tirage convenable possible est donc le suivant :
1 match
J1 VS J2 | J3 VS J4 | J5 VS J6
2 match
J1 VS J3 | J2 VS J5 | J4 VS J6
3 match
J1 VS J4 | J2 VS J6 | J3 VS J5
4 match
J1 VS J5 | J2 VS J4 | J3 VS J6
5 match
J1 VS J6 | J4 VS J5 | J3 VS J2

Bien entendu, les matches pouvant être inversés et l’ordre des duos tirés dans le même match aussi.
Exemple :
J1 VS J2 = J2 VS J1
et :
J1 VS J6 | J4 VS J5 | J3 VS J2 = J4 VS J5 | J3 VS J2 | J1 VS J6

Le nombre de joueurs peut aller de 4 à plus de 30.

Je souhaite générer, selon le nombre de joueurs entré, l'intégralité des matches à faire.

Auriez vous une idée ? Un algo ?

Voici le petit bout de code utilisé actuellement et qui fonctionne pour 4 / 8 / 16 / 32 joueurs mais qui ne fonctionne pas pour 6 / 10 / 12 etc. joueurs.

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
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
procedure TForm1.but_genereClick(Sender: TObject);
var Fichier       : TextFile;
    Ligne         : string;
    i, j, k       : integer;
    ListeSousText : String;
    NbGenereation : integer; //permet de savoir le nombre de couple généré
begin
  try
    Listeresult.Items.Clear;//listbox afficher dans l'écran
    Listeresult.Visible := False;
    self.Refresh;
 
    if not dejagenere then //boolean déclaré dans le TFORM afin de savoir si on doit générer ou pas la liste des matchs
    begin
      NbFois := 0;
      if FNE_nomfic.Text = '' then //chargement depuis un fichier texte de la liste des joueurs
      begin
        showmessage('Choisissez un fichier.');
        exit;
      end;
 
      if not FileExists(FNE_nomfic.Text) then
      begin
        showmessage('Fichier inexistant !');
        exit;
      end;
    end;
 
    dejagenere := true;
    Randomize;//pour après lorsque cela fonctionnera tirage des match aléatoire
    Listeresult.Items.Clear;
 
    //boucle pour ajouter  les noms trouvés dans un fichier texte
    //dans une tstringlist
    if Listeinfo.Count = 0 then //liste généré de nom via le fichier texte
    begin
      AssignFile(Fichier,STR_nomfic);
 
      Reset(Fichier);
      while not Eof(Fichier) do
      begin
        ReadLn(Fichier, Ligne);
        Listeinfo.Add(Ligne);
      end;
 
      if (Listeinfo.Count mod 2) <> 0 then //ajout d'un joueur si nb joueur est un nombre impaire
        Listeinfo.Add('Gain Automatique');
 
      CloseFile(Fichier);
    end;
 
    //Arrivé ici on créer autant de liste que possible
    for I := 0 to Listeinfo.Count -1 do
    begin
      ListeSimpleNumJoueur := TStringList.Create;
      for J := 0 to Listeinfo.Count -1 do
      begin
        if I <> J then
          ListeSimpleNumJoueur.Add(IntToStr(j));
      end;
      ListeDesListesPossible.Add(ListeSimpleNumJoueur); //liste contenant l'ensemble des ListeSimpleNumJoueur cré a la creation du TFORM détuite au destroy
    end;
 
    //ici on a LES listes de toutes les possibilités d'adversaire pour tous les joueurs.
    //Maintenant on va créer Les listes des possibilités pour chaque mach
    //pour cela on parcours de manière séquentiel les listes en partant de la première
    ListeDuo.Clear; //tstringlist retenant le duo d'adversaire
    ListeIndice.Clear; //tstringlist retenant les indice des joueurs déjà utilisé  pour ne plus les prendre dans un autre duo
    Listeresult.Items.Clear;
    for K := 0 to Listeinfo.Count -1 do
    begin
      for I := 0 to Listeinfo.Count -1 do
      begin
        //si toutes les possibilités déjà prise alors plus rien a générer dans la liste on sort
        if TStringList(ListeDesListesPossible[i]).count = 0 then
          Break;
        if ListeIndice.IndexOf(IntToStr(i)) = -1 then
        begin
          j := 0;
          try
            while ListeIndice.IndexOf(TStringList(ListeDesListesPossible[i])[j]) <> -1 do
            begin
              inc(J);
            end;
          except
            on e : exception do
              break;
          end;
 
          //ajout du duo
          ListeDuo.Add(Listeinfo[i]+' contre '+Listeinfo[StrToInt(TStringList(ListeDesListesPossible[I])[J])]);
          //ajout de l'exception
          ListeIndice.Add(IntToStr(i));
          ListeIndice.Add(TStringList(ListeDesListesPossible[I])[j]);
          //suppression des possibilitées
          TstringList(ListeDesListesPossible[strtoint(ListeIndice.Strings[ListeIndice.Count-1])]).Delete(TstringList(ListeDesListesPossible[strtoint(ListeIndice.Strings[ListeIndice.Count-1])]).IndexOf(IntToStr(i)));
          TStringList(ListeDesListesPossible[i]).Delete(J);
        end;
      end;
      //à la fin on a le match
      ListeIndice.Clear;//suppression des exceptions
      ListeDuo.Add('********************************');
    end;
    for I := 0 to ListeDuo.Count -1 do
      Listeresult.Items.Add(ListeDuo.Strings[i]);
    Listeresult.Visible := true;
  except
    on e : exception do
    begin
      MessageDlg('Erreur : '+e.Message+ #13#10+ListeComplete.DelimitedText,MtInformation,[MbOk],0);
      dejagenere := False;
    end;
  end;
end;
Je vous remercie par avance.