[C] Rombo con asteriscos

Iniciado por dmacias, 1 Marzo 2014, 20:14 PM

0 Miembros y 2 Visitantes están viendo este tema.

leosansan

#10
Cita de: yoel_alejandro en  6 Marzo 2014, 16:37 PM
Bueno ..... creo que ya hemos dado una tremenda cantidad de opciones al autor del post sobre cómo resolver su problema.

Lástima que él no haya seguido escribiendo, y al final terminamos agarrándonos el tema para nosotros, jeje  :laugh:



Me quedó un mal regusto al tener que usar un array en la última versión, así que ahí va una sin un array de caracteres:

Código (cpp) [Seleccionar]

#include <stdio.h>

int main(){
 int i=0, j, a;
 do{
   printf("\nBase del rombo(numero impar positivo): \n");
   scanf("%d", &a);
   }while ( a <=0 || (a % 2) == 0);
   for ( i=2*(a/2);i>=0;i-=2){
     printf("%*c",i/2+a/2,'*');
     for ( j=0;j<=2*(a/2)-1-i;j++)
       putchar('*');
     putchar ('\n');
   }
   for ( i=1;i<2*(a/2);i+=2){
     printf("%*c",i/2+a/2+1,'*');
     for ( j=0;j<=2*(a/2)-2-i;j++)
       putchar('*');
     putchar ('\n');
   }
   return 0;
}


¡¡¡¡ Saluditos! ..... !!!!





do-while

¡Buenas!

Como aun no había ninguna solución recursiva, aquí os dejo una  ;D

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

/* n == numero total de filas del rombo (no puede ser par) y el segundo parametro siempre es cero:
   ejemplos: rombo(3,0);
             rombo(11,0);
*/
void rombo(int n,int paso)
{
    char *str = malloc(n / 2 + paso + 4);

    if(!(n & 1))
        return;

    memset(str,' ',n / 2 - paso + 1);
    memset(str + n / 2 - paso + 1 , '*' , 2 * paso + 1);
    memcpy(str + n / 2 + paso + 2 ,"\n\0",2);

    printf("%s",str);

    if(paso == n / 2)
    {
        free(str);
        return;
    }

    rombo(n,paso+1);

    printf("%s",str);

    free(str);
}

int main(int argc, char *argv[])
{
    rombo(5,0);
    rombo(4,0);
    return 0;
}
- Doctor, confundo los números y los colores.
- Vaya marrón.
- ¿Marrón? ¡Por el culo te la hinco!

rir3760

Otra solución recursiva pero forzada (ya que parte de la información se codifica en la cadena a imprimir) es:
#include <stdio.h>
#include <stdlib.h>

void f(char *ch);

int main(void)
{
   char ch[] = "    *\0*******";
   
   f(ch);
   
   return EXIT_SUCCESS;
}

void f(char *ch)
{
   int i = printf("%s\n", ch) - 1;
   
   if (*ch == ' '){
      ch[i] = '*';
      ch[i + 2] = '\0';
      f(ch + 1);
     
      printf("%.*s\n", i, ch);
   }
}


Un saludo
C retains the basic philosophy that programmers know what they are doing; it only requires that they state their intentions explicitly.
--
Kernighan & Ritchie, The C programming language

eferion

Venga va, yo también aporto un código con recursividad.


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

void paso( int max_filas, int fila, int col );

int main()
{
 paso( 11, 0, 0 );
 return EXIT_SUCCESS;
}

void paso( int max_filas, int fila, int col )
{
 const char* chars = " *";
 if( fila < max_filas )
 {
   int num_sp = abs( max_filas/2 - fila);
   int end = max_filas - num_sp;
   if ( col == end )
   {
     printf( "\n" );
     col = -1;
     fila++;
   }
   else
     printf( "%c", chars[ col >= num_sp ] );

   paso( max_filas, fila, ++col );
 }
}

leosansan

#14
Sin arrays, sólo printf y un par de for menos que antes:

Código (cpp) [Seleccionar]

#include <stdio.h>

int main(){
 int i=0,j,k,a;
 do{
   printf("\nBase del rombo(numero impar positivo): \n");
   scanf("%d",&a);
   }while ( a <=0 || (a % 2) == 0);
   for ( i=-2*(a/2);i<=2*(a/2);i+=2){
     k=i;
     if (i>0)
       k=-i;
     printf("%*c",-k/2+a/2,'*');
     for ( j=0;j<=2*(a/2)-1+k;j++)
       putchar('*');
     putchar ('\n');
   }
   return 0;
}


Y por qué no dibujar el rombo "vacio":


Código (cpp) [Seleccionar]

#include <stdio.h>

int main(){
 int i=0,j,k,a;
 do{
   printf("\nBase del rombo(numero impar positivo): \n");
   scanf("%d",&a);
   }while ( a <=0 || (a % 2) == 0);
   for ( i=-2*(a/2);i<=2*(a/2);i+=2){
     k=i;
     if (i>0)
       k=-i;
     if (k==-2*(a/2) || k==2*(a/2))
       printf("%*c",-k/2+a/2,'*');
     else
       printf("%*c%*c",-k/2+a/2,'*',2*(a/2)+k,'*');
     putchar ('\n');
   }
   return 0;
}


Y para que no falte, uno con recursividad:

Código (cpp) [Seleccionar]

#include <stdio.h>

int rellenar (int A,int a);
int main(){
 int a;
 do{
   printf("\nBase del rombo(numero impar positivo): \n");
   scanf("%d",&a);
   }while ( a <=0 || (a % 2) == 0);
   rellenar (-2*(a/2),a);
   return 0;
}

int rellenar (int A,int a){
 int j,k;
 if (A==2*(a/2)+2)
   return 1;
 k=A;
 if (A>0)
   k=-A;
 printf("%*c",-k/2+a/2,'*');
 for ( j=0;j<=2*(a/2)-1+k;j++)
   putchar('*');
 putchar ('\n');
 rellenar (A+2,a);
}


¡¡¡¡ Saluditos! ..... !!!!



dmacias

Vaya, si que os entreteneis con esto jajajajaja.
He estado liado, de trabajo asta las cejas asi que llevo unos dias parado con los estudios, pero en unos dias me pongo a ello de nuevo.

De todo lo que habeis puesto, de la mayoria hay cosas que no entiendo, soy muy nuevo y solo llevo 4 temas del libro vistos, pero de todos modos les hechare un vistazo.

Gracias a todos por ponerme tantos ejemplos, asi tengo donde elegir y comparar las logicas de cada uno.

Un saludo

leosansan

Cita de: dmacias en  7 Marzo 2014, 22:57 PM

Vaya, si que os entreteneis con esto jajajajaja.
...............................................................

Gracias a todos por ponerme tantos ejemplos, asi tengo donde elegir y comparar las lógicas de cada uno.

Un saludo

Pues si que ha sido entretenido.

Y aunque do-while me lo piso, no me resisto a poner el caso con memset. Es ligeramente diferente al suyo ya que no uso recurrencia y es ligeramente más cortito:


Código (cpp) [Seleccionar]

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

int main(void){
  int i,j,a;
  do{
    printf("\nBase del rombo(numero impar positivo): \n");
    scanf("%d",&a);
    }while ( a <=0 || (a % 2) == 0);
  char *str = malloc(2*a+1);
  for (i = -a/2; i <= a/2; i++){
    j=i;
  if (i>0)
    j=-i;
    memset (str,' ',(a/2)-j);/** relleno izquierda con espacios **/
    memset (str+(a/2)-j, '*',2*((a/2)+j)+1); /** relleno derecha con asteriscos **/
    printf ("%s\n",str);
    memset (str,0,2*a+1);/** hago nula la cadena para volver a usarla **/
  }
  free(str);
  return EXIT_SUCCESS;
}


¡¡¡¡ Saluditos! ..... !!!!




do-while

#17
Otra forma mas. Esta considerando la pantalla una matriz de 20X80 caracteres y dibujando así sobre la matriz el rombo.


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

#define MAX_FILAS 20
#define MAX_COLUMNAS 80

void dibujar_borde(char pantalla[][MAX_COLUMNAS],int n_filas)
{
   int i;

   for(i = 0 ; i < n_filas ; i++)
       pantalla[i][abs(n_filas / 2 - i)] = pantalla[i][n_filas - abs(n_filas / 2 - i) - 1] = '*';
}

void rellenar(char pantalla[][MAX_COLUMNAS], int fila, int columna)
{
   if(pantalla[fila][columna] == '*' || fila < 0 || fila >= MAX_FILAS || columna < 0 || columna >= MAX_COLUMNAS)
       return;

   pantalla[fila][columna] = '*';

   rellenar(pantalla, fila - 1, columna);
   rellenar(pantalla, fila + 1, columna);
   rellenar(pantalla, fila, columna - 1);
   rellenar(pantalla, fila, columna + 1);
}

void imprimir(char pantalla[][MAX_COLUMNAS])
{
   int i;

   for(i = 0 ; i < MAX_FILAS ; i++)
       printf("%.*s\n",MAX_COLUMNAS - 1 , pantalla[i]);
}

void rombo_2(int n_filas)
{
   char pantalla[MAX_FILAS][MAX_COLUMNAS];
   int i;

   if(!(n_filas & 1))
       return;

   for(i = 0 ; i < MAX_FILAS ; i++)
       memset(pantalla[i],' ',MAX_COLUMNAS);

   dibujar_borde(pantalla,n_filas);
   rellenar(pantalla , n_filas / 2 , n_filas / 2);
   imprimir(pantalla);
}

int main(int argc, char *argv[])
{
   rombo_2(11);

   return 0;
}


No es tan corta como las otras pero bueno, primero dibuja el perimetro y luego rellena el interior. Si rellenais el exterior tendreis el dibujo en "negativo".

¡Saludos!

Y ahora complicandolo un poco mas:

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

#define MAX_FILAS 20
#define MAX_COLUMNAS 80

int correcto(int fila,int columna)
{
   return fila >= 0 && fila < MAX_FILAS && columna >=0 && columna < MAX_COLUMNAS;
}

void dibujar_borde(char pantalla[][MAX_COLUMNAS],int n_filas , int fila_centro, int columna_centro)
{
   int i;

   for(i = 0 ; i < n_filas ; i++)
   {
       if(correcto(fila_centro - n_filas / 2 + i , columna_centro - n_filas / 2 + abs(n_filas / 2 - i)))
           pantalla[fila_centro - n_filas / 2 + i][columna_centro - n_filas / 2 + abs(n_filas / 2 - i)] = '*';

       if(correcto(fila_centro - n_filas / 2 + i , columna_centro + n_filas / 2 - abs(n_filas / 2 - i)))
           pantalla[fila_centro - n_filas / 2 + i][columna_centro + n_filas / 2 - abs(n_filas / 2 - i)] = '*';
   }
}

void rellenar(char pantalla[][MAX_COLUMNAS], int fila, int columna)
{
   if(pantalla[fila][columna] == '*' || fila < 0 || fila >= MAX_FILAS || columna < 0 || columna > MAX_COLUMNAS)
       return;

   pantalla[fila][columna] = '*';

   rellenar(pantalla, fila - 1, columna);
   rellenar(pantalla, fila + 1, columna);
   rellenar(pantalla, fila, columna - 1);
   rellenar(pantalla, fila, columna + 1);
}

void imprimir(char pantalla[][MAX_COLUMNAS])
{
   int i;

   for(i = 0 ; i < MAX_FILAS ; i++)
       printf("%.*s\n",MAX_COLUMNAS - 1 , pantalla[i]);
}

void rombo_3(char pantalla[][MAX_COLUMNAS], int n_filas, int fila_centro, int columna_centro)
{
   int i;

   if(!(n_filas & 1))
       return;

   dibujar_borde(pantalla , n_filas, fila_centro , columna_centro);
   rellenar(pantalla , fila_centro, columna_centro);
}

int main(int argc, char *argv[])
{
   char pantalla[MAX_FILAS][MAX_COLUMNAS];
   int i;
   char cad[] = "QUEDA BONITO";

   for(i = 0 ; i < MAX_FILAS ; i++)
       memset(pantalla[i],' ',MAX_COLUMNAS);

   rombo_3(pantalla, 11 , 10, 11/2);
   rombo_3(pantalla, 17 , 10 , 11 + 17/2);
   rombo_3(pantalla, 19 , 10 , 28 + 19 / 2);

   for(i = 0 ; cad[i] ; i++)
       pantalla[5 + i][50] = cad[i];

   imprimir(pantalla);
}


¡Saludos!

Y en esta tercera versión, podéis jugar con los caracteres que forman el borde y los rellenos.



int correcto(int fila,int columna)
{
    return fila >= 0 && fila < MAX_FILAS && columna >=0 && columna < MAX_COLUMNAS;
}

void dibujar_borde(char pantalla[][MAX_COLUMNAS],int n_filas , int fila_centro, int columna_centro,char ch)
{
    int i;

    for(i = 0 ; i < n_filas ; i++)
    {
        if(correcto(fila_centro - n_filas / 2 + i , columna_centro - n_filas / 2 + abs(n_filas / 2 - i)))
            pantalla[fila_centro - n_filas / 2 + i][columna_centro - n_filas / 2 + abs(n_filas / 2 - i)] = ch;

        if(correcto(fila_centro - n_filas / 2 + i , columna_centro + n_filas / 2 - abs(n_filas / 2 - i)))
            pantalla[fila_centro - n_filas / 2 + i][columna_centro + n_filas / 2 - abs(n_filas / 2 - i)] = ch;
    }
}

void rellenar(char pantalla[][MAX_COLUMNAS], int fila, int columna, char relleno)
{
    char actual;

    if(!correcto(fila,columna))
        return;

    actual = pantalla[fila][columna];

    if(relleno == actual)
        return;

    pantalla[fila][columna] = relleno;

    if(correcto(fila - 1,columna) && actual == pantalla[fila - 1][columna])
        rellenar(pantalla, fila - 1, columna,relleno);

    if(correcto(fila + 1,columna) && actual == pantalla[fila + 1][columna])
        rellenar(pantalla, fila + 1, columna,relleno);

    if(correcto(fila,columna + 1) && actual == pantalla[fila][columna + 1])
        rellenar(pantalla, fila, columna + 1,relleno);

    if(correcto(fila,columna - 1) && actual == pantalla[fila][columna - 1])
        rellenar(pantalla, fila, columna - 1,relleno);

    pantalla[fila][columna] = relleno;
}

void imprimir(char pantalla[][MAX_COLUMNAS])
{
    int i;

    for(i = 0 ; i < MAX_FILAS ; i++)
        printf("%.*s\n",MAX_COLUMNAS - 1 , pantalla[i]);
}

int main(int argc, char *argv[])
{
    char pantalla[MAX_FILAS][MAX_COLUMNAS];
    int i;
    char cad[] = "QUEDA BONITO",interior = '*', exterior = ' ';

    for(i = 0 ; i < MAX_FILAS ; i++)
        memset(pantalla[i],' ',MAX_COLUMNAS);

    dibujar_borde(pantalla, 11 , 10, 11/2 , interior);
    rellenar(pantalla,10,11/2,interior);

    dibujar_borde(pantalla, 17 , 10, 10 + 17/2, interior);
    rellenar(pantalla, 10 , 10 + 17 / 2, interior);

    dibujar_borde(pantalla, 11 , 10, 26 + 11 / 2, interior);
    rellenar(pantalla, 10 , 26 + 11 / 2 , interior);

    rellenar(pantalla,0,0,exterior);

    for(i = 0 ; cad[i] ; i++)
        pantalla[5 + i][50] = cad[i];

    imprimir(pantalla);

    return 0;
}


¡Saludos de nuevo!
- Doctor, confundo los números y los colores.
- Vaya marrón.
- ¿Marrón? ¡Por el culo te la hinco!

leosansan


Vamos, con matrices.

Ahí va una con el borde:




Código (cpp) [Seleccionar]

/** BORDES **/
#include <stdio.h>

int main(){
  int i=0,j,k=1,a=21;

  /*do{
    printf("\nBase del rombo(numero impar positivo): \n");
    scanf("%d",&a);
    }while ( a <=0 || (a % 2) == 0);*/
    char A[a+4][a+4],cad[]="L E O S A N S A N";
    for ( i=0;i<=a+4;i++)
      for ( j=0;j<=a+4;j++)
        A[i][j]='0';
    A[0][a/2]='*';
    i=1;
    while (i<=a/2){
      A[i][(a/2)-i]=A[i][i+(a/2)]='*';
      i++;
    }
    k=i;
    while (i>=(a/2)+1 && i<=a){
      k--;
      A[i][(a/2)+1-k]=A[i][(a/2)+k-1]='*';
      i++;
    }
    if (a>20){
      for ( i=(a/2)-8,k=0;i<(a/2)+10;i++,k++)
        A[i][22]=cad[k];
    }

    putchar ('\n');
    for ( i=0;i<a;i++){
      printf("\t\t");
      for ( j=0;j<a+2;j++){
         if (A[i][j]=='0' )
            printf("%c",' ');
          else
            printf("%c",A[i][j]);
      }
      putchar ('\n');
    }
    return 0;
}


Y por qué no en positivo y negativo:


Código (cpp) [Seleccionar]

#include <stdio.h>

int main(){
  int i=0,j,k=1,a=21;
  /*do{
    printf("\nBase del rombo(numero impar positivo): \n");
    scanf("%d",&a);
    }while ( a <=0 || (a % 2) == 0);*/
    char A[a+1][a+1];
    for ( i=0;i<=a;i++)
      for ( j=0;j<=a;j++)
        A[i][j]='0';
    A[0][a/2]='*';
    i=1;
    while (i<=a/2){
      for ( j=(a/2)-i;j<=i+(a/2);j++){
        A[i][j]='*';
      }
      i++;
    }
    k=i;
    while (i>=(a/2) && i<=a){
      --k;
      for ( j=(a/2)+1-k;j<(a/2)+k;j++)
        A[i][j]='*';
      i++;
    }
    /** EN POSITIVO **/
    for ( i=0;i<=a;i++){
      printf("\t\t");
      for ( j=0;j<a;j++){
         if (A[i][j]=='0')
            printf("%c",' ');
          else
            printf("%c",A[i][j]);
      }
      putchar ('\n');
    }
    putchar ('\n');
    /** EN NEGATIVO **/
    for ( i=0;i<=a;i++){
      printf("\t\t");
      for ( j=0;j<a;j++){
         if (A[i][j]=='0')
            printf("%c",'*');
          else
            printf("%c",' ');
      }
      putchar ('\n');
    }
    return 0;
}


He preferido hacer dos códigos en lugar de uno con funciones para los posibles seguidores de este tema .... y paso de traslaciones, empiezo a estar saturado de tanto rombo. ¿Alguien se anima a empezar un nuevo tema con el triángulo de Pascal o Tartaglia?

¡¡¡¡ Saluditos! ..... !!!!



Yoel Alejandro

Ok, el triángulo de Pascal, pero exactamente qué se te ocurre hacer?? Acepto el reto, jeje (claro, en un nuevo post) ...
Saludos, Yoel.
P.D..-   Para mayores dudas, puedes enviarme un mensaje personal (M.P.)