Ir ao conteúdo
  • Comunicados

    • Gabriel Torres

      Seja um moderador do Clube do Hardware!   12-02-2016

      Prezados membros do Clube do Hardware, Está aberto o processo de seleção de novos moderadores para diversos setores ou áreas do Clube do Hardware. Os requisitos são:   Pelo menos 500 posts e um ano de cadastro; Boa frequência de participação; Ser respeitoso, cordial e educado com os demais membros; Ter bom nível de português; Ter razoável conhecimento da área em que pretende atuar; Saber trabalhar em equipe (com os moderadores, coordenadores e administradores).   Os interessados deverão enviar uma mensagem privada para o usuário @Equipe Clube do Hardware com o título "Candidato a moderador". A mensagem deverá conter respostas às perguntas abaixo:   Qual o seu nome completo? Qual sua data de nascimento? Qual sua formação/profissão? Já atuou como moderador em algo outro fórum, se sim, qual? De forma sucinta, explique o porquê de querer ser moderador do fórum e conte-nos um pouco sobre você.   OBS: Não se trata de função remunerada. Todos que fazem parte do staff são voluntários.
    • DiF

      Poste seus códigos corretamente!   21-05-2016

      Prezados membros do Fórum do Clube do Hardware, O Fórum oferece um recurso chamado CODE, onde o ícone no painel do editor é  <>     O uso deste recurso é  imprescindível para uma melhor leitura, manter a organização, diferenciar de texto comum e principalmente evitar que os compiladores e IDEs acusem erro ao colar um código copiado daqui. Portanto convido-lhes para ler as instruções de como usar este recurso CODE neste tópico:  
Leandro Arnold

C Problema no sorteio das perguntas

Recommended Posts

Postado (editado)

Olá companheiros de fórum

 

Estou com o seguinte problema em meu programa.

Eu construiu um jogo de perguntas e respostas, um quis, utilizando arquivos e funções. Entretanto, o computador sorteia a mesma pergunta mais de uma vez.

Como eu poderia resolver isso?

 

Desde já agradeço pela ajuda. Um cordial abraço!

 

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

int pergunta;
char resposta;
char arquivopergunta[20];
char arquivoresposta[10];

void concatenapergunta(){
	char arquivo[]="pergunta";
	char n[2];
	char extans[]=".qiz";
	
	srand(time(NULL));	
	pergunta=1+(rand()%10);
	
	sprintf(n,"%d",pergunta);
	strcat(arquivo,n);
	strcat(arquivo,extans);
	
	strcpy(arquivopergunta,arquivo);
}

void concatenaresposta(){
	char arquivo[]="resposta";
	char n[2];
	char extans[]=".qiz";
	sprintf(n,"%d",pergunta);
	strcat(arquivo,n);
	strcat(arquivo,extans);
	
	strcpy(arquivoresposta,arquivo);
}

void lepergunta(){//arquivo para a pergunta
	concatenapergunta();
	concatenaresposta();
	
 	FILE *f;//ponteiro
 	f=fopen (arquivopergunta,"r");//função para abrir o arquivo, tipo do arquivo e visibilidade
 	char c;
	//printf("entrou, %s", arquivopergunta);
 	while(1){
 		c=fgetc(f);//armazenar cada caractere que tiver no arquivo
 		if(c==EOF){//final do arquivo
 			break;
 			
 		}
 		printf("%c",c);

 	}
 	printf("\n");
 	fclose(f);
 }
 
void responde(){//função para responder
	FILE *F;
	char c;
	printf("\nInforme sua resposta: ");
	scanf("%c",&resposta);
	fflush(stdin);
}

void checar(){//função para checar se a resposta está correta e contem o arquvio da redposta
	FILE *f;
	char c;f=fopen(arquivoresposta,"r");
	c=fgetc(f);
	if(c==resposta){
		printf("\n\nParabens voce acertou!");
	}
	else{
		printf("\n\nVoce errou");
	}
	printf("\n\n");
}
 int main(){	
     int i, nperguntas;
     printf("\nInforme quantas perguntas voce quer responder?");
     scanf("%d",&nperguntas);
     fflush(stdin);
     
     for(i=0;i<nperguntas;i++){
 	  lepergunta();//arquivo da pergunta
 	  responde();
 	  checar();//aarquivo da resposta
    }
 	return 0;
}



 

 

Editado por Leandro Arnold
  • Curtir 1

Compartilhar este post


Link para o post
Compartilhar em outros sites

@Leandro Arnold  Quantas perguntas seriam? 10? Se é isso faz assim:

 

srand(time(NULL));	
pergunta = (rand() % 10) + 1;

Mas, se são dez perguntas, as chances da mesma pergunta aparecer mais de uma vez são grandes

Compartilhar este post


Link para o post
Compartilhar em outros sites

@Leandro Arnold  Olá. Uma sugestão q eu daria para que as perguntas não se repitam é fazer uso do algoritmo Knuth Fisher-Yates. Esse algoritmo embaralha um vetor (aprendi a respeito dele aqui)

Segue um exemplo do seu uso. Perceba que faço uso de 10 valores, de 1 a 10, incluindo e em nenhum momento os valores se repetem. Dá uma olhada no código para ver se ajuda:

 

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

#define QTDE 10

int main()
{
    int i, j, n, temp;
    int vet[QTDE];

    srand(time(NULL));

    for (i = 0; i < QTDE; i++)
    {
        vet[i] = i + 1;
    }

    for (i = 0; i < QTDE; i++) {
        printf("%d ", vet[i]);
    }

    //Embaralha os números no vetor (algoritmo Knuth Fisher-Yates)
    for (i = 10; i >= 1; i--)
    {
        n = rand() % (i + 1);

        temp = vet[i];
        vet[i] = vet[n];
        vet[n] = temp;
    }

    printf("\n\n");
    for (i = 0; i < 10; i++)
    {
        printf("%d ", vet[i]);
    }

    printf("\n");

    return 0;
}

Se você conseguir adaptar esse código ao seu exercício creio q vai solucionar o problema de perguntas repetidas

  • Curtir 2

Compartilhar este post


Link para o post
Compartilhar em outros sites
12 horas atrás, giu_d disse:

@Leandro Arnold  Olá. Uma sugestão q eu daria para que as perguntas não se repitam é fazer uso do algoritmo Knuth Fisher-Yates. Esse algoritmo embaralha um vetor (aprendi a respeito dele aqui)

Segue um exemplo do seu uso. Perceba que faço uso de 10 valores, de 1 a 10, incluindo e em nenhum momento os valores se repetem. Dá uma olhada no código para ver se ajuda:

 


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

#define QTDE 10

int main()
{
    int i, j, n, temp;
    int vet[QTDE];

    srand(time(NULL));

    for (i = 0; i < QTDE; i++)
    {
        vet[i] = i + 1;
    }

    for (i = 0; i < QTDE; i++) {
        printf("%d ", vet[i]);
    }

    //Embaralha os números no vetor (algoritmo Knuth Fisher-Yates)
    for (i = 10; i >= 1; i--)
    {
        n = rand() % (i + 1);

        temp = vet[i];
        vet[i] = vet[n];
        vet[n] = temp;
    }

    printf("\n\n");
    for (i = 0; i < 10; i++)
    {
        printf("%d ", vet[i]);
    }

    printf("\n");

    return 0;
}

Se você conseguir adaptar esse código ao seu exercício creio q vai solucionar o problema de perguntas repetidas

Tentei seguir esse método amigo, mas não consegui embaralhar as perguntas. O número de perguntas é o usuário que define.

 

Tentei assim:

# define pergunta 10
  
  void concatenapergunta(){
	int i, j, ne, temp;
	int vet[pergunta];
	char arquivo[]="pergunta";
	char n[2];
	char extans[]=".qiz";
	
	srand(time(NULL));
	
	for (i = 0; i < pergunta; i++){
        vet[i] = i + 1;
    }

    for (i = 0; i < pergunta; i++) {
    }
		
    for (i = 10; i >= 1; i--){
        ne = rand() % (i + 1);
        temp = vet[i];
        vet[i] = vet[ne];
        vet[ne] = temp;
    }
	
	sprintf(n,"%d",pergunta);
	strcat(arquivo,n);
	strcat(arquivo,extans);
	
	strcpy(arquivopergunta,arquivo);
}

Não deu certo, agora só aparece a mesma pergunta.

Compartilhar este post


Link para o post
Compartilhar em outros sites

@Leandro Arnold Olá. Pelo q vi no seu código anterior a esse e pelo q você falou é o usuário que define a quantidade de perguntas. Logo, na função que seleciona as perguntas, teria que passar essa qtde de perguntas para ser usada no código.

Também tem o seu comando sprintf() que não está sendo usado de maneira correta. Do modo como está, toda vez a pergunta de número 10 vai aparecer, isso porque o valor da variável 'pergunta' é 10

adicionado 5 minutos depois

Passei esse código referente a gerar números aleatórios sem repetição como uma maneira de resolver o problema de repetir a mesma pergunta. Não posso garantir q seja a melhor forma de fazer esse exercício

adicionado 28 minutos depois

@Leandro Arnold  Olá. Procure pensar dessa forma: O código que passei e q gera um vetor com 10 (ou qualquer outro tamanho) números aleatórios e sem repetição é executado apenas "uma" vez.

Com isso, você vai ter um vetor com dez números aleatórios e sem repetição armazenados nele. Feito isso, para a 1ª pergunta você passa o valor q está no índice 0 do vetor, para a 2ª pergunta você passa o valor que está  no índice 1 do vetor, e assim por diante

Para essa lógica funcionar de acordo com o esperado, o sorteio desse números que serão armazenados em um vetor deve ocorrer só uma vez. Se toda vez q tiver q selecionar uma nova pergunta você fizer um novo sorteio e criar outra sequência de números aleatórios, aí é bem provável que apareçam valores repetidos

Não sei dizer se deu para "pegar" a linha d raciocínio q estou querendo passar. Mas se deu ok!

  • Curtir 1

Compartilhar este post


Link para o post
Compartilhar em outros sites

Entendi seu raciocínio @giu_d mas não consegui implementar no código.

 

""Feito isso, para a 1ª pergunta você passa o valor q está no índice 0 do vetor, para a 2ª pergunta você passa o valor que está  no índice 1 do vetor, e assim por diante"

 

Como eu poderia implementar isso nele? Seria com ordenação de vetores?

Compartilhar este post


Link para o post
Compartilhar em outros sites

@Leandro Arnold  Olá. A solução q encontrei para essa questão é fazendo uso de uma estrutura de dados (FILA), inserindo os números na fila e selecionado o numero de índice 0 da fila e logo removendo esse elemento.

Dá uma olhada no código para ver se está de acordo como o esperado:

 

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

int pergunta;
char resposta;
char arquivopergunta[20];
char arquivoresposta[10];
int *fila;
int qtdeDeElementos = 0;

void inserirNaFila(int elemento) {

    qtdeDeElementos++;

    int *novaFila = malloc(qtdeDeElementos * sizeof(int));

    int i;

    if (qtdeDeElementos > 1) {
        for (i = 0; i < qtdeDeElementos - 1; i++) {
            novaFila[i] = fila[i];
        }
    }
    novaFila[qtdeDeElementos - 1] = elemento;
    free(fila);
    fila = novaFila;
}

int removerDaFila() {

    qtdeDeElementos--;

    int *novaFila = malloc(qtdeDeElementos * sizeof(int));

    int i;

    if (qtdeDeElementos >= 1) {
        for (i = 1; i < qtdeDeElementos + 1; i++) {
            novaFila[i - 1] = fila[i];
        }
    }
    int elementoRemovido = fila[0];
    free(fila);
    fila = novaFila;

    return elementoRemovido;
}

void gerarNumeros() {

    int i, n, *vet = NULL, temp;

    srand(time(NULL));

    vet = malloc(10 * sizeof(int));

    for (i = 0; i < 10; i++) {
        vet[i] = (i + 1);
    }

    for (i = 10 - 1; i > 0; i--) {
        n = rand() % (i + 1);
        temp = vet[i];
        vet[i] = vet[n];
        vet[n] = temp;
    }

    for (i = 0; i < 10; i++) {
        inserirNaFila(vet[i]);
    }
}

void concatenapergunta(){
	char arquivo[]="pergunta";
	char n[2];
	char extans[]=".qiz";

	pergunta = fila[0]; // o número do índice 0 da fila foi selecionado e depois será removido, dando lugar ao próximo nº q tá na fila

	printf("Pergunta selecionada: %d\n\n", pergunta);

	sprintf(n,"%d",pergunta);
	strcat(arquivo,n);
	strcat(arquivo,extans);

	strcpy(arquivopergunta,arquivo);

	int elemento = removerDaFila(); // remove o número da fila

	printf("Elemento removido: %d\n\n", elemento);
}

void concatenaresposta(){
	char arquivo[]="resposta";
	char n[2];
	char extans[]=".qiz";
	sprintf(n,"%d",pergunta);
	strcat(arquivo,n);
	strcat(arquivo,extans);

	strcpy(arquivoresposta,arquivo);
}

void lepergunta(){//arquivo para a pergunta
	concatenapergunta();
	concatenaresposta();

 	FILE *f;//ponteiro
 	f=fopen (arquivopergunta,"r");//função para abrir o arquivo, tipo do arquivo e visibilidade
 	char c;
	//printf("entrou, %s", arquivopergunta);
 	while(1){
 		c=fgetc(f);//armazenar cada caractere que tiver no arquivo
 		if(c==EOF){//final do arquivo
 			break;

 		}
 		printf("%c",c);

 	}
 	printf("\n");
 	fclose(f);
 }

void responde(){//função para responder
	FILE *F;
	char c;
	printf("\nInforme sua resposta: ");
	scanf("%c",&resposta);
	fflush(stdin);
}

void checar(){//função para checar se a resposta está correta e contem o arquvio da redposta
	FILE *f;
	char c;f=fopen(arquivoresposta,"r");
	c=fgetc(f);
	if(c==resposta){
		printf("\n\nParabens voce acertou!");
	}
	else{
		printf("\n\nVoce errou");
	}
	printf("\n\n");
}
 int main(){

     int i, nperguntas;

     gerarNumeros();

     printf("\nInforme quantas perguntas voce quer responder: ");
     scanf("%d",&nperguntas);
     fflush(stdin);

     for(i=0;i<nperguntas;i++){
 	  //lepergunta();//arquivo da pergunta
 	  //responde();
 	  //checar();// arquivo da resposta
 	  concatenapergunta();

    }
 	return 0;
}

O código  ficou um pouco grande, mas foi a forma q achei melhor para resolver esse exercício, já q ninguém mais se manifestou

Espero q ajude.

adicionado 25 minutos depois

OBS: Esqueci de liberar a memória alocada para os elementos do vetor. Então, no final da função gerarNumeros(); seria preciso colocar esses comandos:

 

free(vet);

vet = NULL;

Também seria mais adequado remover o número da fila ao final da função concatenaresposta();. Mas o importante é não esquecer de remover o número da fila. Se der certo avisa. Não tenho como testar de maneira adequada aqui pois não tenho acesso aos arquivos

  • Curtir 1

Compartilhar este post


Link para o post
Compartilhar em outros sites
Postado (editado)

Fiz uma solução mais simples:

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

#define QTDE 10

void flush_stdin() {
    int c;
    while((c=getchar()) != '\n' && c != EOF);
}

void embaralhaperguntas(int perguntas[]) {
    int i, n, temp;

    for (i = 0; i < QTDE; i++)
    {
        perguntas[i] = i + 1;
    }

    //Embaralha os números no vetor (algoritmo Knuth Fisher-Yates)
    for (i = QTDE-1; i > 0; i--)
    {
        n = rand() % (i + 1);
        temp = perguntas[i];
        perguntas[i] = perguntas[n];
        perguntas[n] = temp;
    }
}

void lepergunta(int pergunta) {
    char arquivopergunta[20], c;
    FILE *f;

    sprintf(arquivopergunta, "pergunta%d.qiz", pergunta);

    f = fopen(arquivopergunta, "r");

    while ((c=fgetc(f)) != EOF)
        printf("%c", c);

    fclose(f);
}

void checar(int pergunta, char resposta) {
    char arquivoresposta[20], c;
    FILE *f;

    sprintf(arquivoresposta, "resposta%d.qiz", pergunta);

    f = fopen(arquivoresposta, "r");

    c=fgetc(f);

    if(toupper(c) == toupper(resposta)) {
        printf("\nParabens voce acertou!\n\n");
    }
    else {
        printf("\nVoce errou\n\n");
    }

    fclose(f);
}

int main()
{
    srand(time(NULL));
    int nperguntas, perguntas[QTDE], i;
    char resposta;

    printf("\nInforme quantas perguntas voce quer responder? ");
    scanf("%d",&nperguntas);
    flush_stdin();

    embaralhaperguntas(perguntas);

    for(i = 0; i < nperguntas; i++) {
        lepergunta(perguntas[i]);

        printf("\n\nInforme sua resposta: ");
        scanf("%c",&resposta);
        flush_stdin();

        checar(perguntas[i], resposta);
    }

    return 0;
}

Com QTDE igual a 10 tem que existir 10 arquivos de perguntas e respostas senão pode dar erro se sortear o número de um arquivo que não existe.

Editado por isrnick
  • Curtir 1

Compartilhar este post


Link para o post
Compartilhar em outros sites

@isrnick  É. Só agora, né? :(

adicionado 2 minutos depois

Seu código ficou bastante simplificado se comparado com o meu.

A questão agora é ver se o autor do tópico aprova as soluções apresentadas hehe

  • Curtir 1

Compartilhar este post


Link para o post
Compartilhar em outros sites

@giu_d :lol: Foi quando deu pra fazer, também tenho que trabalhar... :P

  • Curtir 2

Compartilhar este post


Link para o post
Compartilhar em outros sites

Obs: Mas indiferente do autor do tópico aprovar ou não as soluções apresentadas a questão é q apresentei um solução por querer mesmo aprender a trabalhar em projetos diferentes, e não para satisfazer a expectativa do autor do tópico

adicionado 2 minutos depois

@isrnick Tá vendo q também tô fazendo uso do algoritmo Knuth Fisher-Yates? Aprendi sobre esse algoritmo aqui 

  • Curtir 1
  • Amei 1

Compartilhar este post


Link para o post
Compartilhar em outros sites

@giu_d Sim, bom ver que o algoritmo que postei tá servindo de aprendizado pra as pessoas. :thumbsup:

  • Curtir 2

Compartilhar este post


Link para o post
Compartilhar em outros sites

@isrnick Só que veio uma pergunta agora. Para um exercício como esse não seria mais interessante colocar n perguntas em um mesmo arquivo, carregar essas perguntas do arquivo via código e ir selecionando as perguntas de forma aleatória ao invés de criar 10 arquivos para perguntas e mais 10 para respostas?

Fica até essa sugestão para o autor do tópico  

  • Curtir 1

Compartilhar este post


Link para o post
Compartilhar em outros sites
41 minutos atrás, giu_d disse:

carregar essas perguntas do arquivo via código e ir selecionando as perguntas de forma aleatória

Não é a forma mais "elegante".
 

 

42 minutos atrás, giu_d disse:

ao invés de criar 10 arquivos para perguntas e mais 10 para respostas?

Isso sim que é muito pior >_<

  • Curtir 1

Compartilhar este post


Link para o post
Compartilhar em outros sites

Mas eu entendi porque ele fez assim... Desta maneira ele pode colocar a pergunta e as alternativas no arquivo, e não importa o tamanho do texto no arquivo que vai funcionar e imprimir tudo na tela, dá até pra formatar o modo que o texto ficará facilmente, e fazer alterações é bem fácil.

 

Mas podia colocar a resposta gabarito e pergunta no mesmo arquivo pelo menos, fazendo a primeira letra do arquivo ser o gabarito, e o resto do arquivo é o texto da pergunta.

  • Curtir 2

Compartilhar este post


Link para o post
Compartilhar em outros sites

Crie uma conta ou entre para comentar

Você precisar ser um membro para fazer um comentário






Sobre o Clube do Hardware

No ar desde 1996, o Clube do Hardware é uma das maiores, mais antigas e mais respeitadas publicações 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

×