Mélanger un tableau d'entier ou autre?

Signaler
Messages postés
13
Date d'inscription
mardi 8 mars 2005
Statut
Membre
Dernière intervention
28 février 2006
-
cs_coq
Messages postés
6352
Date d'inscription
samedi 1 juin 2002
Statut
Modérateur
Dernière intervention
2 août 2014
-
Bonjour,

j'aimerais savoir si quelqu'un connaît un algorithme de mélange d'un tableau en c# ?



Merci!!
A voir également:

23 réponses

Messages postés
4936
Date d'inscription
lundi 17 février 2003
Statut
Modérateur
Dernière intervention
14 février 2014
32
en fait, la technique est relativement simple... il fait procéder comme si tu allais trier ton tableau...

Tu commences par créer une classe qui implémente IComparer :


public
class
Melangeur :
IComparer {

private
static
Random rnd;

static Melangeur() {
rnd =
new
Random();
}



public
int Compare(
object x,
object y) {

if (x.Equals(y))

return 0;

else {

return rnd.Next(-1, 1);
}
}

}

ensuite, il suffit de trier ton tableau :


int[] toto =
new
int[16];

Array.Sort(toto,
new
Melangeur());

et voila, c'est fini.


Sébastien FERRAND (
blog)
[Microsoft MVP Visual C#]
Messages postés
794
Date d'inscription
vendredi 24 septembre 2004
Statut
Membre
Dernière intervention
19 août 2008
9
Très sympa comme méthode :)
Messages postés
13
Date d'inscription
mardi 8 mars 2005
Statut
Membre
Dernière intervention
28 février 2006

Merci, pour cette solution même si je n'en comprends pas tout le fonctionnement... en tout cas ça marche! Merci!
Messages postés
13
Date d'inscription
mardi 8 mars 2005
Statut
Membre
Dernière intervention
28 février 2006

Si quelqu'un pourrait?
En faite cette méthode, mais je la comprend pas tout à fait. Et le problème, c'est qu'environ une fois sur vingt Array.Sort(toto,
new
Melangeur()); me sort une erreur:

"Une exception non gérée du type 'System.ArgumentException' s'est produite dans mscorlib.dll

Informations supplémentaires :

IComparer (ou les méthodes IComparable dont il dépend) n'a pas retourné zéro lorsque Array.Sort a appelé x.

CompareTo(x). x : Poker.Card Type de x : Card Le IComparer : Poker.Shaker."

Si quelqu'un pourrait me dire une autre solution ou alors m'aider à trouver le problème.
Information complémentaire:
J'utilise cette méthode pour mélanger un tableau de carte dans un jeu de poker.

Merci
Messages postés
4936
Date d'inscription
lundi 17 février 2003
Statut
Modérateur
Dernière intervention
14 février 2014
32
il ne faut pas oublier :

if (x.Equals(y))
return 0;

dans la classe Melangeur...


Sébastien FERRAND (
blog)
[Microsoft MVP Visual C#]
Messages postés
13
Date d'inscription
mardi 8 mars 2005
Statut
Membre
Dernière intervention
28 février 2006

Comme écrit dans la solution proposée?

Je l'ai bien mis et il y a quand même l'erreur!
Messages postés
4936
Date d'inscription
lundi 17 février 2003
Statut
Modérateur
Dernière intervention
14 février 2014
32
Essaye comme ceci :

public
class
Melangeur :
IComparer {

private
static
Random rnd;

static Melangeur() {
rnd =
new
Random();
}



public
int Compare(
object x,
object y) {

if (Object.Equals(x, y))

return 0;

else {

return rnd.Next(-1, 1);
}
}

}


Sébastien FERRAND (
blog)
[Microsoft MVP Visual C#]
Messages postés
13
Date d'inscription
mardi 8 mars 2005
Statut
Membre
Dernière intervention
28 février 2006

Pour le moment, ça a l'air de marcher... mais bon je reste prudent comme c'est une erreur qui ce produit que de temps en temps.
Messages postés
4936
Date d'inscription
lundi 17 février 2003
Statut
Modérateur
Dernière intervention
14 février 2014
32
ok


Sébastien FERRAND (
blog)
[Microsoft MVP Visual C#]
Messages postés
13
Date d'inscription
mardi 8 mars 2005
Statut
Membre
Dernière intervention
28 février 2006

Bon ben j'avais raison d'être méfiant... ça n'a pas enlevé le problème.

A mon avis, tu trouveras pas le problème sans savoir ce que j'ai fait:

Card[] cards = new Card[52];
Array.Sort(cards,new Shaker());

public class Card
{
private string suit;
private int valu; /* 11 <-> J
* 12 <-> Q
* 13 <-> K
* 14 <-> AS */

private string picture;

public Card(string suit, int valu, string picture)
{
this.suit = suit;
this.valu = valu;
this.picture = picture;
}
...
}

Sinon, personne aurait une autre solution?.. ou toi, d'ailleurs
Messages postés
6352
Date d'inscription
samedi 1 juin 2002
Statut
Modérateur
Dernière intervention
2 août 2014
80
Card[] cards = new Card[52];
Array.Sort(cards,new Shaker());

=> là tu mélanges un tableau de 52 null

/*
coq
MVP Visual C#
*/
Messages postés
13
Date d'inscription
mardi 8 mars 2005
Statut
Membre
Dernière intervention
28 février 2006

Ouais, enfin je suis pas non plus totalement nul en prog... j'ai juste simplifié, j'ai pas tout marqué...
Le tableau de carte est bien initialisé, sinon ça ne marcherait pas du tout, et pas 19 fois sur 20...

Tant pis, je me suis résolu à ne pas résoudre cette erreur mais juste à la contourné.

Et ça marche, même si c'est pas la meilleure solution
Messages postés
6352
Date d'inscription
samedi 1 juin 2002
Statut
Modérateur
Dernière intervention
2 août 2014
80
C'est assez étonnant comme erreur.
Peut tu mettre le code complet des classes Card et Shaker stp ?

/*
coq
MVP Visual C#
*/
Messages postés
13
Date d'inscription
mardi 8 mars 2005
Statut
Membre
Dernière intervention
28 février 2006

public class Card
{
private string suit;
private int valu; /* 11 <-> J
* 12 <-> Q
* 13 <-> K
* 14 <-> AS */

private string picture;

public Card(string suit, int valu, string picture)
{
this.suit = suit;
this.valu = valu;
this.picture = picture;
}
}

public class Shaker: IComparer
{
private static Random rnd;
static Shaker()
{
rnd = new Random();
}

public int Compare(object x, object y)
{
if (Object.Equals(x, y))
return 0;
else
{
return rnd.Next(-1, 1);
}
}
}

Par contre pour raccourcir, j'ai enlevé les accesseurs de la classe Cards, mais bon vous m'en voudrait pas .
Messages postés
6352
Date d'inscription
samedi 1 juin 2002
Statut
Modérateur
Dernière intervention
2 août 2014
80
Ceci résoudra ton problème (normalement) :

public class Shaker : IComparer
{
private static Random rnd;
static Shaker()
{
rnd = new Random();
}


public int Compare(object x, object y)
{
int ret = 0;


if (Object.Equals(x, y))
ret = 0;
else
{
while(ret==0)
ret = rnd.Next(-1, 1);
}


return ret;
}
}

(testé avec 28323775 tris sans erreur)

Maintenant je voudrais bien comprendre pourquoi l'exception est levée si on ne fait pas ça...

/*
coq
MVP Visual C#
*/
Messages postés
13
Date d'inscription
mardi 8 mars 2005
Statut
Membre
Dernière intervention
28 février 2006

Heu, c'est vrai y a plus d'erreur!

Mais ça mélange plus mes cartes...
Messages postés
6352
Date d'inscription
samedi 1 juin 2002
Statut
Modérateur
Dernière intervention
2 août 2014
80
Exact -_-
Eh bah là je n'ai vraiment pas d'idée sur le problème de fond...

/*
coq
MVP Visual C#
*/
Messages postés
13
Date d'inscription
mardi 8 mars 2005
Statut
Membre
Dernière intervention
28 février 2006

Tant pis merci quand même. Pour les curieux voilà comment j'ai contourné le problème:

try
{
Array.Sort(cards,new Shaker());
rank = 0;
}
catch{ rank = 25;};

Donc, dans le cas où l'on a une erreur, au lieu d'utilisé le tableau de carte à partir de la 1ère, on le fait à partir de la 26ème. Comme dans mon jeu de poker, sur une partie on n'utilise qu'au plus 25 cartes, et que l'erreur ce produit rarement... il y a de très très très faible probabilité pour que sur 2 tours consécutifs on ait les même carte.

Et encore merci à vous pour votre aide.
Messages postés
6352
Date d'inscription
samedi 1 juin 2002
Statut
Modérateur
Dernière intervention
2 août 2014
80
En fait je pense que le problème doit venir de l'algorithme "QuickSort" utilisé pour le tri.
Il vaudrait peut être mieux que tu passes par une autre méthode de mélange.

/*
coq
MVP Visual C#
*/
Messages postés
6352
Date d'inscription
samedi 1 juin 2002
Statut
Modérateur
Dernière intervention
2 août 2014
80
Bon, le message n'était pas partit tout à l'heure... :

Voilà un petit exemple de ce à quoi je pensais :

private static void RandomizeArray(object[] array)
{
int arrayLength = array.Length;


// parcours de la liste en partant de la fin
for (int i = arrayLength - 1; i > 1; --i)
{
// tirage au sort d'un index entre 0 et la valeur courante de "i"
int randomIndex = rnd.Next(i);
// intervertion des éléments situés aux index "i" et "randomIndex"
object temp = array[i];
array[i] = array[randomIndex];
array[randomIndex] = temp;
}
}

/*
coq
MVP Visual C#
*/
1 2