Chargement...

Opérations aléatoires en C#

Apprenez à utiliser la classe Random en C# pour générer des nombres et valeurs aléatoires avec Next, NextDouble et exemples.

En C#, la classe principale pour générer des valeurs aléatoires est System.Random. Elle est souvent utilisée dans des scénarios comme les mécaniques de jeu, les simulations ou la génération de données de test. Dans cet article, nous allons voir comment générer des nombres avec Random, définir des plages, mélanger des tableaux, utiliser des graines (seed) et ce qu’il faut faire lorsqu’une forte sécurité cryptographique est nécessaire.


Utilisation de base : Next()

Next() génère un entier (int) non négatif. Des versions surchargées permettent de définir une plage.


var rnd = new Random();

int a = rnd.Next();        // 0..Int32.MaxValue
int b = rnd.Next(10);      // 0..9  (borne supérieure exclusive)
int c = rnd.Next(5, 11);   // 5..10 (borne inférieure incluse, borne sup. exclue)

Console.WriteLine($"{a}, {b}, {c}");

Valeurs à virgule flottante : NextDouble()

NextDouble() génère un nombre compris entre 0.0 et 1.0 (exclu). Vous pouvez mettre l’intervalle à l’échelle.


var rnd = new Random();

double x = rnd.NextDouble();          // [0.0, 1.0)
double y = 5.0 + rnd.NextDouble()*3;  // [5.0, 8.0)

Console.WriteLine($"{x}, {y:0.000}");

Remplissage d’un tableau de bytes : NextBytes()

Lorsque des octets aléatoires sont nécessaires (ex. : données fictives), utilisez NextBytes.


var rnd = new Random();
byte[] buffer = new byte[8];
rnd.NextBytes(buffer);

Console.WriteLine(BitConverter.ToString(buffer)); // Exemple : "3F-91-0C-..."

Reproductibilité avec une graine (Seed)

Un Random initialisé avec la même graine génère la même séquence de nombres. Utile pour les tests.


var r1 = new Random(12345);
var r2 = new Random(12345);

Console.WriteLine(r1.Next() == r2.Next()); // True

Erreur fréquente : Créer plusieurs Random successivement

Créer plusieurs fois new Random() en peu de temps peut produire des résultats similaires/identiques (seed basé sur l’heure). Solution : utiliser une seule instance durant l’application ou Random.Shared.


// MAUVAIS
int MauvaiseGeneration()
{
    return new Random().Next(100); // nouvelle instance à chaque appel
}

// BON
var rnd = new Random(); // partagé
int BonneGeneration() => rnd.Next(100);

// .NET 6+ : Random.Shared (thread-safe)
int MeilleureGeneration() => Random.Shared.Next(100);

Exemples : Couleur, Étudiant, Code


var rnd = Random.Shared;

// Choix d’une couleur aléatoire
string[] couleurs = { "Rouge", "Bleu", "Vert", "Jaune", "Violet" };
string couleurChoisie = couleurs[rnd.Next(couleurs.Length)];
Console.WriteLine("Couleur choisie : " + couleurChoisie);

// Sélection d’un étudiant au hasard
string[] etudiants = { "Claire", "Lucas", "Sophie", "Antoine", "Marie" };
string etudiantChoisi = etudiants[rnd.Next(etudiants.Length)];
Console.WriteLine("Étudiant choisi : " + etudiantChoisi);

// Génération d’un code aléatoire (6 caractères)
const string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
var sb = new System.Text.StringBuilder();
for (int i = 0; i < 6; i++)
    sb.Append(chars[rnd.Next(chars.Length)]);
Console.WriteLine("Code de vérification : " + sb.ToString());

Mélanger un tableau (Fisher–Yates)

Pour mélanger des éléments avec des probabilités égales, utilisez l’algorithme de Fisher–Yates.


var rnd = Random.Shared;
int[] tableau = { 1, 2, 3, 4, 5 };

for (int i = tableau.Length - 1; i > 0; i--)
{
    int j = rnd.Next(0, i + 1); // 0..i
    (tableau[i], tableau[j]) = (tableau[j], tableau[i]);
}

Console.WriteLine(string.Join(", ", tableau));

Sélection aléatoire

Choisir un élément au hasard dans une collection :


var rnd = Random.Shared;
string[] couleurs = { "Rouge", "Bleu", "Vert", "Jaune" };

string choix = couleurs[rnd.Next(couleurs.Length)];
Console.WriteLine("Choix : " + choix);

Mot de passe aléatoire simple (Démo)

Non cryptographiquement sûr ; adapté aux jeux/données de test. Pour la sécurité, utilisez la méthode ci-dessous.


var rnd = Random.Shared;
const string alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
int longueur = 10;

var sb = new System.Text.StringBuilder(longueur);
for (int i = 0; i < longueur; i++)
{
    int idx = rnd.Next(alphabet.Length);
    sb.Append(alphabet[idx]);
}
Console.WriteLine("Mot de passe (démo) : " + sb.ToString());

Aléatoire cryptographiquement sûr

Pour les scénarios critiques de sécurité comme la génération de mots de passe, de tokens ou de clés, n’utilisez pas Random. Utilisez plutôt System.Security.Cryptography.RandomNumberGenerator ou les utilitaires RandomNumber.


using System.Security.Cryptography;

// 0..int.MaxValue (exclusif)
int n1 = RandomNumberGenerator.GetInt32(int.MaxValue);

// Intervalle défini
int n2 = RandomNumberGenerator.GetInt32(100, 201); // 100..200

// Octets aléatoires
byte[] key = new byte[32];
RandomNumberGenerator.Fill(key);

Console.WriteLine($"{n1}, {n2}, {BitConverter.ToString(key)}");

Remarque sur la distribution

Random produit des valeurs proches d’une distribution uniforme. Pour des distributions comme la normale (Gauss), des transformations (ex. : Box–Muller) ou des bibliothèques statistiques sont nécessaires.


TL;DR

  • Random.Next, NextDouble, NextBytes → API de base.
  • Utilisez une seule instance ou Random.Shared ; n’instanciez pas plusieurs new Random().
  • Même graine → même séquence de nombres (tests reproductibles).
  • Pour mélanger un tableau, appliquez Fisher–Yates.
  • Pour la sécurité, utilisez RandomNumberGenerator / GetInt32.