Como adicionar probabilidade na programação?

Exemplo, se eu estiver criando um jogo q tenha 3 níveis de cartas, supondo que a carta nível 1 tenha probabilidade de 60%, a carta nível 2 30% e a carta nível 3 10%.

Como faço para codar probabilidade?

Uma maneira simples é usando java.util.Random para gerar um número aleatório, e depois você analisa o resultado assim:

Random rand = new Random();
int n = rand.nextInt(100);
if (n < 60) {
    // carta 1
} else if (n < 90) { // 90 porque é 60 + 30
    // carta 2
} else { // se não caiu em nenhum if, é porque é maior ou igual a 90, então caiu nos 10% restantes
    // carta 3
}

No caso, nextInt(100) gera um número entre zero e 99 (sim, o número que você passa - no caso, o 100 - não é incluso). Sendo assim, basta ver onde esse número caiu e retornar o valor da carta de acordo com as probabilidades.


Outra forma um pouco mais genérica é ter um array de probabilidades e seus respectivos valores:

int[][] probabilidades = {
    {60, 1}, // 60% de chance para carta 1
    {30, 2}, // 30% de chance para carta 2
    {10, 3}  // 10% de chance para carta 3
};

Assim, bastaria um método que recebe esse array e retorna o valor com base nas probabilidades:

public static int getCarta(Random rand, int[][] probabilidades) {
    int probabilidade = rand.nextInt(100) + 1;
    for (int[] v : probabilidades) {
        probabilidade -= v[0];
        if (probabilidade <= 0) {
            return v[1];
        }
    }
    // se a soma das probabilidades é 100, nunca vai chegar aqui (mas precisa ter essa linha para o "satisfazer" o compilador)
    return -1; 
}

E para usar:

Random rand = new Random();
int[][] probabilidades = {
    {60, 1}, // 60% de chance para carta 1
    {30, 2}, // 30% de chance para carta 2
    {10, 3}  // 10% de chance para carta 3
};
int carta = getCarta(rand, probabilidades);

Desta forma fica bem flexível, pois dá para mudar tanto o gerador de números aleatórios quanto as probabilidades e seus respectivos valores.

Obs: não usei Map porque podem ter casos em que dois valores tenham a mesma probabilidade, e como um Map não permite dois valores para a mesma chave, não serviria para este caso.


Um problema é que as porcentagens do array devem obrigatoriamente somar 100, senão não funciona adequadamente. Mas você pode adaptar para usar a soma das probabilidades:

public static int getCarta(Random rand, int[][] probabilidades) {
    int somaProbabilidades = 0;
    for (int[] v : probabilidades) {
        somaProbabilidades += v[0];
    }
    int probabilidade = rand.nextInt(somaProbabilidades) + 1;
    for (int[] v : probabilidades) {
        probabilidade -= v[0];
        if (probabilidade <= 0) {
            return v[1];
        }
    }
    return -1; 
}

Assim eu poderia ter, por exemplo, um array como { {3, 1}, {1, 2} } (ou seja, a carta 1 tem 3 vezes mais chances de sair do que a carta 2), e aí nem depende mais de porcentagem, pois agora pode ter a proporção que você quiser.

Vc é fera mano, valeu!