Solucionado (ver solução)
Solucionado
(ver solução)
4
respostas

Diferentes comportamentos da função rand()

Olá, estou criando este tópico devido um problema que eu me deparei quando estava criando um algorítimo de sorteio que varia as chances de acerto de acordo com a porcentagem inserida.

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <conio.h>

int ChanceDrop(float porcent);

int main(void)
{
    while (1)
    {
        //srand(time(NULL));
        if (ChanceDrop(14)) //14%
        {
            printf("ganhou\n");
        }
        else
        {
            printf("nao ganhou\n");
        }
        getch();
    }
    return 0;
}
int ChanceDrop(float porcent)
{
    int intervalo = 2, i = 0, n, v = 0;
    int *prob = malloc(sizeof(int) * n);
    if (porcent > 1 && (int)(porcent * 10) % 10 == 0) //se a porcentagem for inteira
    {
        n = 100;
        if (porcent > 50)
        {
            intervalo = 1;
        }
        while (porcent >= 1) //grava os numeros da porcentagem dentro da matriz
        {
            prob[i] = porcent;
            i += intervalo;
            porcent--;
        }
    }
    else if (porcent > 1 && (int)(porcent * 10) % 10 != 0 || porcent < 1) //se a porcentagem tiver decimais ou ser menor que 1  ex: 12.2% e 0.5%
    {
        n = 1000;
        porcent *= 10;
        if (porcent <= 500)
        {
            intervalo = 2; //distribui os numeros da porcentagem com espaço de 1 bloco dentro  dentro da matriz
        }
        else if (porcent > 500)
        {
            intervalo = 1;
        }
        while (porcent >= 1)
        {
            prob[i] = porcent;
            i += intervalo;
            porcent--;
        }
    }
    //srand(time(NULL));
    v = (rand() % n) + 1; //sorteia numeros no intervalo de 1 e o numero de blocos dentro da matriz
    printf("n: %d\n", v); //para saber o numero sorteado
    if (prob[v] != 0)
    {
        return 1;
    }
    else
    {
        return 0;
    }
}

Ok, esse é o meu codigo. O problema que eu encontrei foi na hora de colocar a função srand(time(NULL)). Como vocês podem ver no meu código, ela aparece duas vezes comentada no meu código. A primeira é na main(), a segunda é logo acima da função rand(). Quando eu botei o codigo para rodar com a srand(time(NULL)) habilitada em cima da rand(), o codigo compilou mas não rodou. Quando eu habilitei a mesma função na main(), o codigo compilou e rodou, mas eu percebi que os numeros sorteados seguiam uma sequencia crescente (se o primeiro numero sorteado fosse 88, o proximo seria qualquer outro numero acima de 88 até chegar em 100 e a sequencia de numeros crescentes reiniciaria). Por fim, eu desabilitei a srand(time(NULL)) em todo meu codigo e para a minha surpresa, ele não só compilou, como rodou com perfeição, sorteando numeros aleatorios e sem sequancias crescentes ou decrescentes.(oque para mim não faz sentido, pois a rand() precisa da srand(time(NULL)) para gerar novos numeros aleatorios). Se alguém pudesse me ajudar a entender o por que disso acontecer ou me apresentar outro codigo/função que realize a mesma coisa que esse escrito por mim, seria de grande ajuda. Desde já, grato!

4 respostas
solução!

Boa noite, Eduardo.

A melhor posição para o seu "srand" seria antes do while. Dessa forma você só passaria uma semente para sua função rand a cada vez que executava.

Ao chamar dentro de um loop vc está alterando a semente toda hora, o que pode ocasionar esses problemas que citou.

Outro problema que vi no seu código é na função "ChanceDrop". A variável "n" não está iniciada, mas ainda assim você usa ela para fazer um cálculo de malloc. Aquele "n=100" não deveria ser a inicialização da variável?

Olá, alexandre. Muito obrigado pela ajuda com a srand(), sua explicação conseguiu solucionar o meu problema! Agora em relação a inicialização da variável "n", oque eu fiz foi uma alocação dinamica(ou pelo menos é oq eu imagino ter feito), porque ela tanto pode ser "n = 100" como "n = 1000" dependendo de qual dos dois if's tiverem sua condição satisfeita. Você poderia me mostrar como que faz corretamente? Pois eu achava ter feito certo, até por que o codigo está funcionando normalmente como foi feito para ser.

O malloc está correto. O problema é que vc não inicializou o n antes. Como a variavel "prob" vc só usa dentro do while, e esse while é igual tanto no if quanto no else, vc pode jogar ele pra fora e fazer o malloc logo antes do while.

Dessa forma vc vai alocar o tamanho correto para "prob" (100 ou 1000 inteiros)

int ChanceDrop(float porcent)
{
    int intervalo = 2, i = 0, n, v = 0;
    if (porcent > 1 && (int)(porcent * 10) % 10 == 0) //se a porcentagem for inteira
    {
        n = 100;
        if (porcent > 50)
        {
            intervalo = 1;
        }
    }
    else if (porcent > 1 && (int)(porcent * 10) % 10 != 0 || porcent < 1) //se a porcentagem tiver decimais ou ser menor que 1  ex: 12.2% e 0.5%
    {
        n = 1000;
        porcent *= 10;
        if (porcent > 500)
        {
            intervalo = 1;
        }

    }

    int *prob = malloc(sizeof(int) * n);
    while (porcent >= 1)
    {
        prob[i] = porcent;
        i += intervalo;
        porcent--;
    }

    //srand(time(NULL));
    v = (rand() % n) + 1; //sorteia numeros no intervalo de 1 e o numero de blocos dentro da matriz
    printf("n: %d\n", v); //para saber o numero sorteado
    if (prob[v] != 0)
    {
        return 1;
    }
    else
    {
        return 0;
    }
}

Muito obrigado!