[DOTNET] Probleme improbable de Random

Probleme improbable de Random [DOTNET] - C#/.NET managed - Programmation

Marsh Posté le 12-07-2008 à 14:53:50    

Bonjour :hello:
 
J'ai un probleme tres sympa de Random qui commence a bien me les casser :/
 
Je vous expose le truc
 
Je suis sur un bout de code pour un jeu de carte (rien d'exceptionel me direz vous)
 
J'ai une classe CARTE qui génère une carte avec un numéro.
 
Je doit tirer 5 cartes (5 différentes) et c'est LA que le problème survient
 
Dans le constructeur de la classe CARTE j'ai ceci :

Code :
  1. public Carte()
  2.         {
  3.             System.Random rnd = new System.Random(DateTime.Now.Millisecond * DateTime.Now.Millisecond);
  4.             _numero = rnd.Next(1,53) ;
  5.             _image = new Image();
  6.             _image.ImageUrl = "~/img/cards/" + _numero + ".png";
  7.             _valeur = "";
  8.             _couleur = "";
  9.         }


 
 
Elles sont crées tout simplement comme ceci :
 

Code :
  1. C1= new Carte();
  2.             C2= new Carte();
  3.             C3= new Carte();
  4.             C4= new Carte();
  5.             C5= new Carte();


 
Mais le problème c'est qu'il me fou a chaque fois les 5 mêmes cartes :(
 
Comprend vraiment pas pourquoi  
 
Si vous avez une idée, n'hesitez pas !
 
merci :jap:


Message édité par massanu le 12-07-2008 à 14:55:00
Reply

Marsh Posté le 12-07-2008 à 14:53:50   

Reply

Marsh Posté le 12-07-2008 à 15:01:45    

J'ajouterais meme a l'improbable ceci
 
Si je fais la même génération aléatoire sans passé par une création d'instance d'objet carte
 
En gros
 

Code :
  1. System.Random rnd = new System.Random(DateTime.Now.Millisecond * DateTime.Now.Millisecond);
  2.              _numero = rnd.Next(1,53) ;


 
Et bien cela me donne bien 5 numéros distinct  :heink:  
 
Je doit avoir un problème avec mes instances d'objet mais je ne sais guère lequel  :pt1cable:

Reply

Marsh Posté le 12-07-2008 à 15:07:32    

A chaque carte que tu crées, tu réinitialises ta séquence random avec la même seed (puisque tes cartes sont créées quasi simultanément), puis tu tires le premier numéro de la séquence.
 
Normal que ce soit à chaque fois le même.
 
Initialise rnd une seule fois au début de ton programme, et pas à chaque création d'une carte.
 
De plus, il est tout à fait admissible de tirer deux fois la même carte avec ton implémentation. Pour tirer des cartes toutes différentes, il te faut supprimer les cartes déjà tirées de ta pile. Il y a différentes implémentations pour ca, je te laisse chercher un moment.

Reply

Marsh Posté le 12-07-2008 à 15:28:27    

Merci pour ta réponse :jap:
 
- Si j'ai réinitialisé le seed à chaque fois, c'est parcequ'en l'initialisant une seule fois au départ, j'obtenais les mêmes cartes également
 
Ce qui me laisse pensé que le problème viens bien quand j'initialise les cartes dans le constructeur de la classe Carte

Reply

Marsh Posté le 15-07-2008 à 13:56:01    

massanu a écrit :


- Si j'ai réinitialisé le seed à chaque fois, c'est parcequ'en l'initialisant une seule fois au départ, j'obtenais les mêmes cartes également


 
impossible, tu t'es planté quelque part.
 
initialise ton random en dehors de ta classe, et passe-le en paramètre à ton constructeur.
 
ou alors crée une classe static avec comme variable privée static le random, que tu initialise dans le constructeur static et ajoute une méthode static public "NextValue" :
 

Code :
  1. using System;
  2.  
  3. namespace SandBoxConsole
  4. {
  5.    class Program
  6.    {
  7.        static void Main(string[] args)
  8.        {
  9.            Console.WriteLine(new Carte());
  10.            Console.WriteLine(new Carte());
  11.            Console.WriteLine(new Carte());
  12.            Console.WriteLine(new Carte());
  13.            Console.WriteLine(new Carte());
  14.            Console.ReadKey(true);
  15.        }
  16.    }
  17.  
  18.    static class MyRandomGenerator
  19.    {
  20.        private static Random rnd;
  21.  
  22.        static MyRandomGenerator()
  23.        {
  24.            rnd = new Random();
  25.        }
  26.  
  27.        public static int NextValue(int max)
  28.        {
  29.                return rnd.Next(0, max) + 1;
  30.        }
  31.    }
  32.  
  33.    public class Carte
  34.    {
  35.        int numero = 0;
  36.  
  37.        public Carte()
  38.        {
  39.            numero = MyRandomGenerator.NextValue(52);
  40.        }
  41.  
  42.        public override string ToString()
  43.        {
  44.            return string.Format("Carte numéro {0}.", numero);
  45.        }
  46.    }
  47. }


 
(les puristes POO aiment pas ce raccourci .NET pour faire des singleton, mais moi j'aime bien, je trouve ça super simple d'utilisation)
 
Sortie :


Carte numéro 42.
Carte numéro 6.
Carte numéro 8.
Carte numéro 10.
Carte numéro 52.


 


Carte numéro 10.
Carte numéro 33.
Carte numéro 32.
Carte numéro 50.
Carte numéro 31.


 


Carte numéro 10.
Carte numéro 18.
Carte numéro 1.
Carte numéro 44.
Carte numéro 49.


 


Carte numéro 24.
Carte numéro 4.
Carte numéro 37.
Carte numéro 47.
Carte numéro 19.


 
(pour le reste, +1 avec cpp6128, tu peux tirer des doublons, c'est mal)
 
passe plutôt par un List<Carte> trié aléatoirement, et tu tires les 5 premières, en plus ça se comportera comme en vrai...

Message cité 1 fois
Message édité par MagicBuzz le 15-07-2008 à 14:15:26
Reply

Marsh Posté le 15-07-2008 à 14:17:03    

ps : et à la base pas besoin de spécifier un seed à ton random, le seed automatique est plus "aléatoire", ce qui réduit la prédictabilité du résultat.


Message édité par MagicBuzz le 15-07-2008 à 14:17:34
Reply

Marsh Posté le 15-07-2008 à 15:09:59    

MagicBuzz a écrit :


 
impossible, tu t'es planté quelque part.
 
initialise ton random en dehors de ta classe, et passe-le en paramètre à ton constructeur.
 
ou alors crée une classe static avec comme variable privée static le random, que tu initialise dans le constructeur static et ajoute une méthode static public "NextValue" :
 

Code :
  1. using System;
  2.  
  3. namespace SandBoxConsole
  4. {
  5.    class Program
  6.    {
  7.        static void Main(string[] args)
  8.        {
  9.            Console.WriteLine(new Carte());
  10.            Console.WriteLine(new Carte());
  11.            Console.WriteLine(new Carte());
  12.            Console.WriteLine(new Carte());
  13.            Console.WriteLine(new Carte());
  14.            Console.ReadKey(true);
  15.        }
  16.    }
  17.  
  18.    static class MyRandomGenerator
  19.    {
  20.        private static Random rnd;
  21.  
  22.        static MyRandomGenerator()
  23.        {
  24.            rnd = new Random();
  25.        }
  26.  
  27.        public static int NextValue(int max)
  28.        {
  29.                return rnd.Next(0, max) + 1;
  30.        }
  31.    }
  32.  
  33.    public class Carte
  34.    {
  35.        int numero = 0;
  36.  
  37.        public Carte()
  38.        {
  39.            numero = MyRandomGenerator.NextValue(52);
  40.        }
  41.  
  42.        public override string ToString()
  43.        {
  44.            return string.Format("Carte numéro {0}.", numero);
  45.        }
  46.    }
  47. }


 
(les puristes POO aiment pas ce raccourci .NET pour faire des singleton, mais moi j'aime bien, je trouve ça super simple d'utilisation)
 
Sortie :


Carte numéro 42.
Carte numéro 6.
Carte numéro 8.
Carte numéro 10.
Carte numéro 52.


 


Carte numéro 10.
Carte numéro 33.
Carte numéro 32.
Carte numéro 50.
Carte numéro 31.


 


Carte numéro 10.
Carte numéro 18.
Carte numéro 1.
Carte numéro 44.
Carte numéro 49.


 


Carte numéro 24.
Carte numéro 4.
Carte numéro 37.
Carte numéro 47.
Carte numéro 19.


 
(pour le reste, +1 avec cpp6128, tu peux tirer des doublons, c'est mal)
 
passe plutôt par un List<Carte> trié aléatoirement, et tu tires les 5 premières, en plus ça se comportera comme en vrai...


 
 
Nickel chrome, Merci :jap:
 
Je vais utilisé ce bout de code pour la génération aléatoire, j'espere que sa pourra aider d'autre personne :)

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed