Ir ao conteúdo
  • Cadastre-se

C Problema no sorteio das perguntas


Posts recomendados

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;
}



 

 

Link para o comentário
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

Link para o comentário
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.

Link para o comentário
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!

Link para o comentário
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?

Link para o comentário
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

Link para o comentário
Compartilhar em outros sites

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.

Link para o comentário
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 

Link para o comentário
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  

Link para o comentário
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 >_<

Link para o comentário
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 1
Link para o comentário
Compartilhar em outros sites

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...

 

GRÁTIS: ebook Redes Wi-Fi – 2ª Edição

EBOOK GRÁTIS!

CLIQUE AQUI E BAIXE AGORA MESMO!