[Resolvido] Probabilidade (55%)

Olá, no desenvolvimento de um jogo de dados onde a “casa” tem 55% de chance de ganhar, e o apostador 45% de chance, eu me deparei com um problema.

Porém como não sou muuuito bom em matemática/probabilidade está difícil de raciocinar.

No jogo atual, um número randômico é gerado (0 - 100)

caso random < 55 (Casa ganha a partida)
caso random == 55 (Repete a partida)
caso random > 55 (Apostador ganha a partida)

Porém está ocorrendo casos de apostador/casa ganhar 11 vezes seguidas.
Então cheguei à uma conclusão (talvez equívoca) de que na verdade como a probabilidade de cair qualquer número é de 1% (1/100) o 55% só seria perceptível em uma larga escala de apostas.

Então penso em criar menos probabilidades de números. A princípio pensei em simplesmente fazer “2” (0 - 1)
Porém eu estaria ignorando os 5% que a casa tem de vantagem.

Então eu pensei em duas soluções:

1 - Criar uma boolean randômica de duas probabilidades (new Random().nextBoolean());
e caso a casa perca, seria gerado um número decimal entre 0 e 1 sendo assim:

se casa perdeu:
gera randômico 0 - 1
se randômico < 0.05 (5% de 1)
casa ganhou
senão
casa perdeu;

Algorítimo.

[code] boolean hostWins = new Random().nextBoolean();
double modificator = (Math.floor(new Random().nextFloat() * 100) / 100);
if(!hostWins && modificator < 0.05)
hostWins = true;

		return hostWins;

[/code]

2 - Criar um número decimal randômico entre 0 e 1, arredondar o número decimal em até duas casas dando 5% de vantagem para casa na hora de arredondar.

caso randômico seja < 0.55 (Casa ganha)
caso randômico seja == 0.55 (Empata)
caso randômico seja > 0.55 (Apostador ganha)

Algorítimo. (0.4 = vantagem)

float randomValue = new Random().nextFloat(); float rollAmount = (float) (Math.floor(randomValue * 10 + 0.4) / 10); if (rollAmount < 0.55) { hosterWins++; } else if (rollAmount > 0.55) { betterWins++; } else { draws++; }

Porém fica muito possível que haja várias vitórias consecutivas:

[quote]Hoster wins
Hoster wins
Hoster wins
Hoster wins
Hoster loses
Hoster loses
Hoster loses[/quote]

O que eu precisaria é que a porcentagem fosse perceptível em baixa escala de apostas (De preferência sem muito uso de lógica).
É possível?

Obrigado!

Edit: Até que ficou razoável o segundo algorítimo.

[quote]Bet Amount: 100
Hoster: 58
Better: 42
Bigger Hoster Win Rows: 6
Bigger Better Win Rows: 4[/quote]

[quote=pb600]Olá, no desenvolvimento de um jogo de dados onde a “casa” tem 55% de chance de ganhar, e o apostador 45% de chance, eu me deparei com um problema.

Porém como não sou muuuito bom em matemática/probabilidade está difícil de raciocinar.

No jogo atual, um número randômico é gerado (0 - 100)

caso random < 55 (Casa ganha a partida)
caso random == 55 (Repete a partida)
caso random > 55 (Apostador ganha a partida)

Porém está ocorrendo casos de apostador/casa ganhar 11 vezes seguidas.
Então cheguei à uma conclusão (talvez equívoca) de que na verdade como a probabilidade de cair qualquer número é de 1% (1/100) o 55% só seria perceptível em uma larga escala de apostas.

Então penso em criar menos probabilidades de números. A princípio pensei em simplesmente fazer “2” (0 - 1)
Porém eu estaria ignorando os 5% que a casa tem de vantagem.

Então eu pensei em duas soluções:

1 - Criar uma boolean randômica de duas probabilidades (new Random().nextBoolean());
e caso a casa perca, seria gerado um número decimal entre 0 e 1 sendo assim:

se casa perdeu:
gera randômico 0 - 1
se randômico < 0.05 (5% de 1)
casa ganhou
senão
casa perdeu;

Algorítimo.

[code] boolean hostWins = new Random().nextBoolean();
double modificator = (Math.floor(new Random().nextFloat() * 100) / 100);
if(!hostWins && modificator < 0.05)
hostWins = true;

		return hostWins;

[/code]

2 - Criar um número decimal randômico entre 0 e 1, arredondar o número decimal em até duas casas dando 5% de vantagem para casa na hora de arredondar.

caso randômico seja < 0.55 (Casa ganha)
caso randômico seja == 0.55 (Empata)
caso randômico seja > 0.55 (Apostador ganha)

Algorítimo. (0.4 = vantagem)

float randomValue = new Random().nextFloat(); float rollAmount = (float) (Math.floor(randomValue * 10 + 0.4) / 10); if (rollAmount < 0.55) { hosterWins++; } else if (rollAmount > 0.55) { betterWins++; } else { draws++; }

Porém fica muito possível que haja várias vitórias consecutivas:

[quote]Hoster wins
Hoster wins
Hoster wins
Hoster wins
Hoster loses
Hoster loses
Hoster loses[/quote]

O que eu precisaria é que a porcentagem fosse perceptível em baixa escala de apostas (De preferência sem muito uso de lógica).
É possível?

Obrigado![/quote]

A única parte que importa de tudo o que você escreveu é isso:

caso random < 55 (Casa ganha a partida)
caso random == 55 (Repete a partida)
caso random > 55 (Apostador ganha a partida)

Na verdade, daria até pra tirar o empate, basta o sorteio ser entre 0 e 99 ou entre 1 e 100.

O restante, é tudo gambi.

O fato de cair 11 seguidas não desmerece a sua implementação. Acho que é pouco provável de ocorrer, mas pode. Se quiser testar, procure por teste de hipótese, onde você calcularia a probabilidade de dar 11 vitórias seguidas pro apostador, dado que ele tem 45% de chance de ganhar.

O problema é que você está fazendo testes com poucas jogadas (essa sua hipótese está correta). Isso não quer dizer que testando com muitas, há garantias de que irá se comportar da maneira correta (se estiver bem implementado), mas a probabilidade de dar algo fora do esperado com, digamos, 100000 testes, é muito pequena.

Acredito que você nunca tenha feito teste automatizado, então acho que essa é a hora.

Faça um método que gera 100000 apostas e conta quantas vezes cada uma das partes venceu. Se as probabilidades derem perto do esperado (44 e 56% ou 46 e 54%, por exemplo) então a sua implementação muito provavelmente está correta e não há com o que se preocupar se deu 11 vezes seguidas pro apostador. Se não der dentro do esperado, arruma o que você fez, ao invés de tentar “consertar” com uma gambi :slight_smile:

Olá, obrigado pela resposta.

Sim eu já havia executado testes automatizados, eu até editei postando minutos antes de seu comentário.

O meu problema é que quando ocorre muitos resultados semelhantes o jogador sente que está sendo roubado pelo jogo, e não adianta falar: Probabilidade é assim mesmo… Só que estava ocorrendo muito de 11 - 7 vitórias/derrotas seguidas.
Com o meu segundo algorítimo, a porcentagem está perfeita, e até ficou melhor que um simples random do java, e agora ocorre de ganhar 12 vezes seguidas mas quando em muitas apostas.

Bet Amount: 10000 Hoster: 5584 Better: 4416 Bigger Hoster Win Rows: 15 Bigger Better Win Rows: 10

Bet Amount: 500 Hoster: 271 Better: 229 Bigger Hoster Win Rows: 9 Bigger Better Win Rows: 8

Você diz que não tem solução? (Imagina você apostando dinheiro e perde 8 vezes seguidas quando a proposta é de 45% de chance)

O que está errado na sua implementação é fazer diretamente new Random().nextFloat().

Isso força a criar um objeto random a cada jogada e, se fizer isso num loop de maneira seguida, o número sorteado será o mesmo. Isso porque o Random gera uma sequencia pseudo-aleatória baseada numa semente.
Se não for informada, a semente será o horário atual do sistema, que não muda entre 2, 3, ou até 10 loops consecutivos.

Como você está descartando e recriando o Random sempre, você acaba vendo várias vezes seguidas o primeiro número dessa sequencia.

Eu implementaria o algoritmo assim:

[code]public class Game {
private static final Random RANDOM = new Random();

/** Faz o sorteio e indica se o jogador ganhou */
public boolean sortear() {
       return RANDOM.nextInt(100) &lt;= 45;
 }

}[/code]

[quote=ViniGodoy]O que está errado na sua implementação é fazer diretamente new Random().nextFloat().

Isso força a criar um objeto random a cada jogada e, se fizer isso num loop de maneira seguida, o número sorteado será o mesmo. Isso porque o Random gera uma sequencia pseudo-aleatória baseada numa semente.
Se não for informada, a semente será o horário atual do sistema, que não muda entre 2, 3, ou até 10 loops consecutivos.

Como você está descartando e recriando o Random sempre, você acaba vendo várias vezes seguidas o primeiro número dessa sequencia.

Eu implementaria o algoritmo assim:

[code]public class Game {
private static final Random RANDOM = new Random();

public boolean sortear() {
       return RANDOM.nextInt(100) &lt;= 45;
 }

}[/code]
[/quote]

Sim Vini, esqueci de avisar que na implementação real eu utilizaria uma única instância para manter um único seed :stuck_out_tongue:
E no teste automatizado eu esperei 30 segundos para começar operação, e dei um intervalo de tempo entre cada operação.
Na aplicação real provavelmente a quantidade de repetições de ganhador seria menor pois o intervalo de tempo entre cada aposta é consideravelmente grande :stuck_out_tongue:

return RANDOM.nextInt(100) &lt;= 45; 

A princípio eu fazia ± assim (Nesse exemplo é 46% de chance de ganhar/perder), isso provou ser muito ineficaz, resultando em mais de 11 vitórias/derrotas seguidas.

Obrigado :stuck_out_tongue:

É bom você ler esse artigo:

Esses aqui também podem ajudar:


Uma forma de deixar o jogo mais divertido seria avisar ao jogador que num lance de 4 dados, ele deveria tirar um número menor ou igual 13. Isso dá 44.3% de chance de acerto.
Ou então, dizer que se ele tirar um valor inferior a 14, ele irá perder o jogo (o que ocorre em 55.6% dos casos).

Na prática, dá na mesma, e ele ainda tem chance de ganhar ou perder várias vezes seguidas. Mas o jogador fica entretido ao ver números diferentes, ao invés de dizer que só “ganhou” ou “perdeu”. Ele também começa a criar superstições próprias, como achar que se está tirando números altos em 2 “dados” estará com chances de tirar números altos nos outros dois também, ou que está conseguindo se aproximar ou se afastar dos números corretos a cada jogada.

Você pode conferir mais probabilidades de dados aqui: http://alumnus.caltech.edu/~leif/FRP/probability.html

[quote=ViniGodoy]É bom você ler esse artigo:

Esses aqui também podem ajudar:


Uma forma de deixar o jogo mais divertido seria avisar ao jogador que num lance de 4 dados, ele deveria tirar um número menor ou igual 13. Isso dá 44.3% de chance de acerto.
Ou então, dizer que se ele tirar um valor inferior a 14, ele irá perder o jogo (o que ocorre em 55.6% dos casos).

Na prática, dá na mesma, mas o jogador fica entretido ao ver números diferentes, ao invés de dizer que só “ganhou” ou “perdeu”. Ele também começa a criar superstições próprias, como achar que se está tirando números altos em 2 “dados” estará com chances de tirar números altos nos outros dois também.[/quote]

Obrigado Vini, O jogador vê um número entre 0 - 100 no formato de porcentagem, e sim eles acham que apostando baixo e perdendo vão ganhar na próxima ^^ Pena que quando perdem colocam a culpa no sistema hehe. E como é jogador contra jogador, um sempre perde. Ou seja cada jogada o sistema perde Karma do pessoal :lol:
Eu deveria é anexar esses artigos para os jogadores :stuck_out_tongue:

Resolvi utilizar o algorítimo que criei mesmo, pois apresentou resultados mais interessantes.

float rollAmount = (float) (Math.floor(random.getFloat() * 10 + 0.4) / 10);