×
Ir ao conteúdo
  • Cadastre-se

C Gerar valores aleatórios sem repetição em uma matriz


Posts recomendados

Preciso fazer uma matriz que gere valores aleatórios e esses valores não podem se repetir, indo de 0 a 8. Estou a manhã toda tentando fazer isso e simplesmente não consigo, se alguém puder ajudar eu agradeceria muito. Achei essa aula e tentei aplicar ela ao meu código, mas não consegui: https://www.youtube.com/watch?v=7C2PLt_M2ig

#include <stdio.h>
#include <stdlib.h>
#include <locale.h>
#include<stdio.h>
#include<string.h>
#include<unistd.h>
#include<sys/types.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <time.h>


#define ACIMA 72
#define ABAIXO 80
#define DIREITA 77
#define ESQUERDA 75

int col = 3, col2 = 4, col3 = 5;
int colunas, i = 0, j = 0;
int m, n, p, q, z, cont, igual, v, ok = 1;
int cont;
char teclas;

char tabuleiro[3][3];

char final1 = {{'1','2','3'},{'4','5','6'},{'7','8',' '}};
char final2 = {{'1','2','3','4'},{'5','6','7','8'},{'9','10','11','12'},{'13','14','15',' '}};
char final3 = {{'1','2','3','4','5'},{'6','7','8','9','10'},{'11','12','13','14','15'},{'16','17','18','19','20'},{'21','22','23','24',' '}};




int main()
{
    printf("Entre com o número de colunas e linhas");
    scanf("%d", &colunas);

    if(colunas == col)
    {

        srand(time(NULL));
        int ale = 9;
        do
        {
            ok = 1;
            tabuleiro[i][j] = rand()%ale;
            for (m = 0; m < i; m++)
            {
                for (n = 0; n < j; n++)
                {
                    if(tabuleiro[i][j] == tabuleiro[m][n])
                        ok = 0;
                }
            }
            if(ok == 1)
                j++;
            if(j == 3)
            {
                j = 0;
                i++;
            }

        }
        while(i < col && j < col);


        for (i = 0; i < col; i++)
        {
            for (j = 0; j < col; j++)
            {
                printf("|%d|", tabuleiro[i][j]);
            }
            printf("\n");
        }

    }

    return 0;
}

 

  • Curtir 1
Link para o comentário
Compartilhar em outros sites

ve se isso lhe dá uma ideia:
 

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include <sys/time.h>
#include <sys/stat.h>


int exemploRemover()
{
	printf("Remover valor 5 \n");
	int array[9] = {0,1,2,3,4,5,6,7,8};
	int tm = sizeof(array)/sizeof(array[0]);
	int escolhido = 5;
	for(int i=0;i<tm;i++)
	{
		if(array[i] == escolhido)
		{
			for(int j=i; j<tm-1; j++)
			{
				array[j] = array[j+1];
			}
			array[tm-1]=-1;
			tm--;
			break;
		}
	}
	printf("Os que sobraram foram:\n");
	int i=0;
	while(array[i]!=-1)
	{
		printf("%i\n", array[i]);
		i++;
	}
	return 1;
}

int exemplo2()
{
	int array[9] = {0,1,2,3,4,5,6,7,8};
	int tm = sizeof(array)/sizeof(array[0]);

 	// sem isso aqui, o programa vai 
	// iniciar escolhendo sempre a mesma sequencia.
	// comente e descomente para ver o que acontece.
	// gerador de aleatoriedade ou simplesmente semente:
	srand ( time(NULL) );
				

	while(tm>1)
	{
		int escolhido = rand()%(tm);
		printf("Remover valor %i \n", array[escolhido]);

		for(int i=0; i<tm; i++)
		{
			if(array[i] == array[escolhido])
			{
				for(int j=i; j<tm-1; j++)
				{
					array[j] = array[j+1];
				}
				array[tm-1]=-1;
				tm--;
				break;
			}
		}
	}
	return 1;
}

int main()
{
	exemplo2();

	return 0;
} 



Existem formas melhores de trabalhar com arrays.
Para criar funções como inserção edição e deleção, o melhor seria criar uma struct que contivesse até o tamanho do seu array.
Isso é só um exemplo simples de como poderia resolver seu problema.

  • Curtir 2
Link para o comentário
Compartilhar em outros sites

3 horas atrás, GabrielPinheiroamd disse:

Preciso fazer uma matriz que gere valores aleatórios e esses valores não podem se repetir, indo de 0 a 8. Estou a manhã toda tentando fazer isso e simplesmente não consigo, se alguém puder ajudar eu agradeceria muito

 

Não consegui entender ao certo o que tem na matriz e o que precisa fazer. Talvez pudesse postar mais detalhes ou um enunciado.

 

Sobre como fazer: 

 

Pense no sorteio do bingo na igreja: as bolinhas são iguais, mesmo peso e tudo exceto pelos números. E tem uma canaleta onde ficam as bolinhas sorteadas.

Transporte isso para o programa em C 

  • onde você tem um vetor com um int ou um char para cada bolinha. 
  • numere as bolinhas como no bingo
  • sorteia uma bolinha e põe na canaleta
  • troca a bolinha sorteada pela última do vetor
  • continua sorteando bolinhas mas diminui o tamanho do vetor

É só isso: na igreja não tem o lance de colocar no fim :) porque a bolinha fica fora do globo na canaleta. 

 

No seu programa a canaleta seria um vetor de saida.

 

Isso é o que uma criança faria com um maço de cartas. Nem era pra chamar de algoritmo, mas na literatura é chamado de algoritmo de fisher-yates, e me surpreende que alguém tenha tido  a coragem de pleitear ou aceitar seu nome em algo tão ingênuo. Podia ser o algoritmo do Padre José na quermesse em 1940. 

 

Um exemplo em C

 

Esse é um troço que sempre aparece aqui e eu tenho um registro de ter postado algo sobre isso em abril-julho desse ano, mas não acho o link. De todo modo era para um sorteio como o da loteria e o código completo pode ser visto aqui ou baixado aqui clicando no botão verde e marcando download ZIP ou abrindo direto no visual studio se usa isso.

 

O resumo do "sorteio"

 

// retorna um vetor de 'N' valores inteiros 
// entre 'menor' e 'maior' em ordem aleatoria. 
// Ex (10,0,100) retorna 10 valores entre 0 e 100
// inclusive. (12,0,11) retorna o vetor com todos
//  os 12 numeros em ordem aleatoria.
int*        sorteados(unsigned N, int menor, int maior)
{
    unsigned cjto = maior - menor + 1;
    if (cjto < 2) return NULL; // tem que ter um par ao menos
    if (N == 0) return NULL; // bobagem, mas...
    if (N > cjto) N = cjto; // por sanidade :) 
    int* v = (int*)malloc(cjto * sizeof(int)); // cria o vetor
    if (v == NULL) return NULL; // deu pau
    // numera as bolinhas
    for (unsigned i = 0, valor = menor;
         i < cjto; i += 1) *(v + i) = valor++;
    // as "bolinhas" estão em ordem: faz os sorteios
    for (unsigned i = 1; i < cjto; i += 1)
    {
        int outra = i + rand() % (cjto - i); // uma das outras
        int temp = *(v + i - 1); // a primeira bolinha
        *(v + i - 1) = *(v + outra); // troca pela outra
        *(v + outra) = temp;
    };  // for()
    return v;
};

 

E vai ver que a ideia é simples. Trata-se de um sorteio como os da CEF que pode ver no Youtube.

 

Siga os comentários e se não entender pergunte.

 

Um programa de teste:

 

int main(void)
{
    srand(210920);
    int* v = sorteados(9, 0, 8);
    mostra(9, v, "9 valores entre 0 e 8");
    free(v);
    return 0; // nada mais
}

 

Mostra

 

9 valores entre 0 e 8
O vetor [9]: 7, 5, 6, 4, 8, 3, 1, 2, 0

 

Acho que isso foi publicado na primeira semana de julho desse ano e pode ver no meu conteúdo dessa época consultando meu perfil aqui no forum. Deve ter mais detalhes e explicações lá.

 

 

 

Link para o comentário
Compartilhar em outros sites

Segue um exemplo de um sorteio:

 

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

int *sorteia_seed(int min, int max, unsigned int seed)
{
    assert(min < max);

    int len = max - min + 1;
    int *result = calloc(len, sizeof(int));

    for (int i = 0, val = min; i < len; i++, val++)
        result[i] = val;

    srand(seed);
    for (int i = 0; i < len; i++)
    {
        int random_index = rand() % len;

        int tmp = result[i];
        result[i] = result[random_index];
        result[random_index] = tmp;
    }
    
    return result;
}

int *sorteia(int min, int max)
{
    return sorteia_seed(min, max, time(NULL));
}

int main()
{
    int *numeros = sorteia(1, 60);

    for (int i = 0; i < 6; i++)
        printf("%d, ", numeros[i]);

    printf("\n");   

    free(numeros); 
    
    return 0;
}

 

  • Curtir 1
Link para o comentário
Compartilhar em outros sites

int *sorteia_seed(int min, int max, unsigned int seed)
{
    assert(min < max);

    int len = max - min + 1;
    int *result = calloc(len, sizeof(int));

    for (int i = 0, val = min; i < len; i++, val++)
        result[i] = val;

 

@Matheus Maldi não há razão para usar calloc() para alocar um vetor que vai ser totalmente preenchido na linha seguinte do programa. Prefira sempre malloc() que não zera o espaço alocado.

 

E o uso de assert() num forum para iniciantes pode ser um pouco de exagero ;) Convém explicar que assert() é uma garantia e só roda em debug mode e muitos usuários sequer atentam para a existência disso. Ao menos explique porque está usando isso. Ou faça o simples e use um if e retorne NULL quando o intervalo for inválido ao invés de simplesmente cancelar o programa com uma mensagem estranha, que é o que assert() vai fazer se a condição não for satisfeita.

 

E se o código for compilado do modo normal sua função não vai testar o intervalo...

E nesse caso isso possivelmente seria mais importante, já que a função estará em uso afinal, e não mais em teste.  assert() se destina a garantir condições de teste durante o desenvolvimento e não substitui ter um mínimo de cuidado na versão definitiva, ao menos em garantir a consistência dos argumentos...

  • Curtir 1
Link para o comentário
Compartilhar em outros sites

Muito elegante a solução do AlfNeto:

 


int exemplo3()
{
	int arrayFonte[9] = {0,1,2,3,4,5,6,7,8};
	int tm = sizeof(array)/sizeof(array[0]);
	for (int i=0; i<tm; i++)
	{
		int outra = i + rand() % (tm - i);
		int temp = arrayFonte[i];
		arrayFonte[i] = arrayFonte[outra];
		arrayFonte[outra] = temp;
		printf("Escolhido %i \n", arrayFonte[i]);
	}
}

int main()
{
	exemplo3();
	return 0;
} 

 

Link para o comentário
Compartilhar em outros sites

51 minutos atrás, arfneto disse:
int *sorteia_seed(int min, int max, unsigned int seed)
{
    assert(min < max);

    int len = max - min + 1;
    int *result = calloc(len, sizeof(int));

    for (int i = 0, val = min; i < len; i++, val++)
        result[i] = val;

 

@Matheus Maldi não há razão para usar calloc() para alocar um vetor que vai ser totalmente preenchido na linha seguinte do programa. Prefira sempre malloc() que não zera o espaço alocado.

 

E o uso de assert() num forum para iniciantes pode ser um pouco de exagero ;) Convém explicar que assert() é uma garantia e só roda em debug mode e muitos usuários sequer atentam para a existência disso. Ao menos explique porque está usando isso. Ou faça o simples e use um if e retorne NULL quando o intervalo for inválido ao invés de simplesmente cancelar o programa com uma mensagem estranha, que é o que assert() vai fazer se a condição não for satisfeita.

 

E se o código for compilado do modo normal sua função não vai testar o intervalo...

E nesse caso isso possivelmente seria mais importante, já que a função estará em uso afinal, e não mais em teste.  assert() se destina a garantir condições de teste durante o desenvolvimento e não substitui ter um mínimo de cuidado na versão definitiva, ao menos em garantir a consistência dos argumentos...

 

Referente ao malloc e calloc eu SEMPRE uso o calloc, vou contar um motivo, uma vez estava escrevendo um PERFT, e para escrever um desses é normal escrever muitos testes, assim é fácil detectar quando uma alteração código quebrar, depois de uma certa complexidade do código acontecia algo estranho, se eu mandasse executar o código 10 vezes em 9 passava e 1 quebrava, o mesmo binário. Foi mais de um dia procurando e o problema era no malloc, pelo motivo de eu esquecer de iniciar todos os campos. Não vale a pena nenhum ganho de performance que talvez exista na chamada das funções.

 

Referente aos asserts, como você mesmo disse, não estamos desenvolvendo nada definitivo, apenas um exemplo de código para se ler em 2 minutos.

 

 

Link para o comentário
Compartilhar em outros sites

25 minutos atrás, Matheus Maldi disse:

Não vale a pena nenhum ganho de performance que talvez exista na chamada das funções

 

Entendo. Mas o problema não é um atraso na chamada da função. calloc() é uma chamada convencional a malloc() seguida de um memset() para zerar toda a área alocada. Se todos os bytes vão ser redefinidos na linha de baixo não há razão para usar isso.

 

Sempre alguém tem que pagar a conta. 

 

31 minutos atrás, Matheus Maldi disse:

Referente aos asserts, como você mesmo disse, não estamos desenvolvendo nada definitivo, apenas um exemplo de código para se ler em 2 minutos

 

Por isso mesmo escrevi sobre o assert(). Você não explicou o que é ou para que serve, e ao mesmo tempo não testou os intervalos. E se era para testar em algum momento, num código "para se ler em dois minutos" e postado num forum para iniciantes, seria mais razoável:

  • não testar nada, por essa mesma razão.
  • testar usando um if se o fim é de fato maior que o inicio do intervalo e retornar NULL

Só uma opinião.

 

34 minutos atrás, Matheus Maldi disse:

Foi mais de um dia procurando e o problema era no malloc, pelo motivo de eu esquecer de iniciar todos os campos

 

Isso é curioso. calloc() é imple,entado usando malloc() e memset() em geral, e não há como falhar malloc() e calloc() não falhar. Em que plataforma viu isso acontecer? Chegaram a isolar o erro? Enviou ao fabricante?

 

Link para o comentário
Compartilhar em outros sites

33 minutos atrás, arfneto disse:

 

Entendo. Mas o problema não é um atraso na chamada da função. calloc() é uma chamada convencional a malloc() seguida de um memset() para zerar toda a área alocada. Se todos os bytes vão ser redefinidos na linha de baixo não há razão para usar isso.

 

Sempre alguém tem que pagar a conta. 

 

 

Por isso mesmo escrevi sobre o assert(). Você não explicou o que é ou para que serve, e ao mesmo tempo não testou os intervalos. E se era para testar em algum momento, num código "para se ler em dois minutos" e postado num forum para iniciantes, seria mais razoável:

  • não testar nada, por essa mesma razão.
  • testar usando um if se o fim é de fato maior que o inicio do intervalo e retornar NULL

Só uma opinião.

 

 

Isso é curioso. calloc() é imple,entado usando malloc() e memset() em geral, e não há como falhar malloc() e calloc() não falhar. Em que plataforma viu isso acontecer? Chegaram a isolar o erro? Enviou ao fabricante?

 


O problema eh que usei malloc sem iniciar todos os campos, na maioria das vezes o malloc entrega a memória já zerada principalmente quando alocamos pouco espaço, mas as vezes nem com lixo.

Link para o comentário
Compartilhar em outros sites

48 minutos atrás, Matheus Maldi disse:

O problema eh que usei malloc sem iniciar todos os campos, na maioria das vezes o malloc entrega a memória já zerada principalmente quando alocamos pouco espaço, mas as vezes nem com lixo

 

Entendi. Foi o que pensei. Isso está fora do tópico aqui, mas calloc() é implementada via malloc() e memset() então fiquei imaginando onde seria diferente. Note que malloc() muitas vezes gerencia um pool de áreas alocadas e liberadas durante a execução do processo e essas não são inicializadas, mas as áreas recebidas direto do sistema são em geral garantias zeradas por questões de segurança de dados.

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

Curso de Hacker Ético

LANÇAMENTO!

CLIQUE AQUI E CONFIRA!

* Este curso não é ministrado pela equipe do Clube do Hardware.