Já explicaram o seu erro, mas apenas para detalhar melhor.
Jogos.add(new ArrayList<>());
Aqui vc adiciona um novo ArrayList
em Jogos
. Mas depois vc faz:
Jogos.set(i, jogo);
Isso sobrescreve a lista que havia sido inserida, substituindo-a por jogo
.
Só que jogo
é uma referência para uma lista, então no fim vc está inserindo a mesma referência várias vezes em Jogos
. No final, Jogos
terá várias referências para a mesma lista jogo
. E como vc ainda faz jogos.clear()
, isso limpa a lista, e no final Jogos
tem várias referências para uma lista vazia.
Isso é porque vc imprime jogo
antes de chamar clear()
. Mas tente colocar System.out.println(Jogos)
depois do for
pra ver o que acontece: ele vai mostrar todas as listas vazias.
Outra coisa, para gerar números aleatórios sem repetição (como a amostragem é pequena: de 1 a 60), uma forma mais simples é simplesmente embaralhar todos os números e pegar os 6 primeiros (também conhecido como Algoritmo de Fisher-Yates).
Só que além disso, também precisa verificar se os 6 números sorteados já não estão na lista de Jogos
. Pra facilitar essa verificação, troquei List
por Set
(e usei TreeSet
, que já deixa os números em ordem). Além disso, isso já serve também para deixar indicado que os números não se repetem (um Set
, por definição, não permite elementos repetidos).
Por fim, sugiro que siga as convenções de nomenclatura da linguagem: nomes de variáveis e métodos começam com minúscula, e constantes (variáveis estáticas e final
), com NOMES_DESSE_JEITO.
Enfim, minha sugestão:
public class Sorteador {
// não precisa de getInstance(), inicialize o Random aqui mesmo
private static final Random RAND = new Random();
// lista de todos os números que podem ser sorteados
private List<Integer> numeros = new ArrayList<>();
// quantidade de números por sorteio
private int qtdPorSorteio;
private List<Set<Integer>> jogos = new ArrayList<>();
// sorteia números entre min e max, e com determinada quantidade de números por sorteio
public Sorteador(int min, int max, int qtdPorSorteio) {
for (int i = min; i <= max; i++) {
this.numeros.add(i);
}
this.qtdPorSorteio = qtdPorSorteio;
}
public void sortearJogos(int qntJogos) {
// limpa os jogos atuais
this.jogos.clear();
// sorteia novos
int i = 1;
while (this.jogos.size() < qntJogos) {
Collections.shuffle(this.numeros, RAND); // embaralha os números e pega os N primeiros (Fisher-Yates)
// pega os primeiros e adiciona na lista de jogos
Set<Integer> jogo = new TreeSet<>(this.numeros.subList(0, this.qtdPorSorteio));
if (! this.jogos.contains(jogo)) {
// só adiciona se não existe nenhum outro sorteio com os mesmos números
// por isso usei Set, que facilita muito essa comparação
// (com listas, precisaria ordenar o jogo antes de usar contains)
this.jogos.add(jogo);
System.out.printf("%d# Jogo: %s\n", i, jogo);
i++;
}
}
}
public void escolherJogo() {
if (this.jogos.size() > 0) {
System.out.println("Jogo da sorte: " + this.jogos.get(RAND.nextInt(this.jogos.size())));
} else {
System.out.println("Você precisa sortear jogos para escolher 1!!");
}
}
}
Adicionei uns parâmetros para deixar mais flexível. Pro seu caso (sortear 6 números entre 1 e 60), seria assim:
// números de 1 a 60, e 6 números por sorteio
Sorteador sorteador = new Sorteador(1, 60, 6);
sorteador.sortearJogos(4);
sorteador.escolherJogo();
Desta forma fica mais flexível, pois dá para usar a mesma classe para outros tipos de sorteio. Por exemplo, se for para a Quina (5 números de 1 a 80), bastaria usar new Sorteador(1, 80, 5)
.
Mas se quiser continuar usando List
em vez de Set
basta mudar para:
private List<List<Integer>> jogos = new ArrayList<>();
E o loop que sorteia os jogos mudaria para:
// sorteia novos
int i = 1;
while(this.jogos.size() < qntJogos) {
Collections.shuffle(this.numeros, RAND); // embaralha os números e pega os N primeiros (Fisher-Yates)
// pega os primeiros e adiciona na lista de jogos
List<Integer> jogo = new ArrayList<>(this.numeros.subList(0, this.qtdPorSorteio));
Collections.sort(jogo); // precisa ordenar, senão o contains não detecta jogos duplicados (caso os números estejam em ordem diferente)
if (! this.jogos.contains(jogo)) {
// só adiciona se não existe nenhum outro sorteio com os mesmos números
this.jogos.add(jogo);
System.out.printf("%d# Jogo: %s\n", i, jogo);
i++;
}
}
Precisa ordenar o jogo
porque senão o contains
não verifica jogos duplicados. Por exemplo, se um jogo for [1, 2, 3, 4, 5, 6] e outro for [6, 5, 4, 3, 2, 1], ele só detecta que o jogo já existe em jogos
se os números estiverem na mesma ordem (com Set
não tem esse problema).