|
Más Cuadrados Mágicos TemasIntroducción.Si has aprobado el examen y la práctica, en estos momentos debes tener
una pequeña aplicación que, a petición del usuario, dibuja un CM
(Cuadrado Mágico) de 3x3. Pero los Cuadrados Mágicos pueden ser mayores, de hecho, es infinito el número de
CM's que podemos crear, siguiendo determinadas reglas. La entrada de datos.En la mayoría de las aplicaciones, se requiere la intervención del usuario, para algo más que abrir o cerrar ventanas, pulsar botones o seleccionar elementos de listas o menús. En todos estos casos, la aplicación conoce todas las posibles respuestas, ya que pertenecen a un conjunto finito de opciones posibles.
Los cuadros de introducción de datos. Inputbox.Aunque no es la forma más comúnmente utilizada para la entrada de datos, la función
InputBox es, en ocasiones, bastante útil. Las Funciones.Visual Basic como todos los lenguajes de programación tiene funciones
y procedimientos incorporados aunque también puedes definir los tuyos propios. La sintaxis genérica de las funciones es:
donde variable es la variable que almacenará el resultado de la función, función es el nombre de la función y argumentos son los datos que opcionalmente necesita la función. La función InputBox.Esta función muestra un cuadro de diálogo modal (éste es un término técnico para definir un formulario que ha de cerrarse antes de poder continuar con el desarrollo normal del programa), que contiene un Título y un Mensaje (definibles), un cuadro de texto y dos botones y .
La sintaxis general de la función InputBox es:
donde:
El funcionamiento dc InputBox es el siguiente: Cuando Vb se encuentra con una línea como esta:
presenta en pantalla un InputBox como el de la figura 2.2 y espera que el usuario introduzca algún texto en el cuadro de texto y pulse los botones o , o las teclas o o pulse el botón para cerrar la ventana.
Analicemos todas las posibilidades:
Evidentemente las dos primeras devuelven el mismo valor independientemente de lo que haya en el cuadro de texto, es decir, una cadena
nula; y la última devuelve lo que haya en el cuadro de texto, se haya modificado o no. Los cuadros de texto. Textbox.A diferencia de los InputBox, dentro de nuestro formulario, sí podemos tener más de un TextBox, de hecho, éste será el caso más común dentro de una aplicación Vb. Otra gran diferencia es que en los TextBox sí podemos controlar mucho de su comportamiento. Los cuadros de texto con formato. RichTextBox.Estos cuadros de texto son muy similares a los TextBox, es decir, podemos tener varios dentro del mismo formulario y podemos controlar su comportamiento; pero la gran diferencia con los TextBox es que pueden mostrar texto con varios tipos de fuentes y tamaño, además de no estar limitados a 32.000 caracteres. Tanto los TextBox como los RichTextBox los veremos más en detalle cuando sea necesario. De momento para nuestra práctica usaremos un InputBox como el de a figura 2.2. Con este InputBox permitiremos que el usuario decida el tamaño del CM. Pero existen unas reglas que ha de cumplir, y esto nos servirá para introducir otro concepto importante en la programación, las estructuras de control de flujo del programa. Las Estructuras de Control de Flujo del Programa.El control de flujo de un programa es la herramienta principal que permite que un programa tome decisiones y efectúe así una acción u otra, es decir, sin estas estructuras, el fluir del programa sería secuencial, de izquierda a derecha y de arriba a abajo, mientras que, gracias a ellas, el flujo puede cambiar el orden de las instrucciones. Podemos decir que existen dos tipos de estructuras de control de flujo:
En nuestro caso, la aplicación debe tomar una decisión dependiendo del tamaño del CM que el usuario elija, por lo que necesitará una estructura de decisión, pero primero vamos a explicar algunas de las reglas que deben cumplirse para poder crear un CM. La primera limitación que debemos tener en cuenta a la hora de generar un CM es que su razón sólo puede ser impar, es decir, sólo puede ser 3x3, 5x5, 11x11, etc. Luego, nuestra aplicación debe controlar que el usuario no introduzca un número par como razón del CM. Otra limitación es más bien física que real, ya que debemos limitar el tamaño del CM para poder mostrarlo en nuestro formulario. En realidad, los CMs no tienen límite de tamaño, pero, aunque existen métodos para mostrar en una ventana un formulario mayor que el tamaño de la ventana, existe también la limitación del tamaño de memoria del ordenador del usuario. De manera que limitaremos el tamaño de nuestro CM a 15x15. Luego para nuestro InputBox definiremos los siguientes parámetros:
(El resto de los parámetros los dejaremos con sus valores por omisión.) La línea de código entonces será:
Esto nos genera un InputBox como el de la figura 2.3:
A nivel puramente estético, podemos preferir que el texto del mensaje que se encuentra entre paréntesis empiece en la siguiente línea. Esto es posible cambiando la cadena del mensaje de manera que contenga un código de salto de línea. Para ello dividimos la cadena en dos trozos, que corresponden a las dos líneas del mensaje resultante e intercalamos entre las dos cadenas el código correspondiente al salto de línea Chr(13) mediante el operador de concatenación &. De manera que la línea de código queda como sigue:
Compruébalo tu mismo Volviendo a nuestra aplicación, hemos dicho que necesitará una estructura de decisión, veamos por qué. Supongamos que el usuario ha decidido generar un CM, luego aparece el InputBox el cual puede devolvernos distintos valores en la variable cRazonCM que pueden ser:
Aunque te parezca un poco exagerado este estudio, cuanto más profundices en las posibles respuestas de los usuarios a tus programas, controlarás mejor los posibles errores de programación que, por otro lado, he de decirte que siempre surgirán; es utópico pensar que un programa funcionará perfectamente a la primera, siempre se nos escapa algo. De todas las opciones posibles, vemos que la primera de cada subgrupo no es válida ya que no cumple con los criterios establecidos para nuestro CM y la segunda nos lleva a un nuevo subgrupo de discriminación hasta llegar a la última subopción que es la única que cumple con dicho criterio. Para que nuestra aplicación decida si el valor obtenido es válido vamos a utilizar una estructura de decisión. Las estructuras de decisión.Las estructuras de decisión permiten comprobar una condición y, dependiendo del resultado, ejecutar una serie de instrucciones. Vb contiene las siguientes estructuras de decisión:
La estructura de decisión If...Then.En lenguaje natural equivale a "Si..entonces". Esta estructura tiene dos posibles sintaxis:
donde:
La estructura de decisión If...Then...Else.En lenguaje natural equivale a "Si...entonces...si no". Su sintaxis es:
donde primero se comprueba la condición 1; si devuelve True se ejecuta el bloque de instrucciones 1, en caso contrario, se comprueba la condición 2 y así sucesivamente hasta que una condición devuelve True o bien, si ninguna de las condiciones lo hace, se ejecuta el bloque de instrucciones n, La estructura de decisión Select Case.En lenguaje natural equivale a "En el caso que...o que". Esta estructura es muy similar a If...Then...Else. De hecho todo lo que hace Select Case se puede hacer con If...Then...Else, sólo que Select Case consigue un código más legible cuando son varias las opciones. Su sintaxis es:
donde:
En concreto para nuestra aplicación utilizaremos el primer tipo If...Then. En lenguaje natural diríamos:
Para traducirlo a Vb debemos aprender a usar alguna de sus funciones. Como ves, la condición debe ser: que cRazonCM sea impar y entre 3 y 15. Otra forma de expresarlo sería: que cRazonCM sea impar y que cRazonCM sea mayor o igual a 3 y que cRazonCM sea menor o igual a 15. Los operadores lógicos mayor o igual que y menor o igual que son >= y <= respectivamente, y la unión lógica Y es And. Luego la segunda parte de la condición quedará ...(cRazonCM >= 3) And (cRazonCM <= 15)... En este caso, los paréntesis están sólo para mayor claridad, pero no son indispensables. La primera parte de la condición es un poco más complicada. ¿Como podemos controlar que un número sea o no impar? En la vida real, simplemente lo sabemos si el número en cuestión es o no divisible por 2, pero en el cibermundo no existe una función así; en su lugar tenemos la función Módulo m Mod n que nos devuelve el resto de dividir m entre n; de manera que para saber si un número es impar sólo debemos comprobar que el módulo de dicho número con respecto a 2 es distinto de 0 que traducido a Vb será: ...cRazonCM Mod 2 <> 0 (el operador lógico distinto de en Vb es <>); de manera que la estructura de control queda:
Este fragmento de código debe insertarse justo después de la línea InputBox. Bien, ya tenemos claro dónde colocar la estructura de control y el
InputBox y es dentro del evento Click del botón
; pero este evento lo tenemos que modificar un poco. Para ello sigamos el diagrama de
flujo de la figura 2.4:
Como podemos ver, nuestra aplicación sólo actuará si el dato introducido es válido. Pero ¿que líneas debe haber dentro de la estructura de control
If...Then? Evidentemente ya no nos sirven las que teníamos, pues esas sólo generaban un
CM de 3x3, y ahora el usuario puede pedirlo de 7x7, 11x11, etc. Luego ¿vamos a crear un grupo de líneas para cada tamaño? En nuestro caso sería posible, ya que hemos definido un número finito de opciones al usuario, en concreto sólo puede pedirnos 8
CM's distintos (3x3, 5x5, 6x6, 7x7, 9x9, 11x11, 13x13 y 15x15) lo cual representaría
ocho grupos de líneas diferentes, un poco de tedioso trabajo nada más. Pero
¿que pasa si queremos aumentar las posibilidades de nuestra aplicación?, ¿que pasa si queremos que nuestro programa pueda crear
CM's de 100x100 o de1000x1000?, la cosa cambia. Evidentemente ésta no es la solución. ¡Hagamos que las computadoras trabajen por nosotros! pero ¿Como? El Método.Para rellenar un CM debemos seguir las siguientes reglas independientemente del tamaño:
Y eso es todo. Parece increíble ¿verdad?, pero funciona, te lo aseguro. Y si no lo crees, compruébalo por ti mismo. Y resumiendo, el código del evento Click del botón debe quedar así:
El Algoritmo.Nuestro siguiente paso es convertir todo lo que hemos visto
anteriormente en un Algoritmo, que es como en lenguaje de programación se conoce al
conjunto de instrucciones que ejecutan una tarea
determinada. Los Procedimientos Sub.Más arriba en esta lección ya hablamos de las funciones y los
procedimientos. Una de las principales razones para crear procedimientos
es el hecho de que un determinado grupo de líneas de código se repita varias veces en un programa. Cuantas más veces se repita, más importante es el ahorro en líneas de código. Además, hacen los programas más fáciles de mantener, ya que si tenemos que efectuar alguna modificación a dicho código, sólo lo haremos una vez.
Otra razón es la de simplificar los programas en unidades lógicas más
pequeñas. También es importante su capacidad de reutilización para otros
programas. Sub GeneraCM + y automáticamente aparecen las líneas de división (si tienes activada esta opción) así como el código de fin de procedimiento: End Sub y es entre estas dos líneas en las que desarrollaremos el algoritmo. Si hemos dicho que este procedimiento debe servir para generar cualquier tamaño de CM, entonces, tiene que haber alguna forma de que el procedimiento se entere del tamaño deseado. Para esto sirven los parámetros. Los Parámetros.A diferencia de las funciones, los procedimientos o procedimientos Sub no se pueden llamar incluyendo su nombre en una expresión. Para llamar a un procedimiento Sub desde nuestro código existen dos métodos diferentes:
Observa que cuando utilizas el primer formato, los parámetros deben ir entre paréntesis. Pero ¿que son los parámetros? Es la forma en que nosotros, desde nuestro código, le pasamos datos a las funciones o procedimientos para que los utilicen. También se les conoce como argumentos y se pueden pasar de dos formas:
Cuando se pasa un argumento o parámetro por valor lo que se le pasa al procedimiento en realidad es una copia de la variable y no la variable en sí, de manera que, si el procedimiento modifica la variable, los cambios sólo afectan a la copia de la variable y no a la variable original. Para pasar un parámetro por valor se utiliza la palabra clave ByVal en la definición del procedimiento, por ejemplo: Sub Nombre_del_procedimiento (ByVal Parámetro as Tipo_de_dato) Cuando se pasa una parámetro por referencia, que es la forma predeterminada para Vb, se le pasa al procedimiento el contenido real de la variable en su ubicación original. Si el procedimiento modifica el parámetro, modifica la variable en sí. El formato es: Sub Nombre_del_procedimiento (Parámetro [as Tipo_de_dato]) Luego nuestro procedimiento quedará como sigue:
Como puedes ver, he añadido una p al nombre del parámetro para diferenciarlo de la variable en sí y lo definimos del tipo Integer (entero). El Desarrollo.Pasemos por fin al meollo del asunto, el desarrollo del algoritmo para rellenar el CM. Primero vamos a definir qué tipo de dato necesitamos para almacenar en memoria el CM antes de colocarlo en nuestro formulario. Evidentemente no es un tipo de dato sencillo, es decir, no es ni un Número ni una Cadena de caracteres, si no, un conjunto de números organizados en filas y columnas. A este tipo de datos se le conoce como Matriz y en Vb se identifica con la palabra clave Array. El tipo de dato Array.Para declarar una matriz en Vb usamos la palabra clave Dim, a continuación el nombre de la matriz seguido, entre paréntesis, del límite superior. Las matrices en Vb pueden ser unidimensionales y multidimensionales. El límite superior de cada dimensión no puede exceder de un tipo de dato Long (-2.147.483.648 a 2.147.483.647). A menos que se indique lo contrario el subíndice del primer elemento es 0. Así por ejemplo:
Una matriz dinámica es aquella que durante la ejecución de la aplicación, puede cambiar de tamaño. Como la declaración anterior sólo permite constantes como límites, no podemos definir los límites de nuestra matriz en la declaración, así que usaremos la sentencia Redim la cual funciona igual que Dim pero que nos permite el uso de variables para las dimensiones. Luego en nuestro código debe declararse la matriz como sigue:
de esta forma, nuestro procedimiento creará una matriz diferente según el tamaño elegido por el usuario. ¿Por que usar una Matriz? La respuesta es bien sencilla. En primer lugar, es mucho más cómodo trabajar en memoria al rellenar el CM que sobre los labels del formulario y, además, al tratarse de una matriz cuadrada con filas y columnas, resulta muy fácil a la hora de referirnos a cada elemento de la matriz como si de una celda de la matriz se tratara, utilizando las dos dimensiones como equivalentes de la fila y la columna. Una vez entendido esto, sigamos con el desarrollo del algoritmo. En primer lugar definamos su principal tarea. En lenguaje coloquial diremos "Rellenar el CM" y esto consiste ni más ni menos que en recorrer todos los números, desde el 1 hasta el resultado de multiplicar la razón por si misma. (Por ejemplo: si la razón es 7 los números serán desde el 1 hasta el 49). Como esto es una tarea repetitiva, existe un tipo de estructura de control de flujo que ya hemos visto en la primera lección, conocida como "Estructura de bucle" Este tipo de estructura es, en gran medida, lo que hace realmente útiles los programas ya que pueden repetir una tarea determinada, cientos, miles, incluso millones de veces. Estas repeticiones (también conocidas como iteraciones), pueden realizarse un número finito de veces y entonces los llamamos "bucles determinados"; también pueden repetirse hasta que se cumpla una determinada condición, a estos los llamamos "bucles indeterminados". En nuestro caso vamos a necesitar....... Si pensaste en un bucle determinado acertaste. El número de iteraciones de nuestro programa será finito, (desde 1 hasta 49 en el ejemplo). La estructura de control del tipo bucle determinado de Vb es el conocido como bucle For...Next, que ya utilizamos en la primera lección. Su diagrama de flujo es el de la figura 2.n y su sintaxis es como sigue:
y su explicación es como sigue:
Luego, para nuestro código tomaremos los siguientes valores:
esto es, el contador empezará con el valor 1, ejecutará las sentencias del cuerpo del bucle e incrementará el contador en 1 repitiendo el cuerpo del bucle hasta que el contador sea mayor que el valor_final pasando en dicho caso a ejecutar las líneas de código a cuntinuación del Next. De manera que en nuestro código quedará:
Como puedes ver, utilizo n como contador, aunque puedes darle cualquier nombre. También notarás que Vb utiliza el asterisco * como operador de la multiplicación. Al ser el incremento igual a 1, que es el valor predeterminado, no necesita especificarse. Ahora recordemos la primera regla para rellenar un CM:
Calcular la última fila es fácil ya que coincide con el valor de la razón y calcular la columna central también, ya que es igual a la mitad de la razón más uno. Pero como esta regla sólo debe cumplirse para un elemento, es decir, sólo para el primer elemento, la asignación de la fila y columna correspondiente la haremos fuera del bucle, así:
Como puedes ver, usamos la operación pcRazonCM / 2 +1 para calcular la columna central, pero quizá estés pensando que el resultado real sería un número de columna fraccionario, (por ejemplo, para un rango de 15, sería igual a 8.5), pero como hemos definido el tipo de dato de nColumna a Integer (entero) Vb se encarga automáticamente de truncar el número para convertirlo en entero. Ahora debemos asignar el número n al elemento de la matriz de fila nFila y columna nColumna. En Vb la sintaxis para asignar valores a elementos de una matriz es la siguiente: CuadradoMagico( nFila, nColumna ) = n así que añadimos esta línea a nuestro código, como primera línea del cuerpo del bucle. En realidad, esta será la línea principal ya que es la que asignará cada elemento a la matriz hasta llenarla. Seguidamente tenemos que aplicar las demás reglas del método para rellenar CM's. Iremos rellenando los elementos de la matriz uno a uno, pasando a la siguiente fila y siguiente columna, excepto que el último elemento asignado a la matriz sea igual o múltiplo de la razón en cuyo caso sería en la fila anterior y misma columna. Pero ¿como traducimos ésto a còdigo Vb? Vayamos por partes. En primer lugar nos encontramos con que debemos comprobar si n es múltiplo de pcRazonCM; en caso afirmativo ejecutar una acción y, en caso contrario, ejecutar otra distinta. Para esto utilizamos la estructura de decisión If...Then...Else. Para saber si n es múltiplo de pcRazonCM usamos de nuevo la función Mod (mòdulo).
Como ves, las líneas en color verde van precedidas de un apóstrofe ' que es uno de los métodos que usa Vb para añadir comentarios al código. Es muy importante comentar el código, ya que te será de gran ayuda si tienes que depurarlo o, sobre todo, cuando tengas que mantenerlo o bien, que el mantenimiento lo vaya a realizar otra persona, por ejemplo, de tu grupo de programación. Ahora, dentro de las acciones a ejecutar si n es múltiplo de pcRazonCM, el método de relleno de CM's nos dice que el siguiente elemento debe colocarse en la fila anterior y en la misma columna, pero si la fila es igual a 1 entonces la fila debe ser igual a la razón. Luego nos encontramos con otra toma de decisión que se traduce en una estructura de control If...Then...Else dentro de la primera, lo que se conoce con estructuras anidadas. Y el código es el siguiente:
Observa como indentamos (colocamos un poco más a la derecha) las líneas que pertenecen a una estructura; esto no es obligatorio, pero nos ayuda a ver con mucho más claridad el código. Por último, para las acciones a ejecutar si n NO es múltiplo de pcRazonCM, tenemos que el método nos dice que tanto la fila como la columna del siguiente elemento debe ser la siguiente pero que tanto si la fila como la columna son la última, entonces deben ser la primera. Y con esto concluye la Lección II. Ejercicio de control.Como ejercicio de comprobación de esta lección deberás hacer lo siguiente:
Si consideras que ya estás preparado, puedes acceder al examen de la Lección II
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||