24 de set. de 2009

Embaralhando uma Lista

image

Pessoal, em jogos é muito comum usarmos o recurso Random.

Então é natural que vamos usar uma hora ou outra uma lista embaralhada, para um jogo de cartas por exemplo.

No LINQ nós temos o “order by”, mas não temos o “desorder by” hehehehe.

Então criei um extension method para embaralhar uma lista, com vocês o shuffle List:

using System;
using System.Collections.Generic;

namespace Extension
{
    public static class ListUtils
    {
        /// <summary>
        /// Embaralha uma Lista.
        /// </summary>
        /// <typeparam name="T">Tipo da Lista.</typeparam>
        /// <param name="list">Lista que será embaralhada.</param>
        /// <returns>A Lista embaralhada.</returns>
        public static IList<T> Shuffle<T>(this IList<T> list)
        {
            // -> Gerador de numeros ramdomicos.
            var r = new Random();

            // -> Percorre a Lista para embaralhar.
            for (int i = 0; i < list.Count; i++)
            {
                // -> Adiquire um indice ramdomico
                //    Observe que é passado o contador de indices da lista,
                //    como indice máximo e Exclusivo!
                //    (ou seja, o máximo não é incluso nos numeros randomicos).
                var j = r.Next(list.Count);
                // -> Pega o item da posicao temporaria.
                T obj = list[j];

                // -> Coloca o item da posição "i" na posição aleatória "j".
                list[j] = list[i];

                // -> coloca o item aleatorio na posição "i".
                list[i] = obj;
            }

            // -> Retorna a lista embaralhada.
            return list;
        }
    }
}

image

Espero ter sido útil. :)

4 comentários:

Caio Proiete disse...

Spoky,

Você pode usar o próprio LINQ para criar o seu "desorder by"... Basta utilizar o OrderBy que você já conhece, utilizando o número randômico que você está gerando...

Algo como:

public static IList[T] Shuffle[T](this IList[T] list)
{
// -] Gerador de numeros ramdomicos.
var r = new Random();

// -] Retorna a lista embaralhada.
return list.OrderBy((v) =] r.Next(list.Count)).ToList();
}


Ou então, o meu método preferido, utilizando a geração de GUIDs:

public static IList[T] Shuffle[T](this IList[T] list)
{
// -] Retorna a lista embaralhada.
return list.OrderBy((v) =] Guid.NewGuid()).ToList();
}

---

Vale lembrar que independente da implementação, por padrão, o seu extension method nunca deveria alterar a lista original, mas sim, retornar uma outra versão da lista alterada (no seu caso, desordenada), mantendo a lista original intacta... Exatamente como fazem todas as outras extension do LINQ ;).

Abraços,

Caio Proiete
http://www.caioproiete.com

PS: O Blogspot interpreta os sinais de maior e menor como tags HTML, então tive de substituir por "[" e "]"

Eduardo Spaki disse...

Caio, muito obrigado pela dica, eu pensei em fazer com o proprio linq, já com a guid eu não sabia que dava para fazer.

já no caso de alterar a lista original, foi uma escolha para deixar o código um pouco enxuto. além do que, meu amigo, que me solicitou, queria algo assim: lista.shuffle();

mas muito obrigado, vou testar estas novas ideia!

valew

Cássio disse...

Cara, muito obrigado pela dica!!
Funcionou do jeito que eu queria!!
Abraços.

Ensinando os gemeos disse...

Bom dia,
você tem algum exemplo de como pegar essa lista numerar ela e depois gravar no banco.