2010-01-06 7 views
5

Buscando mezclar cuatro variables (tratando de cambiar el orden en que aparecen en una lista de opciones múltiples).¿Forma de mezclar rápidamente los números del 1 al 4?

He estado dando vueltas por un tiempo, pero no puedo entender bien la lógica, y buscar aleatoriamente en preguntas pasadas da algoritmos súper detallados que están más allá de mis habilidades de novato (y las necesidades de este programa estoy tratando de escribir, solo me gustaría hacer un selector de imágenes de opción múltiple).

Lo ideal sería algo que sigue este pseudocódigo:

// int Answer1 = Random(min1 max4) 

// int Answer2 = Random(min1 max4) 

// int Answer3 = Random(min1 max4) 

// int Answer4 = Random(min1 max4) 

// If Answer 1 equals ANY of the other three, re-randomize Answer1 and loop. 

// Loop through this cycle for all answers. 

que había puesto mi código regulares actuales, pero, francamente, es basura. :(Este parece ser un problema bastante simple, pero simplemente no puede hacerlo bien

Gracias de antemano

+0

Muchas respuestas excelentes. ¡Me alegro de que no sea yo quien tenga que elegir! –

Respuesta

8

arrastrando los pies -.! http://www.codinghorror.com/blog/archives/001008.html

Aunque, no utilice un GUID, utilice un azar número:

//create only once, please 
static readonly Random random = new Random(); 

y luego:

var numbers = Enumerable.Range(1, 4); 
var shuffle = numbers.OrderBy(a => random.NextDouble()); 
+0

+1 concisa. Inteligente. –

+0

Curioso por qué no usaría un GUID. –

+0

Preferencia personal, realmente. Mirando un poco más, esto es mejor: http://stackoverflow.com/questions/1287567/c-is-using-random-and-orderby-a-good-shuffle-algorithm (de hecho, la pregunta es por qué * no * t para usar este método!) – Kobi

5

Bueno, técnicamente, a quién le importa si solo son 4 números de 400 números. Debería usar an implementation of Fisher-Yates shuffle. Sin embargo, para que sea más fácil de entender:

var possibleNumbers = new List<int>(Enumerable.Range(1, 4)); 
var result = new List<int>(4); 
var rnd = new Random(); 
while (possibleNumbers.Count > 0) { 
    int r = rnd.Next(possibleNumbers.Count); 
    result.Add(possibleNumbers[r]); 
    possibleNumbers.RemoveAt(r); 
} 

El algoritmo demostrado anteriormente es básicamente el armado de Fisher-Yates. En la práctica, no usa dos listas distintas para guardar cosas. Simplemente elige un elemento aleatorio de la parte de la matriz que aún no ha arreglado y lo mueve a su lugar. El comienzo de la lista individual será elementos fijos, mientras que el final serán las posibilidades.

0
 Random rand = new Random(); 
     List<int> choices = new List<int>() { 1, 2, 3, 4 }; 

     while (choices.Count > 0) 
     { 
      int index = rand.Next() % choices.Count; 
      int choice = choices[index]; 
      Console.WriteLine(choice); 
      choices.RemoveAt(index); 
     } 

editar - En lugar de simplemente imprimir los números, obviamente puede agregarlos a una nueva lista.

+0

+1 Como el módulo para poner el número aleatorio en el rango del tamaño de las opciones decrecientes. –

+0

@John: este código es una muy mala idea, ya que los números aleatorios no se distribuirán por igual. No uses 'rnd.Next()' cuando realmente quieras 'rnd.Next (int)', lo cual hace todo el trabajo desagradable para ti. –

5

me gusta este método de extensión:

static class IListExtensions { 
    public static void Shuffle<T>(this IList<T> list, Random rg) { 
     for (int i = list.Count; i > 1; i--) { 
      int k = rg.Next(i); 
      T temp = list[k]; 
      list[k] = list[i - 1]; 
      list[i - 1] = temp; 
     } 
    } 
} 

continuación:

Random rg = new Random(); 
List<int> list = Enumerable.Range(1, 4).ToList(); 
list.Shuffle(rg); 

Ahora list es un revolver de {1, 2, 3, 4}.

El algoritmo que utilicé aquí es el Fisher-Yates shuffle.

+0

+1 Me gusta el método de extensión y genérico para ordenar diferentes tipos de listas. También puede conectar el algoritmo de elección sin afectar a las personas que llaman. –

+1

@jdk: en particular, se podría aprobar una implementación de Mersenne Twister que tiene suficientes estados internos para garantizar que tengamos un mezclador realmente imparcial para las listas del tamaño de un mazo de cartas (¡apostar!). O uno podría pasar un mezclador de lámparas de lava (http://www.lavarnd.org/). – jason

+0

Opción de algoritmo eficiente también: se ordena en su lugar, no genera una segunda lista. –

Cuestiones relacionadas