0

Buenas gente alguien sabe como solucionar este problema que tengo, el programa funciona bien en términos generales pero la función "verificar_Repetidos"(no sé si el problema es esa función en concreto),pero no me funciona(quizás estoy mandando mal los parámetros, no tengo ni idea que mandar), me sigue mostrando varios números repetidos, cosa que no tendría que pasar.

¿Alguien tiene una solución para que no me muestre números repetidos?

cuando no estoy usando estructuras todo funciona bien pero ahora cuando agregué estructuras no tengo ni idea porque no funciona

#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#define RENGLONES 3
#define COLUMNA 5

struct Carton{
    
    
    int carton[RENGLONES][COLUMNA];
    
};
struct Jugador {
  
    int cantidadCartones;

    struct Carton cartonJugador[3];
};


void cargarMatriz(int m[RENGLONES][COLUMNA]);
void mostrarMatriz(int m[RENGLONES][COLUMNA]);
void limpiarMatriz (int matriz[RENGLONES][COLUMNA]);
int verificar_Repetidos(int m[RENGLONES][COLUMNA],int numeroBuscar);

int main(){
srand(time(0));
int tam = 3;
    struct  Jugador datosJugador;
    
    for(int i =0;i<tam;i++){
    limpiarMatriz(datosJugador.cartonJugador[i].carton);
    cargarMatriz(datosJugador.cartonJugador[i].carton);
    }
    for(int i =0;i<tam;i++){
    mostrarMatriz(datosJugador.cartonJugador[i].carton);
    }
    
    

}

void limpiarMatriz (int matriz[RENGLONES][COLUMNA]) {
    for (int i = 0; i < RENGLONES; i++) {
        for (int j = 0; j < COLUMNA; j++) {
            matriz[i][j] =0; 
        }
    }
}

void cargarMatriz(int m[RENGLONES][COLUMNA]){
    
    int numero,comprobar;
        for (int r = 0; r < RENGLONES; r++){
            for (int c=0; c < COLUMNA; c++){
                do{
                numero = 1 + rand() % 15;
                comprobar = verificar_Repetidos(m,numero);
                
               }while(comprobar != -1);
               m[c][r] = numero;
            }
        }
}
void mostrarMatriz(int m[RENGLONES][COLUMNA]){

    for(int r=0;r<RENGLONES;r++){
        for(int c=0;c<COLUMNA;c++){
            printf("[%d]",m[c][r]);
        }
        printf("\n");
    }
    printf("\n");
}
int verificar_Repetidos(int m[RENGLONES][COLUMNA],int numeroBuscar){
    int pos = -1;
    
    for (int r=0;r<RENGLONES;r++){
        for (int c=0;c<COLUMNA;c++){
            if (m[c][r] == numeroBuscar){
                pos = 1;
            }
        }
    }
    return pos;
    
}

2 Answers2

3

Si te fijas, estás intercambiando los índices a la hora de acceder a la matriz:

struct Carton{
    int carton[RENGLONES][COLUMNA];
};

void cargarMatriz(int m[RENGLONES][COLUMNA]){
    for (int r = 0; r < RENGLONES; r++){
        for (int c=0; c < COLUMNA; c++){
            m[c][r] = numero; // <<--- AQUI
        }
    }
}

Dado que la matriz no es cuadrada, en algún momento empezarás a escribir fuera de los límites de la matriz actual, machacando valores de otras matrices (algunos de los cuales pueden estar ya validados)

Además, nota que el copypaste es mal aliado a la hora de programar:

for(int r=0;r<RENGLONES;r++){
    for(int c=0;c<COLUMNA;c++){
        printf("[%d]",m[c][r]); // <<--- MAL

for (int r=0;r<RENGLONES;r++){
    for (int c=0;c<COLUMNA;c++){
        if (m[c][r] == numeroBuscar){ // <<--- MAL

Como pequeña optimización, fíjate que a la hora de saber si el número ya existe en el cartón, basta con localizar la primera coincidencia. Es decir, una vez que sabes que el número ya está repetido es totalmente innecesario seguir comprobando el resto del cartón.

Como haces uso de un bucle anidado hay que buscar una alternativa a break, ya que break solo te permite salir de uno de los dos bucles.

int verificar_Repetidos(int m[RENGLONES][COLUMNA],int numeroBuscar){
    int pos = -1;
    
    for (int r=0;r<RENGLONES && pos == -1;r++){   // <<--- Modificamos la condición
        for (int c=0;c<COLUMNA && pos == -1;c++){ // <<--- Modificamos la condición
            if (m[r][c] == numeroBuscar){
                pos = 1;
            }
        }
    }
    return pos;
}
eferion
  • 49,291
  • 5
  • 30
  • 72
3

Tu código conceptualmente está bien, pero es tremendamente ineficiente e innecesariamente complicado.

A parte del problema de índices que menciona eferion y la cantidad de proceso erróneo buscando repetidos que también menciona, tu algoritmo para generar números en tu matriz es potencialmente infinito:

void cargarMatriz(int m[RENGLONES][COLUMNA]){

    int numero,comprobar;

    for (int r = 0; r < RENGLONES; r++){
        for (int c=0; c < COLUMNA; c++){
            do{
                numero = 1 + rand() % 15;
                comprobar = verificar_Repetidos(m,numero);
            }while(comprobar != -1);

            m[c][r] = numero;
        }
    }
}

Vamos a suponer por un momento que 1 + rand() % 15 en lugar de una secuencia aleatoria devolviese una secuencia ascendente (1, 2, 3, 4, 5, 6...) en cada nueva vuelta del bucle do-while.

  1. Generamos 1. No está en la matriz. Se guarda y vuelve a empezar.
  2. Generamos 1. Está en la matriz. Generamos 2. No está en la matriz. Se guarda y vuelve a empezar.
  3. Generamos 1. Está en la matriz. Generamos 2. Está en la matriz. Generamos 3. No está en la matriz. Se guarda y vuelve a empezar.
  4. ...
  5. ...

Como puedes ver, cuantos más números hay generados, más se trabaja. En el caso del número 15 habrías generado catorce números antes de dar con el que falta. La cantidad de generaciones de números que harías para rellenar toda la matriz es 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + 15 = 120.

Eso en el caso de la secuencia ascendente, si es puramente aleatorio existe la posibilidad de que el algoritmo sea infinito.


Mi consejo es que generes los números sin repeticiones y después desordenes la matriz:

#define RENGLONES 3
#define COLUMNAS 5

void swap(int *a, int *b) {
    int temporal = *a;
    *a = *b;
    *b = temporal;
}

void limpiarMatriz(int m[RENGLONES][COLUMNAS]) {
    int total = RENGLONES * COLUMNAS;

    for (int indice = 0; indice != total; ++indice) {
        m[indice / COLUMNAS][indice % COLUMNAS] = indice + 1;
    }
}

void cargarMatriz(int m[RENGLONES][COLUMNAS]) {
    int total = RENGLONES * COLUMNAS;

    for (int indice = 0; indice != total; ++indice) {
        int numero = rand() % 15;
        swap(&m[indice / COLUMNAS][indice % COLUMNAS], &m[numero / COLUMNAS][numero % COLUMNAS]);
    }
}

Observa los siguientes cambios en el código:

  • Consistencia de nombres. No tenía sentido que RENGLONES fuese plural y COLUMNA singular.
  • Un solo bucle. En lugar de dos for anidados, recorremos la matriz con un único bucle.

En total, este código es más eficiente, más sencillo y más fácil de entender. Además te ahorras una función (verificar_Repetidos) con lo que el código es más corto y más fácil de mantener. Puedes verlo funcionando en Try it online!.

Para acabar me gustaría añadir:

PaperBirdMaster
  • 44,474
  • 6
  • 44
  • 82