Cargando...

Operaciones aleatorias en C#

Aprende a usar la clase Random en C# para generar números, valores y selecciones aleatorias con Next, NextDouble y ejemplos.

En C#, la clase principal para generar valores aleatorios es System.Random. Se utiliza con frecuencia en escenarios como la mecánica de juegos, simulaciones o generación de datos de prueba. En este artículo veremos cómo generar números con Random, definir rangos, mezclar arreglos, usar semillas (seed) y qué hacer cuando se necesita aleatoriedad criptográficamente segura.


Uso básico: Next()

Next() genera un entero (int) no negativo. Para un rango, se usan las sobrecargas del método.


var rnd = new Random();

int a = rnd.Next();        // 0..Int32.MaxValue
int b = rnd.Next(10);      // 0..9  (límite superior excluido)
int c = rnd.Next(5, 11);   // 5..10 (límite inferior incluido, superior excluido)

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

Valores decimales: NextDouble()

NextDouble() genera un número entre 0.0 y 1.0 (excluido). Puedes escalar el rango.


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}");

Rellenar un arreglo de bytes: NextBytes()

Si se necesitan bytes aleatorios (ej. datos ficticios), se usa NextBytes.


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

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

Reproducibilidad con Semilla (Seed)

Un Random inicializado con la misma semilla genera la misma secuencia de números. Útil para pruebas.


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

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

Error común: Crear varios Random consecutivos

Crear varias veces new Random() en un corto período puede producir resultados similares/idénticos (semilla basada en la hora). Solución: usar una sola instancia durante la aplicación o preferir Random.Shared.


// MALO
int MalaGeneracion()
{
    return new Random().Next(100); // nueva instancia en cada llamada
}

// BUENO
var rnd = new Random(); // compartido
int BuenaGeneracion() => rnd.Next(100);

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

Ejemplos: Color, Estudiante, Código


var rnd = Random.Shared;

// Selección aleatoria de color
string[] colores = { "Rojo", "Azul", "Verde", "Amarillo", "Morado" };
string colorElegido = colores[rnd.Next(colores.Length)];
Console.WriteLine("Color elegido: " + colorElegido);

// Selección aleatoria de estudiante
string[] estudiantes = { "Carlos", "Lucía", "María", "Andrés", "Sofía" };
string estudianteElegido = estudiantes[rnd.Next(estudiantes.Length)];
Console.WriteLine("Estudiante elegido: " + estudianteElegido);

// Generar un código aleatorio (6 caracteres)
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("Código de verificación: " + sb.ToString());

Mezclar un arreglo (Fisher–Yates)

Para mezclar elementos con probabilidad uniforme, se recomienda el algoritmo Fisher–Yates.


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

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

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

Selección aleatoria

Elegir un elemento aleatorio de una colección:


var rnd = Random.Shared;
string[] colores = { "Rojo", "Azul", "Verde", "Amarillo" };

string eleccion = colores[rnd.Next(colores.Length)];
Console.WriteLine("Elección: " + eleccion);

Contraseña aleatoria simple (Demo)

No es criptográficamente segura; adecuada para juegos/datos de prueba. Para seguridad, usar el método de abajo.


var rnd = Random.Shared;
const string alfabeto = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
int longitud = 10;

var sb = new System.Text.StringBuilder(longitud);
for (int i = 0; i < longitud; i++)
{
    int idx = rnd.Next(alfabeto.Length);
    sb.Append(alfabeto[idx]);
}
Console.WriteLine("Contraseña (demo): " + sb.ToString());

Aleatoriedad criptográficamente segura

Para escenarios críticos de seguridad como generación de contraseñas, tokens o claves, no uses Random. En su lugar, utiliza System.Security.Cryptography.RandomNumberGenerator o los auxiliares RandomNumber.


using System.Security.Cryptography;

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

// Rango definido
int n2 = RandomNumberGenerator.GetInt32(100, 201); // 100..200

// Bytes aleatorios
byte[] key = new byte[32];
RandomNumberGenerator.Fill(key);

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

Nota sobre la distribución

Random produce valores cercanos a una distribución uniforme. Para distribuciones como la normal (Gauss), se necesitan transformaciones (ej. Box–Muller) o bibliotecas estadísticas.


TL;DR

  • Random.Next, NextDouble, NextBytes → API básicas.
  • Usa una sola instancia o Random.Shared; no crees múltiples new Random().
  • Misma semilla → misma secuencia de números (pruebas reproducibles).
  • Para mezclar un arreglo, aplica Fisher–Yates.
  • Para seguridad, usa RandomNumberGenerator / GetInt32.