Pregunta

Estoy tratando de mezclar una matriz, pero la forma en que estoy haciendo que solo funciona sobre cada quinta vez. Le agradecería si alguien podría explicar por qué no está funcionando correctamente y tal vez proponer un pellizco.

private Button[] scrambleBoard(Button[] buttons)
{
    for (int x = 100 * buttons.Count(); x > 0; x--)
    {
        Random rand = new Random();
        int first = rand.Next(buttons.Count());
        int second = rand.Next(buttons.Count());


        Button temp = buttons[first];
        buttons[first] = buttons[second];
        buttons[second] = temp;
    }

    return buttons;
}
¿Fue útil?

Solución

Mover la siguiente línea fuera del bucle:

Random rand = new Random();

La semilla predeterminado utilizado por System.Random se basa en Environment.TickCount. En un bucle estrecho, la garrapata de recuento no puede cambiar entre las iteraciones sucesivas, por lo que puede terminar utilizando con la misma semilla y otra vez. En consecuencia, el bucle intercambiar repetidamente la mismo dos elementos hasta que los cambios tick-recuento (puede que no lo haga antes de que se complete el bucle). Para verificar que este es el problema, puede intentar añadir un Thread.Sleep(100) o similares dentro del bucle; a continuación, debe ser capaz de ver la confusión de funcionar correctamente (aunque muy lentamente).

También debe tener en cuenta que la técnica de href="http://www.codinghorror.com/blog/2007/12/the-danger-of-naivete.html" rel="nofollow"> para permutar la matriz es sesgada ; No todas las combinaciones es igualmente probable. Es posible que desee utilizar un algoritmo de mezcla que está conocido por ser imparcial, tal como el Fisher -Yates aleatoria .

Como alternativa, se puede utilizar una técnica muy simple para mezclar. Es un poco ineficiente, pero no sesgada:

var rand = new Random();
return buttons.OrderBy(button => rand.Next()).ToArray();

Otros consejos

El problema es que va a crear el objeto aleatorio () en cada iteración de su bucle. Como el objeto aleatorio utiliza una semilla durante la inicialización usted encontrará que la mayoría de los valores serán idénticos y no al azar.

Se puede solucionar el problema declarando la clase aleatorio estática como fuera del cuerpo del método.

private static Random rand = new Random();

private Button[] scrambleBoard(Button[] buttons)
{
    for (int x = 100 * buttons.Count(); x > 0; x--)
    {
        int first = rand.Next(buttons.Count());
        int second = rand.Next(buttons.Count());


        Button temp = buttons[first];
        buttons[first] = buttons[second];
        buttons[second] = temp;
    }

    return buttons;
}

Su pregunta ha sido contestada, pero pensé que sería buena idea compartir un pequeño truco para barajar una colección usando LINQ y Guid. Esto crea una lista ordenada al azar con una buena difusión de los valores.

private Button[] scrambleBoard(Button[] buttons)
{
    return buttons.OrderBy(b => Guid.NewGuid()).ToArray();
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top