Ajuda iniciante com Math.Random

Olá sou iniciante e não consigo resolver um problema. Se alguém poder me ajudar agradeço.

Tenho um Array, onde vou inserir numeros sorteados. Porem gostaria que o sorteio repetisse no máximo 3 vezes cada numero.

Exemplo:

Tenho 3 jogadores, cada jogador tem 3 posições do Array. Multipliquei a quantJogadores por 3, sendo assim tenho 9 posições onde eu gostaria de percorrer o Array sorteando de 1 a 3. Porem ao sair 3 números iguais, ele não sorteie mais esse numero

public void inicializaNivel(int quantJogadores){
a = new int[quantJogadores*3];
for(int i=0; i int tipo = (int)(Math.random()*quantJogadores);
a = tipo+1;

ao imprimir o resultado sai assim: 1,2,2,1,3,3,1,3,3. Gostaria que sai-se 3 de cada tipo: 1,2,2,1,3,2,1,3,3. Sendo assim tenho 3 números 1, 3 números 2 e 3 números 3.

Obrigado.

Bem sugiro uma espécie de contador. se número =1 soma1 no contador, se contador +3, vc evita que aceite de fato o número 1, e faz gerar um novo sorteio… certo?

tenho um jogo de bingo que se encaixa neste contexto, pois como vc sabe, não posso ficar repetindo números…

não é mesmo? se quiser estudar o código, postei os links todos em um post recente… bem interessante…

segue o tópico.

Entendi, mas ai eu teria que criar um contador para cada numero, tem somente 3 jogadores no exemplo, porem a quantidade de jogadores é passada por parâmetro. Tem alguma maneira de fazer alguma comparação com as posições do array ? ou mesmo pelo sorteio ?

ah provavelmente sim, faz um for para verificar cada posição… monta a lógica de um número só, e depois é só usar o for, para passar por todos os ítens do array.

o que acha??

Provavelmente será mais facil criares uma lista com todos os valores que pretendes e depois fazer um shuffle.

Poizeh a unica opção que tenho para o método é criar um array, e colocar os números dentro dele porem não repetindo mais que 3x cada numero,

tentei usar um if para caso contenha mais que 3x (contador) porem sem sucesso.

Adicione os números em ordem no array e depois embaralhe o array.


//Adiciona os dado no array de forma ordenada
int[] array = new int[quantJogadores*3];
int c = 0;
for (int i = 0; i < quantJogadores; i++) {
    for (int j = 0; j < 3; j++) {
        array[c] = i+1;
        c++;
    }
}

//Embaralha o array
for (int i = 0; i < array.length; i++) {
    int j = (int)(Math.random() * array.length);
    int temp = array[j];
    array[j] = array[i];
    array[i] = temp;
}

Vini
Obrigado pela ajuda, algumas coisas nao entendi

int[] array = new int[quantJogadores*3];
int c = 0;
for (int i = 0; i < quantJogadores; i++) {
for (int j = 0; j < 3; j++) {
array[c] = i; // por que “c” ?
c++;
}
}

//Embaralha o array // não consegui encontrar a logica dessa parte
for (int i = 0; i < array.size(); i++) {
int j = (int)(Math.random() * array.size());
int temp = array[j];
array[j] = array[i];
array[i] = temp;

tive que trocar o array.size() por array.length pois dava erro. Tambem não consegui fazer com que o sorteio inicia-se em 1, e nao em 0.

consegui fazer partir do 1,

era só somar i+1, mas não entendi muito bem ainda a lógica de todo o método.

Corrigi o código lá em cima para iniciar os jogadores do 1.

A variável c é a que irá contar cada um dos elementos do array. Ele é necessário pois estamos usando 2 fors, um para a quantidade de jogadores, outro para as 3 repetições.

A lógica da parte debaixo é a seguinte:

  1. Sorteia um índice qualquer entre 0 e o tamanho do array;
  2. Troca o valor nesse índice com o valor no primeiro índice do array. Com certeza o primeiro índice está embaralhado.
  3. Passa para o próximo índice e repete o procedimento.

Imagine que você está usando um baralho. Esse código é equivalente a pegar uma carta do meio do baralho, e trocar com a carta que está no topo. Depois, repetir o procedimento para a carta que está abaixo da primeira, e ir fazendo isso até ter percorrido o baralho inteiro.

Assim, ao invés de sortear o conteúdo das cartas, como vc estava fazendo, você só sorteia somente a ordem.

Código explicado:

[code]//Adiciona os dado no array de forma ordenada.
//Isso vai gerar um array ordenado.

Por exemplo, se tiver 4 jogadores, vai gerar o array:
//1,1,1,2,2,2,3,3,3,4,4,4
int[] array = new int[quantJogadores*3];
int c = 0; //Guarda o índice do array onde será inserido o jogador
for (int i = 0; i < quantJogadores; i++) { //Cada jogador
for (int j = 0; j < 3; j++) { //Repetido 3 vezes
array[c] = i+1;
c++;
}
}

//Embaralha o array
//Basta sortear uma posição qualquer e trocar com a posição sendo percorrida.
//Na primeira iteração, troca o sorteado com o que está na posição 0
//Na segunda, o que for sorteado com a posição 1.
//E assim por diante. Ao final do for, o array todo estará embaralhado.

//Note que estamos mexendo só na posição do conteúdo, não estamos cadastrando
//novos valores dentro do array. É como fariamos se estivessemos lidando com cartas.
for (int i = 0; i < array.length; i++) {
int j = (int)(Math.random() * array.length); //Sorteia um dos índices

//Troca o valor do índice i com o valor do índice j
int temp = array[j];
array[j] = array[i];
array[i] = temp;

}
[/code]

Deixa ver se entendi a lógica.

o primeiro for, percorre todo o array.
o segundo ele percorre e índices inserindo o valor de c ? após isso c++ passa a ser dois, ele percorre mais 3 índices inserindo 2, e assim por diante seria isso ?

a ultima parte não compreendo
ele sorteia um índice qualquer j
guarda em temp

pq array[j] = array[i] ?

e por ultimo array[i] = temp;

desculpe o incomodo mas este método não esta entrando em minha cabeça :frowning:

O primeiro for precisa fazer isso aqui:

array[0] = 1;
array[1] = 1;
array[2] = 1;
array[3] = 2;
array[4] = 2;
array[5] = 2;
array[6] = 3;
array[7] = 3;
array[8] = 3;
array[9] = 4;
array[10] = 4;
array[11] = 4;

Esse seria o array perfeito caso ao invés de sorteio você criasse os números em ordem, certo?

Veja que c é a variável que conta de 1 em 1, para cada número percorrido, e que vai ser o índice do array.

“i” é o número do jogador, ou seja, é o dado que está sendo atribuído do lado direito. j é usado apenas para repetir o valor de i em 3 posições diferentes.

Sobre a segunda parte do algoritmo. Você não conhece o algoritmo para trocar duas variáveis de valor? Costuma um dos primeiros exercícios que fazemos em programação com variáveis.

int a = 10; int b = 20;

Como trocar o valor de a e b? Usa-se uma variável temporária:

//Guarda o valor de "a" em "temp" int temp = a; //Agora que o valor de "a" está guardando em temp, podemos altera-lo a = b; //Agora que o valor de "b" já está em a, guardamos em "b" o // valor antigo de "a" que foi guardado em temp b = temp;

Veja o código sem os comentários:

int temp = a; //temp recebe 10 a = b; //"a" recebe 20 b = temp; //"b" recebe o valor de temp, que é o antigo de "a", ou seja, 10

E compare com o código que postei:

int temp = array[j];  
array[j] = array[i];  
array[i] = temp;  [/code]

O que esse código faz? Troca de lugar os valores que estão na posição i e j do array. Por exemplo, no array declarado ali em cima. Se i estiver em 0, e j for sorteado para 9 o que ele vai fazer?
[code]int temp = array[0]; //Temp recebe 1
array[0] = array[9]; //array[0] recebe 4
array[9] = temp; //array[9] recebe 1.[/code]

Portanto, o array agora está assim:
[code]array = {4,1,1,2,2,2,3,3,3,1,4,4};[/code]

Como já mexemos em array[0], vamos agora sortear quem irá trocar com array[1]. Vamos supor que se sorteie o número 5:
[code]int temp = array[1]; //temp recebe 1
int array[1] = array[5]; //array[1] recebe 2
int array[5] = temp; //arrat[5] recebe 1

E o array de jogadores agora está assim:

array = {4,2,1,2,1,2,3,3,3,1,4,4};

E o código prossegue para a posição 2 do array… e depois para a 3… e assim sucessivamente. Até ter certeza que cada casa foi sorteada pelo menos 1 vez.

Observe que como estamos só trocando os números de posição, e não sorteando os seus valores, é impossível que esse algoritmo gere mais (ou menos) do que 3 números por jogador. Por isso a analogia que se faz para esse tipo de algoritmo é como lidar com um baralho de cartas. Na primeira parte, colocamos em ordem todas as “cartas” (jogadores) que tem no nosso baralho (array). Igualzinho quando queremos conferir se o baralho que temos em casa está com todas as cartas certas. Nós organizamos o baralho por naipe e número. Em ordem mesmo, numa boa.

Na segunda parte, estamos misturando tudo, “embaralhando”. Só mexendo na ordem, sem adicionar novas cartas, e nem retirar cartas. Assim, garantimos exatamente o que você quer: exatamente 3 números por jogador, sem nada a mais, e nada a menos.

Entendeu?

de fato no meu jogo de bingo, eles entram em uma lista após sorteados, e se já conterem na lista após sorteados, um novo sorteio é feito e assim, até que o número não exista na lista. Esta foi a lógica que usei, para não sortear números repetidos…

no exemplo do contador, por talvez se contar com poucos casos (ou até quem sabe não, pois um único for pode verificar depois todas as posições do array),
pensei em seguir aquele princípio do ‘descobrir o maior’, que é tipo: ‘se maior vc separa o número e sempre fica comparando com o próximo, até que de fato sobre o maior’.

Porém com muitos números isso talvez fique trabalhoso ( ou não ) , foi a primeira idéia que me surgiu (ainda não sei se é a pior ou melhor, enfim.) , para cada número diferente, vc contaria um até que se fossem 3, e não usaria mais o número.

Porém a idéia da lista, me parece de fato melhor, pois muitos números podem ser usados e facilmente checados… outro ponto é que na lista, eu não podia ‘ver’ o número novamente, ou seja se existisse não seria mais utilizado,

de fato desta vez, vc quer que o número repita três vezes, então acho que de qualquer maneira vai ter que contar se eles estão ou não estão 3 vezes na lista…

Criar uma lista pronta e embaralhar também é uma boa solução, pois vc já determina quantos sorteios haverão e os mistura. Parece uma boa solução.

O que resolveu fazer? Se persistir a dúvida, tento ver se consigo algum código sobre contar os números…

no array embaralhado, que parece a melhor forma,ainda é possível, fazer um ‘arranjo’, para que a quantidade de números sejam variáveis, e com isto o tamanho dele, para que não seja um array único e definitivo. os números e o tamanho do array podem ser gerados por definição. não sei se é um quesito.

Porém este já é um outro passo.

raghy

Vou seguir a opção do Vini, se acertou certinho com meu projeto e serve para qualquer quantidade de valores. Obrigado pelas dicas.

ViniGodoy

Obrigado pelas dicas, foi de muita ajuda onde eu estava bem perdido. Eu realmente não tinha aprendido a substituir valores, vi que com essa lógica é bem simples de fazer a troca mesmo.

Uma outra duvida, é possível pegar um array e colocar ele dentro de um indice de outro array ?

ViniGodoy

Entendi sim, obrigado pelo seu tempo, de parar e me explicar (desenhar). Consegui dar andamento onde estava empacado.

[quote=RodrigoBC]raghy

Vou seguir a opção do Vini, se acertou certinho com meu projeto e serve para qualquer quantidade de valores. Obrigado pelas dicas.

ViniGodoy

Obrigado pelas dicas, foi de muita ajuda onde eu estava bem perdido. Eu realmente não tinha aprendido a substituir valores, vi que com essa lógica é bem simples de fazer a troca mesmo.

Uma outra duvida, é possível pegar um array e colocar ele dentro de um indice de outro array ?[/quote]

Um array inteiro? É possível, mas geralmente não é recomendável. O que exatamente você quer fazer?

Gostaria de criar alguns arrays, com o método que você me ajudou, e guardar dentro de outro array. Depois chamar um índice dentro no novo array e ele me apresentar os números embaralhados referente aquele indicie.

É possível sim. Um array bidimensional, no fundo, é um array de arrays.

//Aqui cabe 10 arrays que tenham 9 posições cada int[][] arrayDeArrays = new int[10][9];

Mas o ideal seria dividir isso em classes. Você já aprendeu sobre classes?