Este que veis sería el resultado de hacer un rombo de lado igual a 7.
@
@.@
@.O.@
@.O.O.@
@.O.@.O.@
@.O.@.@.O.@
@.O.@.O.@.O.@
@.O.@.@.O.@
@.O.@.O.@
@.O.O.@
@.O.@
@.@
@
Lo primero, analicemos como se hace un rombo, simplificandolo lo mas posible. Un rombo está formado por varias partes (sustituiré los puntos por espacios y el patrón por asteriscos). Tambien voy a numerar las lineas y columnas.
1234567|654321
1 ......*| 1
2 .....**|* 2
3 ....***|** 3
4 ...****|*** 4
5 ..*****|**** 5
6 .******|***** 6
7 *******|****** 7
----------------
6 .******|***** 6
5 ..*****|**** 5
4 ...****|*** 4
3 ....***|** 3
2 .....**|* 2
1 ......*| 1
Podemos observar que existen cuatro sectores. En el primer sector de nuestro ejemplo (recordemos que tiene un lado igual a 7), que es el situado arriba a la izquierda, vemos que existen siete columnas y siete filas. En el segundo sector, arriba a la derecha, vemos que existe el mismo numero de filas, pero una columna menos. En el tercer sector hay una fila menos y en el cuarto tanto una fila menos como una columna.
Os preguntareis por que he escrito varios numeros en forma creciente, y otros en forma decreciente. Esto tiene su razon de ser: en este caso necesitaremos que sea simetrico. El sistema sería mucho mas simple sin la simetría requerida, pero la práctica no cumpliría su finalidad.
Vamos a empezar a codificar nuestro programa. Usaré el valor de lado = 7 para las pruebas. Mas adelante incluiré la opcion de que pregunte que queremos hacer.
Necesitaremos un bucle que nos imprima los espacios. Como vamos a usar para nuestro ejemplo asteriscos, puntos y finalmente espacios, crearemos un pequeño procedimiento auxiliar que llamaré escribeCar.
void escribeCar(int veces, char car){
for (int i = 1; i <= veces; i++){
printf("%c",car);
}
}
Esto quiere decir que escriba el caracter car un numero veces de veces. Para ello, usaremos un contador llamado i.
Lo pondremos en práctica con la primera parte del rombo. En cada linea l podemos ver que hay e espacios y l asteriscos y que la suma de ambos es e+l = lado. Entonces en cada linea tendremos que poner (lado-l)-1 espacios y l asteriscos.
Vamos a codificar eso. Usamos el codigo que he puesto en el archivo ejemplo1.cpp
......*
.....**
....***
...****
..*****
.******
*******
......1
.....121
....12321
...1234321
..123454321
.12345654321
1234567654321
......1
.....121
....12321
...1234321
..123454321
.12345654321
1234567654321
.12345654321
..123454321
...1234321
....12321
.....121
......1
Si el resto de dividir el numero del caracter mostrado por 4 es
0, poner @
2, poner o
1 o 3, poner .
Vemos ahora que hay un error que he cometido, que ha sido empezar a escribir las lineas empezando por 1. Tenemos ahora dos opciones, modificar el bucle original y resolverlo, o hacer un parchecito. Como me gusta hacer las cosas bien, corregiré el ejemplo3, y de paso le quitaré los puntos y los sustituiré por espacios. Podeis descargar la correccion en ejemplo4.cpp. Aqui teneis el resultado de la correccion.
0
010
01210
0123210
012343210
01234543210
0123456543210
01234543210
012343210
0123210
01210
010
0
Para cambiarlo, usaré una sentencia switch, que tambien la meteré en una funcion. Veamos el resultado del ejemplo5.cpp:
@
@.@
@.o.@
@.o.o.@
@.o.@.o.@
@.o.@.@.o.@
@.o.@.o.@.o.@
@.o.@.@.o.@
@.o.@.o.@
@.o.o.@
@.o.@
@.@
@
Mi amigo tambien me planteaba una cuestion acerca de los arrays y me pregunto, ¿sería posible usar un array para la secuencia? La respuesta es muy simple: si. Cambiaremos el procedimiento selecCarac para que sea
char selecCarac(int carac){
char secuencia[]={'@','.','o','.'};
printf("%c",secuencia[carac%4]);
}
en lugar de ser
char selecCarac(int carac){
switch (carac%4){
case 0:
printf("%c", '@');
break;
case 2:
printf("%c", 'o');
break;
default:
printf("%c", '.');
break;
}
}
De hecho, la opcion que usa arrays es mucho mas eficiente, ya que en vez de realizar comparaciones simplemente accede a memoria. Por tanto, dejaremos esta opcion en el programa.
Tambien vamos a agregar parte de la interfaz, para que podamos pasar a la parte de pruebas. Aqui teneis el ejemplo6.cpp con la modificacion anterior y las lineas para poder introducir el numero de lados.
Ahora vamos a hacer unas comprobaciones, si no las hemos ido haciendo al probar. Que ocurre si:
- Ponemos un valor impar de lados (probaremos con 9 lados):
@
@.@
@.o.@
@.o.o.@
@.o.@.o.@
@.o.@.@.o.@
@.o.@.o.@.o.@
@.o.@.o.o.@.o.@
@.o.@.o.@.o.@.o.@
@.o.@.o.o.@.o.@
@.o.@.o.@.o.@
@.o.@.@.o.@
@.o.@.o.@
@.o.o.@
@.o.@
@.@
@
- Ponemos un valor par de lados (probaremos con 8 lados):
@
@.@
@.o.@
@.o.o.@
@.o.@.o.@
@.o.@.@.o.@
@.o.@.o.@.o.@
@.o.@.o.o.@.o.@
@.o.@.o.@.o.@
@.o.@.@.o.@
@.o.@.o.@
@.o.o.@
@.o.@
@.@
@
- Ponemos 1 unico lado:
@
Correcto de nuevo. Si hubieramos cometido un error, posiblemente habrian aparecido dos arrobas en vertical.
- Ponemos 2 lados:
@
@.@
@
- Ponemos 0 lados:
Obviamente, el programa no saca nada por pantalla.
- Ponemos un numero negativo (probaremos con -5):
Analogamente, un poligono no puede tener un valor de lado negativo, con lo que no muestra nada por pantalla. De hecho, vamos a hacer una comprobacion adicional: ¿escribe algo raro en donde van los espacios? Si cambio de nuevo el codigo para que en vez de los espacios vuelva a mostrar puntos no muestra absolutamente nada.
El código, por tanto, es correcto tanto en los casos indicados por el enunciado como en un juego de pruebas extendido. No voy a agregar el limite que indicaban en el enunciado, puesto que no me es necesario en para el proyecto.
Doy por concluido este proyecto. Espero que os haya resultado interesante. Desde el punto de vista didactico creo que lo es, ya que trata sobre descomposicion de problemas, bucles, secuencias de seleccion, arrays y juegos de pruebas.
Sobre la licencia del software: esta permitida la descarga, compilacion y modificación del codigo para su uso personal con fines didacticos (o sea, para experimentar). Todas las versiones derivadas de este software también deberán cumplir esta licencia. Queda prohibido su uso como implementación de la práctica (nada de copiar, que nos conocemos). Queda prohibida su uso didactico por terceros, ya sea para su uso en clases a titulo individual o publicacion en material docente. En cualquier caso, queda prohibido su uso con fines comerciales.
Hasta el proximo proyecto, un saludo.
No hay comentarios:
Publicar un comentario