Estou tentando desenvolver um jogo de cartas para Android. Alguém pode me sugerir como escrever um código para baralhar efetivamente as cartas de jogar?
Baralhar cartas é um algoritmo que é fácil de escrever intuitivamente e, ao fazê-lo, é totalmente errado. Há uma boa referência para implementar o embaralhamento de cartões corretamente na Wikipedia . O que estou apresentando aqui é uma versão muito simplificada do algoritmo abordado nessa página em O algoritmo moderno .
Aqui está a idéia básica, em inglês simples:
Considere um baralho de cartas. Para esta discussão, você pode ter qualquer número de cartas no baralho, e elas podem começar em qualquer ordem.
Nós estaremos falando sobre "posição" no baralho, onde "posição" é quantas cartas são maiores no baralho do que a carta nessa posição. Por exemplo, a carta no topo do baralho está na posição 0, a carta abaixo dela está na posição 1 (porque há 1 carta mais alta que ela - a carta superior) e, em um baralho padrão de 52 cartas, a parte inferior a carta está na posição 51, pois 51 são mais altas do que no baralho.
Agora, consideramos cada posição no baralho, uma de cada vez, começando do fundo e subindo até o topo.
Para cada posição, selecionamos aleatoriamente uma das cartas que está nessa posição ou em uma posição de número mais baixo (lembre-se, o topo do baralho é 0, e estamos trabalhando a partir da parte inferior do baralho, então para cada posição, você escolhe efetivamente todas as cartas nessa posição e escolhe aleatoriamente uma dessas cartas).
Quando fizemos a seleção aleatória, trocamos a carta na posição que estamos considerando atualmente pela carta que selecionamos aleatoriamente. Se selecionarmos aleatoriamente o cartão que já estava nessa posição, nenhum swap será realizado.
Depois de trocar (ou não trocar, se selecionarmos aleatoriamente a carta que já estava na posição que estávamos considerando), passamos para a próxima posição no baralho e continuamos.
Em pseudocódigo, com n sendo o número de cartas do baralho, e um sendo uma matriz que representa o convés, o algoritmo se parece com isso:
for each i in [n .. 1] do
j ← random integer in [ 0 .. i ]
exchange a[j] and a[i]
Primeiro, você define uma sequência de todas as cartas que deseja embaralhar:
Depois, você percorre todas as posições da sequência e atribui-lhe um cartão aleatoriamente.
Agora
shuffled
é uma sequência aleatória de todos os seus cartões.fonte
Eu gostaria de mencionar e mencionar "o formato preservando a criptografia" como um método para embaralhar as cartas em um jogo.
Essencialmente, o que você tem é um algoritmo de criptografia que leva um valor de 0 a 51 e uma chave (shuffle seed) e cospe um valor de 0 a 51. Como a criptografia é reversível por definição, significa que quaisquer 2 números de entrada não podem criptografar para o mesmo número de saída, o que significa que, se você criptografar de 0 a 51, obterá de 0 a 51 como saída em uma ordem diferente. Em outras palavras, você tem seu shuffle e nem precisa fazer nenhum shuffling real.
Nesse caso, você teria que criar ou encontrar um algoritmo de criptografia que capturasse 6 bits e cuspisse 6 bits (0-63). Para extrair a próxima carta do baralho, você teria uma variável de índice iniciada em zero, criptografaria esse índice, aumentaria o índice e examinaria o valor que saiu da cifra. Se o valor for> = 52, você o ignora e gera um novo número (e incrementa o índice novamente, é claro). Como a criptografia de 0 a 63 resultará em 0 a 63 como saída, em uma ordem diferente, você estará ignorando qualquer valor que saia> = 52 para que você tenha seu algoritmo que aceita 0 a 51 e cospe 0 a 51.
Para reorganizar o deck, defina o índice novamente como zero e altere a chave de criptografia (shuffle seed).
Seu algoritmo não precisa ter qualidade criptográfica (e não deveria ser, porque isso seria computacionalmente caro!). Uma maneira realmente boa de criar um algoritmo de criptografia de tamanho personalizado como esse seria usar uma rede feistel, que permite personalizar tamanho e qualidade, dependendo de suas necessidades. Para a função round da rede feistel, eu recomendaria algo como murmurhash3 porque é rápido e tem um bom efeito de avalanche, o que faria os shuffles parecerem bem aleatórios.
Confira minha postagem no blog para obter informações e códigos-fonte ainda mais detalhados: http://blog.demofox.org/2013/07/06/fast-lightweight-random-shuffle-functionality-fixed/
fonte
O tutorial java 1.5 enum tem uma maneira interessante de implementar um baralho de cartas, construindo o baralho, baralhando e negociando. Tudo muito simples, utilizando
enum
s eCollections
E a turma para gerenciar o convés.
fonte
Simplesmente use uma função como itertools como no Python. Não estou ciente do nome da mesma função em Java, tente ". Http://code.google.com/p/neoitertools/ "
Descubra todas as permutações do objeto chamado "cards"
fonte
fonte