Ir ao conteúdo

C Preenchimento de valor aleatorio a vetor em C


Ir à solução Resolvido por devair1010,

Posts recomendados

Postado

Boa noite, Consigo preencher um valor aleatorio a um vetor, mas na hora de utilizar meu codigo da erro em algum ponto que eu não consigo saber e nem o porque. alguém pode me alertar pelo menos onde é? cheguei a localizaçao da funçao exibir, mas o que acontece lá e porque la ainda não sei. Segue o ocodigo:

planejo com este: Desenvolver uma função que percorrerá os
elementos de vetorX na ordem definida em
vetX1.

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define TAM 3

/*void preencherAleatorio (int vetor[], int tamanho)
{
    //declaração de variáveis
    int i, igual , j;


    srand(time(NULL));

    do{ // faça
        vetor[i] = rand() % tamanho; // sorteia um número
        igual = 0;
        for(j = 0; j < i; j++){ // percorre a parte do vetor já preenchida
            if(vetor[j] == vetor[i])
                igual = 1; // número repetido
        }

        if(igual == 0) // significa que o elemento não se repetiu
            i++;
    }while(i < tamanho); // enquanto não for sorteado TAM números diferentes

    for(i = 0; i < tamanho; i++){
        printf("%d ", vetor[i]);
    }
    printf("\n\n");
}*/
//implementação das funções
int exibirVetor (int vetor[], int tamanho, int vetor1[])
{
    //declaração de variáveis
    int i, j,cont = 0;

// passando um vetor dentro de outro para seguir ordem de posiçao
    printf ("\nVetor: ");

    for (i=0 ;i<tamanho;i++)
    {
    if(vetor1[vetor[i]] <= vetor1[vetor[i+1]]){
      cont++;
    }
        printf ("%d ", vetor1[vetor[i]]);
    }
    // 1 para crescente, 0 para não crescente
    if( cont == tamanho-1){
    return 1;
  }else{
    return 0;
  }
    printf ("\n\n");
}

int main(void) {
   int A[TAM] = {5,10,11}    ;
    int B[TAM] = {2,1,0} ; // usando um B pré ordenado para testar
  int C[TAM];
  int resp;

preencherAleatorio(C, TAM);
  resp = exibirVetor(C, TAM, A);
  printf ("\nVetor: %d ", resp);
    return 0;
}

 

  • Amei 1
  • Solução
Postado

@alan.modesto     você não disse que erro que dá , mas aqui no codeblocks , não deu nenhum erro , não , apenas também não fez nada ,  e  mostrou uma tela toda preta , 

cb3.thumb.jpg.fdcc0a0061f7f4b1828b2b513e1b1cd3.jpg

mas ele não funciona por que você não inicializou a variável "i"  , assim o valor é desconhecido e o compilador termina a execução para não gravar dados em local que não pode ,  e acertando isso ,  seria assim 

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define TAM 3
void preencherAleatorio (int vetor[], int tamanho)
{
  //declaração de variáveis
  int i     = 0;
  int igual = 0;
  int j     = 0;
  do  // faça
  {
    vetor[i] = rand() % tamanho; // sorteia um número
    igual = 0;
    for(j = 0; j < i; j++)  // percorre a parte do vetor já preenchida
    {
      if(vetor[j] == vetor[i])
        igual = 1; // número repetido
    }
    if(igual == 0) // significa que o elemento não se repetiu
      i++;
  } while(i < tamanho);  // enquanto não for sorteado TAM números diferentes

  for(i = 0; i < tamanho; i++)
  {
    printf("%d ", vetor[i]);
  }
  printf("\n\n");
}
//implementação das funções
int exibirVetor (int vetor[], int tamanho, int vetor1[])
{
  //declaração de variáveis
  int i, j,cont = 0;

// passando um vetor dentro de outro para seguir ordem de posiçao
  printf ("\nVetor: ");

  for (i=0 ; i<tamanho; i++)
  {
    if(vetor1[vetor[i]] <= vetor1[vetor[i+1]])
    {
      cont++;
    }
    printf ("%d ", vetor1[vetor[i]]);
  }
  // 1 para crescente, 0 para não crescente
  if( cont == tamanho-1)
  {
    return 1;
  }
  else
  {
    return 0;
  }
  printf ("\n\n");
}

int main(void)
{
  srand(time(NULL));
  int A[TAM] = {5,10,11}    ;
  int B[TAM] = {2,1,0} ; // usando um B pré ordenado para testar
  int C[TAM];
  int resp;

  preencherAleatorio(C, TAM);
  resp = exibirVetor(C, TAM, A);
  printf ("\nVetor: %d ", resp);
  return 0;
}

 

  • Curtir 1
Postado
int main(void) {
   int A[TAM] = {5,10,11}    ;
   int B[TAM] = {2,1,0} ; // usando um B pré ordenado para testar
   int C[TAM];

 

Não é preciso colocar o tamanho se vai declarar todos os valores. Prefira

 

int main(void) {
   int A[] = {5,10,11};
   int B[] = {2,1,0} ; // usando um B pré ordenado para testar
   int C[] = {0};// todos em zero

 

Sobre o valor aleatório não está bom. Já assistiu um sorteio da loto? Já jogou bingo?

 

Você não sorteia os números. Nunca. Sorteia as posições.

 

Veja como começa um sorteio:  o de 26/11/2022, hoje por exemplo... https://youtu.be/pWNVqCEwkbI?t=517 

 

Começa com a mala com as bolinhas. TODAS as bolinhas são iguais. Idênticas, perfeitamente esféricas e com números pintados com tinta do mesmo peso e são perfeitamente balanceadas. E vem um auditor e rompe o lacre.

 

É assim que funciona. Na literatura dizem que é um algoritmo e tem o nome de dois caras, Fisher e Yates. Masacho uma bobagem. A primeira vez em que eu programei isso eu tinha 14 e só fiz assim porque era o óbvio. Eis o tal "algoritmo" para 60 números da mega-sena:

  • São bolinhas numeradas de 1 a 60 e vem na mala lacrada
  • Vão todas para um único globo
  • O globo gira, tem um furo onde encaixa uma única bolinha
  • O globo para e com o peso embaixo a bolinha fica presa lá
  • o cara aperta o gatilho e a bolinha cai
  • o cara mostra o número para todo mundo e põe a bolinha numa canaleta 
  • o cara gira o globo mais 5 vezes e assim tem as 6 dezenas sorteadas.

É claro que não vai repetir porque no bingo as bolinhas não voltam para o globo. Esse é o erro de todo mundo que programa isso, ao que parece. É como as cartas o poker: não tem como repetir porque elas estão na mesa ou na mão de alguém. Esse é o erro desses programas: a ideia ingênua de sortear números de 1 a 60 por exemplo...E depois de sortear ficar testando pra ver se já tinha saído... E sempre sortear entre todas as bolinhas. Seria como o bingo da igreja colocar a bolinha de volta no globo. PARA QUE?? A cada sorteio tem uma bolinha a menos até ter 2 bolinhas, já que com uma só o sorteio é fácil: ELA, a única e última ou primeira 😉 

 

Como fazer então, e em C? Exemplo como a mega-sena loteria da CEF com bolinhas numeradas de 1 a 5 inclusive e sorteando 3 números

 

Apenas numere as bolas como o bingo. De qualquer jeito. O óbvio: numeradas. Como o bingo.

 

Um vetor. Só isso.

 

para 5 bolinhas:

 

	int T = 5; // total	T
	int N = T; // N faltam
	int bola[] = { 1,2,3,4,5 };

 

E antes de tudo como estão?

 

// as bolas inicialmente
	printf("Bolas no inicio: ");
	for (int i = 0; i < T; i += 1) printf("%d ", bola[i]);
	printf("\n");

 

E vai mostrar o que?

 

Bolas no inicio: 1 2 3 4 5

 

Sorteia 1 das 5 bolas

 

	int qual = rand() % N;

 

É só isso. Mas não tem a canaleta pra bolinha cair do globo como na CEF ou no bingo. 

 

Então faz o simples: coloca no fim ou no começo do vetor e diminui o número de bolas...

 

	// poe no fim: bola 1
	int temp = bola[N - 1];
	bola[N - 1] = bola[qual];
	bola[qual] = temp;
	printf("Bola: %d\n", bola[N-1]);

 

E vai mostrar o que?
 

Bola: 2

 

claro que é aleatório então pode ser qualquer valor entre 1 e 5 porque é a posição do vetor e não o valor que é sorteado. Esse é o erro comum de programas como esse. Deve ser pela falta de jogar bingo e pela ansiedade em escrever código em C ou Pascal ou Python ou FORTRAN ou sei lá em quantas linguagens já vi isso

 

E agora?

 

Já diminuiu o valor de N então é só fazer a mesma coisa e sortear uma das 4 bolinhas que sobrou...

 

	// poe no fim: bola 2
	N -= 1;
	qual = rand() % N;
	temp = bola[N - 1];
	bola[N - 1] = bola[qual];
	bola[qual] = temp;
	printf("Bola: %d\n", bola[N - 1]);

 

E mostra nesse exemplo

 

Bola: 4

 

 

Então no final do vetor tem as bolas 4 e 2. E tem ainda 3 bolinhas pra sortear

 

Então

 


	// poe no fim: bola 3
	N -= 1;
	qual = rand() % N;
	temp = bola[N - 1];
	bola[N - 1] = bola[qual];
	bola[qual] = temp;
	printf("Bola: %d\n", bola[N - 1]);

	// poe no fim: bola 4/5
	N -= 1;
	qual = rand() % N;
	temp = bola[N - 1];
	bola[N - 1] = bola[qual];
	bola[qual] = temp;
	printf("Bola: %d\n", bola[N - 1]);

 

Isso sorteia uma das 3 bolas e depois uma das 2 últimas.

 

O que mostrou?
 

Bola: 5
Bola: 1

 

E agora? Dá claro pra imaginar como ficou o vetor já que a lista de bolas sorteadas está bem aí, mas é melhor conferir

 

	printf("Bolas ao final: ");
	for (int i = 0; i < T; i += 1) printf("%d ", bola[i]);
	printf("\n");

	return 0;

 

E vem 

 

Bolas: 3 1 5 4 2

 

E é só isso.

 

Quer sortear 3 bolas? Pegue as 3 primeiras. 3 1 5

 

O programa todo
 

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

int main(void)
{
	int T = 5; // total	T
	int N = T; // N faltam
	int bola[] = { 1,2,3,4,5 };

// as bolas inicialmente
	printf("Bolas no inicio: ");
	for (int i = 0; i < T; i += 1) printf("%d ", bola[i]);
	printf("\n");

	int qual = rand() % N;

	// poe no fim: bola 1
	int temp = bola[N - 1];
	bola[N - 1] = bola[qual];
	bola[qual] = temp;
	printf("Bola: %d\n", bola[N-1]);

	// poe no fim: bola 2
	N -= 1;
	qual = rand() % N;
	temp = bola[N - 1];
	bola[N - 1] = bola[qual];
	bola[qual] = temp;
	printf("Bola: %d\n", bola[N - 1]);

	// poe no fim: bola 3
	N -= 1;
	qual = rand() % N;
	temp = bola[N - 1];
	bola[N - 1] = bola[qual];
	bola[qual] = temp;
	printf("Bola: %d\n", bola[N - 1]);

	// poe no fim: bola 4/5
	N -= 1;
	qual = rand() % N;
	temp = bola[N - 1];
	bola[N - 1] = bola[qual];
	bola[qual] = temp;
	printf("Bola: %d\n", bola[N - 1]);

	printf("Bolas ao final: ");
	for (int i = 0; i < T; i += 1) printf("%d ", bola[i]);
	printf("\n");
	return 0;
};

 

E uma saída

 

Bolas no inicio: 1 2 3 4 5
Bola: 2
Bola: 4
Bola: 5
Bola: 1
Bolas ao final: 3 1 5 4 2

 

Com 4 sorteios para 5 bolas. Mas se fossem 5000 seriam 4999 sorteios porque os números não voltam para o globo...

 

Note que  o programa não tem nenhum loop nem função nem nada. É uma prova de conceito e rodou assim na primeira vez. É o simples: escrever em torno dos dados.

 

 

É claro que se sair a última bola não precisa inverter

 

E claro que seria bom ter uma semente conhecida chamando srand() no inicio do programa. Em geral eu uso AAAAMMDD a data

 

É claro que isso devia estar em uma struct com o tamanho do vetor e o endereço

 

E isso não é importante. Importante é começar a testar em minutos e não voltar atrás. Não perder tempo

  • Curtir 1
  • Amei 1
Postado

De todo modo imagino que essa seja uma versão do tal algoritmo Fisher-Yates. Se eu tivesse um desses sobrenomes ia achar meio pedante ter meu sobrenome numa coisa tão simples e intuitiva. Ninguém no Bingo fala que está usando o algoritmo de Fisher-Yates. Da primeira vez que programei isso eu não sabia nem o que era um algoritmo ou que eles podiam ter nomes 😄 

 

Seguindo com o exemplo

 

O programa que eu mostrei serve como prova de conceito, pra ver se serve. Sem loop sem nada. Para testar em minutos e entender o mecanismo. É melhor escrever assim. Nunca um programa de 300 linhas com menu e interface e

tal.

 

Está claro agora que sorteia um número entre os possíveis, que estão no globo por exemplo. E continua até terem apenas dois. Então por isso se garante um número fixo de sorteios. 52 cartas no deck, 51 sorteios para embaralhar. Não tem sentido sortear sempre dos 52 e ver DEPOIS se repetiu. Por alguma razão quase todo mundo faz assim. Como o programa original desse tópico.

 

UM EXEMPLO MAIS COMPLETO, escrevendo em torno dos dados

 

typedef struct
{
  unsigned qtd;  // total
  int* V;        // o resultado
} Bloco;

 

Esse bloco é o simples container para um vetor de int de tamanho qtd e vou usar no exemplo para um sorteio da mega-sena e um deal de poker, texas holden com 4 jogadores, flop (3), turn (1) e river (1), as 5 cartas que ficam na mesa

 

Bloco* mix(unsigned t) {
  if (t == 0)
    return NULL;  // vai que...
  Bloco* novo = (Bloco*)malloc(sizeof(Bloco));
  if (novo == NULL)
    return NULL;  // deu pau
  novo->qtd = t;
  novo->V = (int*)malloc(t * sizeof(int));
  if (novo->V == NULL) {
    free(novo);
    return NULL;  // deu pau
  }
  for (unsigned i = 0, val = 0; i < t; ++i)
    novo->V[i] = ++val;
  for (unsigned N = t; N > 1; --N) {
    unsigned b = rand() % N;
    int temp = novo->V[N - 1];
    novo->V[N - 1] = novo->V[b];
    novo->V[b] = temp;
  }
  return novo;
};

 

Essa função mix() retorna um Bloco com os números emvaralhados. O simples. E serve para qualquer coisa

 

Eis main() no exemplo

 

int main(void)
{
  srand(20221125);
  Bloco* B = mix(60);
  mostra(B, "\nteste com 60 numeros (Mega-Sena)\n");
  mega(B);
  B = apaga(B);

  Bloco* deck = mix(52);
  mostra(deck, "\nteste com 52 (baralho)\n");
  texas_holden(deck);
  deck = apaga(deck);

  return 0;
};

 

E é fácil de entender. imagino. mix(60) traz um vetor de 60 números e pode ser usado na loteria, mix(52) embaralha 52 cartas. O simples.

 

mega() pega o bloco e pega 6 números para o sorteio.

texas_holden() pega um bloco e dá cartas para 4 jogadores e mostra as cartas do flop.

 

E é claro que tanto faz o que está sorteando. Podiam ser 5000 amostras com 4999 sorteios.

 

Eis a saída

 

teste com 60 numeros (Mega-Sena)
Bloco com 60 elementos

  55    43    24     5    21    12    20     9    19    58
  56    37    23    15     2    47    34    16    31    45
  51    59     1     8    52    17    35    53    27     6
  36    11    32    44    13     7    29    39     4    49
   3    42    30    28    46    48    38    18    54    41
  60    14    50    33    57    26    22    10    40    25


Um sorteio: 55  43  24  05  21  12

apagando bloco com 60 elementos

teste com 52 (baralho)
Bloco com 52 elementos

  10     5    45     1    41    23    12    34    15     8
  51    22    49     9    43     2    11    14    27    31
  38    40    29    39    37    28    32    35    47    46
   3    20    36    19     4    13    42    50    26    25
  52     7    30    18    21    24    33    48    16    44
  17     6

Jogador 1
  Dama de ouros
  Sete de ouros

Jogador 2
  Oito de paus
  Tres de ouros

Jogador 3
  Quatro de paus
  Dama de espadas

Jogador 4
  As de ouros
  Dez de copas

Flop
  Quatro de espadas
  Dez de ouros
  As de paus

Turn
  Valete de espadas

River
  Dama de paus


apagando bloco com 52 elementos

 

E o "programa" todo

 

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

typedef struct
{
  unsigned qtd;  // total
  int* V;        // o resultado
} Bloco;

Bloco* apaga(Bloco*);             // apaga um bloco
int mega(Bloco*);                 // exemplo 1
Bloco* mix(unsigned);             // retorna um sorteio
int mostra(Bloco*, const char*);  // mostra na tela o bloco
int texas_holden(Bloco*);         // exemplo 1

int main(void)
{
  srand(20221125);
  Bloco* B = mix(60);
  mostra(B, "\nteste com 60 numeros (Mega-Sena)\n");
  mega(B);
  B = apaga(B);

  Bloco* deck = mix(52);
  mostra(deck, "\nteste com 52 (baralho)\n");
  texas_holden(deck);
  deck = apaga(deck);

  return 0;
};

Bloco* apaga(Bloco* bl) {
  if (bl == NULL)
    return NULL;
  printf("apagando bloco com %d elementos\n", bl->qtd);
  free(bl->V);
  free(bl);
  return NULL;
}

int mega(Bloco* B) {
  printf("\nUm sorteio: ");
  for (int i = 0; i < 6; i += 1)
    printf("%02d  ", B->V[i]);
  printf("\n\n");
  return 0;
};

Bloco* mix(unsigned t) {
  if (t == 0)
    return NULL;  // vai que...
  Bloco* novo = (Bloco*)malloc(sizeof(Bloco));
  if (novo == NULL)
    return NULL;  // deu pau
  novo->qtd = t;
  novo->V = (int*)malloc(t * sizeof(int));
  if (novo->V == NULL) {
    free(novo);
    return NULL;  // deu pau
  }
  for (unsigned i = 0, val = 0; i < t; ++i)
    novo->V[i] = ++val;
  for (unsigned N = t; N > 1; --N) {
    unsigned b = rand() % N;
    int temp = novo->V[N - 1];
    novo->V[N - 1] = novo->V[b];
    novo->V[b] = temp;
  }
  return novo;
};

int mostra(Bloco* B, const char* msg) {
  const unsigned n_col = 10;
  if (B == NULL)
    return -1;
  if (msg != NULL)
    printf("%s", msg);
  printf("Bloco com %lu elementos\n\n", B->qtd);
  for (unsigned i = 0, col = 0; i < B->qtd; ++i) {
    printf("%4d  ", B->V[i]);
    if (++col == n_col) {
      printf("\n");
      col = 0;
    }
  };
  printf("\n");
  return 0;
};

int texas_holden(Bloco* deck) {
  const char* naipe[] = {"ouros", "espadas", "copas", "paus"};
  const char* face[] = {"Dois", "Tres", "Quatro", "Cinco", "Seis",
                        "Sete", "Oito", "Nove",   "Dez",   "Valete",
                        "Dama", "Rei",  "As"};
  int t = 0;

  // as cartas para alguns jogadores
  for (int player = 0; player < 4; ++player) {
    printf("\
\n\
Jogador %d\n\
  %s de %s\n", (1+ player), face[deck->V[t] % 13], naipe[deck->V[t] / 13]);
    t += 1;
    printf("  %s de %s\n", face[deck->V[t] % 13], naipe[deck->V[t] / 13]);
    t += 1;
  }

  // flop
  printf("\nFlop\n\
  %s de %s\n", face[deck->V[t] % 13], naipe[deck->V[t] / 13]);
  t += 1;
  printf("  %s de %s\n", face[deck->V[t] % 13], naipe[deck->V[t] / 13]);
  t += 1;
  printf("  %s de %s\n", face[deck->V[t] % 13], naipe[deck->V[t] / 13]);
  t += 1;

  // turn
  printf("\nTurn\n\
  %s de %s\n", face[deck->V[t] % 13], naipe[deck->V[t] / 13]);
  t += 1;

  // river
  printf("\nRiver\n\
  %s de %s\n\n\n", face[deck->V[t] % 13], naipe[deck->V[t]/ 13]);
  t += 1;

  return 0;
};

 

  • Obrigado 1

Crie uma conta ou entre para comentar

Você precisa ser um usuário para fazer um comentário

Criar uma conta

Crie uma nova conta em nossa comunidade. É fácil!

Crie uma nova conta

Entrar

Já tem uma conta? Faça o login.

Entrar agora

Sobre o Clube do Hardware

No ar desde 1996, o Clube do Hardware é uma das maiores, mais antigas e mais respeitadas comunidades sobre tecnologia do Brasil. Leia mais

Direitos autorais

Não permitimos a cópia ou reprodução do conteúdo do nosso site, fórum, newsletters e redes sociais, mesmo citando-se a fonte. Leia mais

×
×
  • Criar novo...