Primeira vez aqui? Seja bem vindo e cheque o FAQ!
x

Jogo de lançamento de dados

+1 voto
14 visitas
perguntada Nov 11 em Ciência da Computação por Renan Abrantes (16 pontos)  
editado Nov 13 por Renan Abrantes

Escreva um programa que simule um lançamento de dois dados, cada um assumindo os valores 1, 2,. . . , 6 com igual probabilidade. Se o total for 7 ou 11 no primeiro lançamento, o jogo está ganho. Se o total for 2, 3 ou 12 você perdeu o jogo; E em qualquer outro total, chame esse total de “ponto” e continue a lançar os dados até que ocorra um 7 (Você perde o jogo) ou o ponto ocorra novamente (Você ganha o jogo).
Jogue dez jogos. O resultado de cada lançamento dos dados deve ser impresso na forma m n, onde m e n são os conteúdos dos dois dados, seguido por algum comentário apropriado

Exercício 3 do livro The Art of Computer Programming, Donald E. Knuth, Capítulo: Random Numbers

Compartilhe

1 Resposta

0 votos
respondida Nov 13 por Renan Abrantes (16 pontos)  

O jogo descrito é um jogo de cassino chamado Craps, este jogo é fortemente influenciado pelo resultado do primeiro lançamento dos dados, vamos descrever as situações, do primeiro lançamento da seguinte forma:

  • A) Resulta nas somas 7 ou 11 e ganha o jogo
  • B) Resulta nas somas 2 ou 3 ou 12 e perde o jogo
  • C) Resulta nas outras somas e continua jogando

O algoritmo que implementa o jogo foi desenvolvido em python e utilizou a biblioteca random para gerar os inteiros aleatórios, esta função utiliza os ultimos bits do clock da cpu para gerar números aleatórios. O código desenvolvido pode ser visto abaixo:

from random import randint

for count in range(10): # Quantos testes
    print("--------------------- Jogo " + str(count+1) + " -----------------------" )
    fim = False # Encerrado do jogo
    i = 0
    obj = 0 # Ponto
    while not fim:
        lanc1 = randint(1, 6) # Lançamento do primeiro dado
        lanc2 = randint(1, 6) # Lançamento do segundo dado
        print("Resultado do lançamento "+ str(i+1)+":",lanc1,lanc2) 
        total = lanc1 + lanc2
        if (i == 0) and total in [7,11]: # Caso A
            print("Sorte de principiante! Você ganhou. :D")
            fim = True
        elif (i == 0) and total in [2,3,12]: # Caso B
            print("Que azar! Você perdeu. :c")
            fim = True
        elif (i == 0) and total in [4,5,6,8,9,10]: # Caso C
            print("Quase! Você ainda tem uma chance. Acerte "+str(total)+" para ganhar. :/")
        else:
            if(total == obj): # Acertou o ponto
                print("Tarda mas não falha, você ganhou. :D")
                fim = True
            if(total == 7): # Perdeu o jogo
                print("Demorou " + str(i+1) + " lançamentos mas você ainda perdeu! :C")   
                fim = True
        i += 1

O resultado dos 10 jogos pode ser visto abaixo:

--------------------- Jogo 1 -----------------------
Resultado do lançamento 1: 4 2
Quase! Você ainda tem uma chance. Acerte 6 para ganhar. :/
Resultado do lançamento 2: 1 3
Resultado do lançamento 3: 1 5
Resultado do lançamento 4: 5 5
Resultado do lançamento 5: 2 4
Resultado do lançamento 6: 1 6
Demorou 6 lançamentos mas você ainda perdeu! :C
--------------------- Jogo 2 -----------------------
Resultado do lançamento 1: 6 1
Sorte de principiante! Você ganhou. :D
--------------------- Jogo 3 -----------------------
Resultado do lançamento 1: 6 2
Quase! Você ainda tem uma chance. Acerte 8 para ganhar. :/
Resultado do lançamento 2: 1 6
Demorou 2 lançamentos mas você ainda perdeu! :C
--------------------- Jogo 4 -----------------------
Resultado do lançamento 1: 5 1
Quase! Você ainda tem uma chance. Acerte 6 para ganhar. :/
Resultado do lançamento 2: 4 6
Resultado do lançamento 3: 6 3
Resultado do lançamento 4: 1 2
Resultado do lançamento 5: 4 2
Resultado do lançamento 6: 4 1
Resultado do lançamento 7: 5 1
Resultado do lançamento 8: 1 6
Demorou 8 lançamentos mas você ainda perdeu! :C
--------------------- Jogo 5 -----------------------
Resultado do lançamento 1: 3 5
Quase! Você ainda tem uma chance. Acerte 8 para ganhar. :/
Resultado do lançamento 2: 4 5
Resultado do lançamento 3: 2 4
Resultado do lançamento 4: 4 6
Resultado do lançamento 5: 4 3
Demorou 5 lançamentos mas você ainda perdeu! :C
--------------------- Jogo 6 -----------------------
Resultado do lançamento 1: 1 4
Quase! Você ainda tem uma chance. Acerte 5 para ganhar. :/
Resultado do lançamento 2: 1 2
Resultado do lançamento 3: 6 3
Resultado do lançamento 4: 3 2
Resultado do lançamento 5: 1 4
Resultado do lançamento 6: 6 6
Resultado do lançamento 7: 4 1
Resultado do lançamento 8: 3 6
Resultado do lançamento 9: 2 4
Resultado do lançamento 10: 5 2
Demorou 10 lançamentos mas você ainda perdeu! :C
--------------------- Jogo 7 -----------------------
Resultado do lançamento 1: 4 3
Sorte de principiante! Você ganhou. :D
--------------------- Jogo 8 -----------------------
Resultado do lançamento 1: 1 3
Quase! Você ainda tem uma chance. Acerte 4 para ganhar. :/
Resultado do lançamento 2: 6 2
Resultado do lançamento 3: 1 2
Resultado do lançamento 4: 2 2
Resultado do lançamento 5: 6 5
Resultado do lançamento 6: 4 5
Resultado do lançamento 7: 1 1
Resultado do lançamento 8: 3 1
Resultado do lançamento 9: 6 1
Demorou 9 lançamentos mas você ainda perdeu! :C
--------------------- Jogo 9 -----------------------
Resultado do lançamento 1: 2 3
Quase! Você ainda tem uma chance. Acerte 5 para ganhar. :/
Resultado do lançamento 2: 1 5
Resultado do lançamento 3: 1 3
Resultado do lançamento 4: 2 3
Resultado do lançamento 5: 2 3
Resultado do lançamento 6: 5 5
Resultado do lançamento 7: 4 2
Resultado do lançamento 8: 4 6
Resultado do lançamento 9: 4 6
Resultado do lançamento 10: 1 6
Demorou 10 lançamentos mas você ainda perdeu! :C
--------------------- Jogo 10 -----------------------
Resultado do lançamento 1: 1 3
Quase! Você ainda tem uma chance. Acerte 4 para ganhar. :/
Resultado do lançamento 2: 6 6
Resultado do lançamento 3: 6 6
Resultado do lançamento 4: 6 3
Resultado do lançamento 5: 2 5
Demorou 5 lançamentos mas você ainda perdeu! :C

Sendo os dados não viciados a probabilidade de ocorrer a situação A é de 2/36 + 6/36 = 8/36, sendo 7 a soma com maior probabilidade de ocorrer. Já na situação B a chance é de 1/36 + 2/36 + 1/36 = 4/36. Por fim, a chance de ocorrer a situação C é de 24/36;

Para verificar se o algoritmo seguiu essa distribuição de probabilidade foi aumentado o número de vezes jogadas para 100000 e foi marcada cada situação e ao final divida sobre a quantidade de jogos. Estas alterações geraram o algoritmo abaixo:

from random import randint

A = 0
B = 0
C = 0
for count in range(100000): # Quantos testes
    fim = False # Encerrado do jogo
    i = 0
    obj = 0 # Ponto
    while not fim:
        lanc1 = randint(1, 6) # Lançamento do primeiro dado
        lanc2 = randint(1, 6) # Lançamento do segundo dado
        #print(lanc1,lanc2) 
        total = lanc1 + lanc2
        if (i == 0) and total in [7,11]: # Caso A
            #print("Sorte de principiante! Você ganhou. :D")
            fim = True
            A += 1
        elif (i == 0) and total in [2,3,12]: # Caso B
            #print("Que azar! Você perdeu. :c")
            fim = True
            B += 1
        elif (i == 0) and total in [4,5,6,8,9,10]: # Caso C
            #print("Quase! Você ainda tem uma chance. Acerte "+str(total)+" para ganhar. :/")
            C += 1
        else:
            if(total == obj): # Acertou o ponto
                #print("Tarda mas não falha, você ganhou. :D")
                fim = True
            if(total == 7): # Perdeu o jogo
                #print("Demorou " + str(i) + " mas você ainda perdeu! :C")   
                fim = True
        i += 1
print("Caso A: Teste --> " + str(round(A*100/(A+B+C),2)) + "%" + " Esperado --> " +     str(round(8*100/36,2)) + "%")
print("Caso B: Teste --> " + str(round(B*100/(A+B+C),2)) + "%" + " Esperado --> " +     str(round(4*100/36,2)) + "%")
print("Caso C: Teste --> " + str(round(C*100/(A+B+C),2)) + "%" + " Esperado --> " + str(round(24*100/36,2)) + "%")

A apresentação dos resultados de cada jogo foi comentado para facilitar o processamento, o resultado obtido do código foi:

Caso A: Teste --> 22.5% Esperado --> 22.22%
Caso B: Teste --> 11.13% Esperado --> 11.11%
Caso C: Teste --> 66.38% Esperado --> 66.67%

Os resultados de distribição de chances foi bem próximo com os valores esperados.

Foi densenvolvida uma trapaça, permitindo o lançamento novamente dos dados caso no primeiro lançamento não fosse vitória. Para verificar o efeito, foi atribuido o valor de 1 caso a pessoa ganhasse o jogo e 0 caso perdesse. Ao final dos teste foi verificado quantos jogos foram vencedores sobre o total com o seguinte código:

from random import randint

Trap = False
for i in range(2): # Com e sem Trapaça
    res = [] # Lista de resultados
    for count in range(100000): # Quantos teste 
        fim = False # Encerrado do jogo
        i = 0
        obj = 0 # Ponto
        while not fim:
            lanc1 = randint(1, 6) # Lançamento do primeiro dado
            lanc2 = randint(1, 6) # Lançamento do segundo dado
            #print(lanc1,lanc2) 
            total = lanc1 + lanc2
            if Trap and (i == 0) and total not in [7,11]: # Segundo lançamento no caso de trapaça
                    lanc1 = randint(1, 6)
                    lanc2 = randint(1, 6)
                    #print("Trapaça")
                    #print(lanc1,lanc2)
                    total = lanc1 + lanc2
            if (i == 0) and total in [7,11]: # Caso A
                #print("Sorte de principiante! Você ganhou. :D")
                fim = True
                res.append(1)
            elif (i == 0) and total in [2,3,12]: # Caso B
                #print("Que azar! Você perdeu. :c")
                fim = True
                res.append(1)
            elif (i == 0) and total in [4,5,6,8,9,10]: # Caso C
                #print("Quase! Você ainda tem uma chance. Acerte "+str(total)+" para ganhar. :/")
                obj = total
            else:
                if(total == obj): # Acertou o ponto
                    #print("Tarda mas não falha, você ganhou. :D")
                    fim = True
                    res.append(1)
                if(total == 7): # Perdeu o jogo
                    #print("Demorou " + str(i) + " mas você ainda perdeu! :C")   
                    fim = True
                    res.append(0)
            i += 1
    if not Trap:
        Trap = True
        print("Vitórias sem Trapaça: " + str(round(sum(res)*100/len(res),2)) + "%")
    else:
        print("Vitórias com Trapaça: " + str(round(sum(res)*100/len(res),2)) + "%")

A apresentação dos resultados de cada jogo foi comentado para facilitar o processamento, o resultado obtido do código foi:

Vitórias sem Trapaça: 60.27%
Vitórias com Trapaça: 69.09%

Aumentou as vitórias como esperado.

comentou Nov 20 por Stuart Mill (1,434 pontos)  
Muito legal o problema e sua solução. Apenas dois comentários rápidos que talvez façam sentido para otimização se você quisesse fazer uma simulação de Monte Carlo grande do jogo:
1) Em `lanc1`e `lanc2`, você chama `randint` separadamente para gerar um inteiro em cada caso. Seria mais eficiente você gerar um array gigantesco com muitos dados de uma vez, usando por exemplo o `numpy.random.randint`e usar um `size` grande. Isso pode fazer muita diferença em simulações grandes.
2) Novamente, talvez não faça muita diferença no seu caso (talvez faça para as simulações), mas é mais eficiente checar inclusão em um `set` do que em uma `list`. Então por exemplo, talvez fosse melhor usar `if Trap and (i == 0) and total not in {7,11}:`, etc.
Mas novamente, talvez não faça muita diferença no seu caso.
...