Más Cuadrados Mágicos


Temas

Introducció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.
En esta lección vamos a ampliar nuestra aplicación con una nueva característica. El usuario podrá elegir el tamaño del CM y para ello vamos a aprender a utilizar un objeto sumamente útil para la interacción aplicación-usuario, la entrada de datos.

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.
Pero ¿que pasa cuando los datos que necesita la aplicación son imprevisibles?; por ejemplo: si necesitamos una fecha, la cantidad de capital para calcular un rendimiento, un nombre de usuario, el tamaño de un CM, etc.
Para estos casos Vb nos ofrece varias opciones. Cada una la veremos de forma general y alguna de forma más específica. Estas opciones son:

  • Los cuadros de introducción de datos. Inputbox.

  • Los cuadros de texto. Textbox.

  • Los cuadros de texto con formato. RichTextBox.

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.
Si te has fijado, no he hablado de control sino de función y es que InputBox es una función y no un control. Veamos que significa esto.

Las Funciones.

Visual Basic como todos los lenguajes de programación tiene funciones y procedimientos incorporados aunque también puedes definir los tuyos propios.
Una función es una porción de código que realiza una tarea específica, que puede recibir datos de entrada, conocidos en el argot informático como parámetros o argumentos y que, a diferencia de los procedimientos de evento siempre devuelven un valor.
Esta última característica es la que te servirá para decidir si defines una función o un procedimiento. Si necesitas que devuelva algún valor será una función lo que definas, si no necesitas que devuelva ningún valor, definirás entonces un procedimiento.

La sintaxis genérica de las funciones es:

  variable = función([argumentos])

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 .

Figura 2.1

La sintaxis general de la función InputBox es:

   variable=InputBox(Prompt[, Title] [, Default] [, XPos] [, YPos] [, HelpFile, Context]) 

donde:

  • Prompt es un mensaje o variable de cadena que Vb presenta dentro del Inputbox.

  • Title (opcional) es el texto que aparece en la barra de título del Inputbox. Si se omite Vb coloca el nombre de la aplicación.

  • Default (opcional) es el texto que aparecerá por omisión en el cuadro de texto. Si se omite el cuadro aparece en blanco.

  • XPos e YPos (opcionales) son valores numéricos que contienen en twips la distancia de los bordes izquierdo y superior del InputBox a los bordes izquierdo y superior de la pantalla respectivamente. Si se omite el primero, el InputBox se centra horizontalmente; si se omite el segundo, el InputBox aparece en el primer tercio de la pantalla aproximadamente.

  • HelpFile y Context se utilizan conjuntamente cuando la aplicación tiene un fichero de ayuda asociado. Si se omiten no tiene ningún efecto pulsar para recibir ayuda.

El funcionamiento dc InputBox es el siguiente:

Cuando Vb se encuentra con una línea como esta:

   cMiVariable=InputBox("¿De que tamaño quieres el Cuadrado Mágico?", "Generador de Cuadrados Mágicos",3) 

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.

Figura 2.2

 

NOTA: Estas son todas las posibilidades que tiene el usuario en este punto. A menudo verás lo conveniente que es, durante el desarrollo de una aplicación, analizar todas las posibles acciones que puede efectuar el usuario en un momento dado, ya que de esta forma controlas los errores generados por acciones indebidas y evitas las sorpresas de acciones inesperadas.

Analicemos todas las posibilidades:

Acción  Efecto
Pulsar

cMiVariable=""
Pulsar

cMiVariable=""
Pulsar

cMiVariable=valor

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.
El inconveniente que tiene la sencillez de uso de InputBox es su poca flexibilidad. Sólo en contadas ocasiones será uno solo el dato necesario, además de no poder controlar de ningún modo el Textbox ni sus eventos. No obstante habrá ocasiones en que te será de gran utilidad.

Los cuadros de texto. Textbox.

A diferencia de los InputBox, dentro de nuestro formulario, 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:

  • Las estructuras de decisión que son las utilizadas para bifurcar y

  • Las estructuras de bucle que son para repetir procesos.

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 Mensaje debe ser "¿De qué tamaño quieres el Cuadrado Mágico?. (Debe ser un número impar y menor o igual a 15)"

  • El Título será "Generador de Cuadrados Mágicos".

  • La Variable para almacenar el resultado se llamará cRazonCM

(El resto de los parámetros los dejaremos con sus valores por omisión.)

La línea de código entonces será:

   cRazonCM=InputBox("¿De que tamaño quieres el Cuadrado Mágico?. (Debe ser un número impar entre 3 y 15 inclusive)", "Generador de Cuadrados Mágicos") 

Esto nos genera un InputBox como el de la figura 2.3:

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:

   cRazonCM=InputBox("¿De que tamaño quieres el Cuadrado Mágico?." & Chr(13) & "(Debe ser un número impar entre 3 y 15 inclusive)", "Generador de Cuadrados Mágicos") 

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:

  1. Una cadena vacía ""

  2. Una cadena no vacía que puede ser:

    1. Una cadena no numérica

    2. Una cadena numérica que puede ser:

      1. Una cadena numérica par

      2. Una cadena numérica impar que puede ser:

        1. Una cadena numérica impar mayor que 15

        2. Una cadena numérica impar menor o igual a 15 que puede ser:

          1. Una cadena numérica impar menor o igual a 15 y menor que 3

          2. Una cadena numérica impar menor o igual a 15 y mayor o igual a 3

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:

  • If..Then

  • If..Then..Else

  • Select Case

La estructura de decisión If...Then.

En lenguaje natural equivale a "Si..entonces". Esta estructura tiene dos posibles sintaxis:

  • En una sola línea

  If condición Then instrucción(es)
  • En un bloque de varias líneas

  If condición Then 
  
instrucción(es)
End If

donde:

  • condición = expresión que devuelve un valor booleano: True (verdadero) o Flase (Falso); o un valor numérico siendo 0 = False o cualquier otro número = True

  • instruccion(es) = Acción(es) que se ejecuta(n) si la condición devuelve un valor True.

La estructura de decisión If...Then...Else.

En lenguaje natural equivale a "Si...entonces...si no". Su sintaxis es:

  If condición1 Then 
  
[bloque de instrucciones 1]
[ElseIf condición2 Then
  
[bloque de instrucciones 2]]..
[Else
  
[bloque de instrucciones n]].
End If

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:

  Select Case expresiónPrueba 
  
[Case listaExpresiones1
     
[bloque de instrucciones 1]]..
   [Case listaExpresiones2
     
[bloque de instrucciones 1]]..
   .
   .
   .
   [Case Else
     
[bloque de instrucciones n]].
End Select

donde:

  • expresiónPrueba = expresión que es evaluada sólo una vez y que puede devolver cualquier valor de cualquier tipo.

  • listaExpresiones 1 = es una lista de valores con los que se compara expresiónPrueba, si existe una coincidencia entonces se ejecuta el bloque de instrucciones 1, si no, se pasa a la siguiente sentencia Case y así sucesivamente. Si existe más de una sentencia Case que contiene un valor coincidente sólo se ejecuta el bloque de instrucciones asociado a la primera coincidencia.

  • bloque de instrucciones n = es el bloque de instrucciones que se ejecuta en caso de que no se encuentre ninguna coincidencia.

En concreto para nuestra aplicación utilizaremos el primer tipo If...Then.

En lenguaje natural diríamos:

  Si el tamaño del CM es impar y está entre 3 y 15 entonces 
  
genera el CM del tamaño definido.

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: 

  If (cRazonCM Mod 2 <> 0) And (cRazonCM >= 3 And cRazonCM <= 15)  Then
   generar CM
End If
 

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:

Figura 2.4- Diagrama de Flujo

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?
Para que esto sea posible, debe existir un método genérico para rellenar los CM's y así es.

El Método.

Para rellenar un CM debemos seguir las siguientes reglas independientemente del tamaño:

  1. El número 1 se coloca SIEMPRE en la columna central de la última fila.

  2. Los siguientes números se colocan de forma secuencial, es decir, en el orden natural, a partir del 2 y hasta el último que será siempre, el resultado de multiplicar la razón por sí misma.

  3. Colocamos cada número siempre en la fila siguiente y en la siguiente columna, excepto el caso de la regla 5.

  4. Al aplicar la regla 3, si nos encontramos en la última fila, entonces la fila 1 es considerada como la siguiente fila. Del mismo modo, si nos encontramos en la última columna, la columna 1 se considera la siguiente columna.

  5. Como excepción a la regla 3, cuando el último número introducido es igual a la razón o múltiplo de ella, entonces el siguiente número se coloca en la fila anterior y en la misma columna.

  6. Para la regla 5, si nos encontramos en la primera fila, la última fila corresponde a la fila anterior.

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í:

  Private Sub btnSi_Click()

Dim
cRazonCM As Integer

cRazonCM = InputBox("¿De que tamaño quieres el Cuadrado Mágico?." & Chr(13) & "(Debe ser un número_ impar entre 3 y 15 inclusive)", "Generador de Cuadrados Mágicos")

If (
cRazonCM Mod 2 <> 0) And (cRazonCM >= 3 And cRazonCM <= 15) Then
   
GeneraCM
End If

End Sub

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.
A simple vista sabemos que se van a necesitar varias líneas de código, las cuales, sin problema, podemos colocar dentro de la estructura de control If...Then, pero vamos a utilizar una de las características de Vb, los procedimientos Sub

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.
Aunque en nuestra aplicación el código para generar el CM sólo se va a ejecutar una vez, vamos a crear un procedimiento más bien, por razones de aprendizaje y claridad que por necesidad. A nuestro procedimiento lo llamaremos GeneraCM y para crearlo, lo único que tenemos que hacer es, en el editor de código, situarnos al final de cualquier función o procedimiento existente y teclear:

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:

  • Call Nombre_del_procedimiento [(Parámetro1[, Parámetro2,...Parámetron])]

  • Nombre_del_procedimiento [Parámetro1[, Parámetro2,...Parámetron]]

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:

  • por valor

  • por referencia

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:

  Sub GeneraCM (pcRazonCM As Integer)

End Sub
 

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:

  • Dim Alumnos(45) As String - define una matriz unidimensional de 46 elementos del tipo String

  • Dim dias(11) As Integer - define una matriz unidimensional de 12 elementos del tipo Integer

  • Dim meses(1 To 12) As Integer - define una matriz unidimensional de 12 elementos del tipo Integer especificando el límite inferior igual a 1

  • Dim CuadradoMágico() As Integer - define una matriz dinámica del tipo Integer.

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:

  Sub GeneraCM (pcRazonCM As Integer)

CuadradoMagico() As Integer
Redim
CuadradoMagico(pcRazonCM, pcRazonCM)


End Sub
 

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:

  For contador = valor_inicial To valor_final [Step incremento|decremento]
    grupo de instrucciones que componen la iteración
Next [contador]

y su explicación es como sigue:

Figura 2.5
  • Cuando Vb se encuentra con un bucle For... Next, inicializa la variable de control, mejor conocida como contador y le asigna el valor_inicial

  • Si el valor del contador es menor que el valor_final, entonces ejecuta el grupo de instrucciones dentro del bucle e incrementa el contador el valor incremento si existe o en 1 si no existe un incremento. y vuelve al principio del bucle.

  • Si el valor del contador es mayor que el valor_final, entonces se sale del bucle y el programa continúa con las líneas de código que siguientes al final del bucle (línea Next)

Luego, para nuestro código tomaremos los siguientes valores:

  • valor_inicial = 1

  • valor_final = pcRazonCM x pcRazonCM

  • incremento = 1 (predeterminado)

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á:

  For n = 1 To pcRazonCM * pcRazonCM
   
Cuerpo del bucle
Next

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:

  1. El número 1 se coloca SIEMPRE en la columna central de la última fila.

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í:

  Sub GeneraCM(pcRazonCM As Integer)

Dim
CuadradoMagico() As Integer
Dim
nFila As Integer, nColumna As Integer, n As Integer
Redim
CuadradoMagico(pcRazonCM, pcRazonCM)

nFila = pcRazonCM
nColumna = pcRazonCM / 2 + 1

For
n = 1 To pcRazonCM * pcRazonCM
   
Cuerpo del bucle
Next

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

  If n Mod pcRazonCM = 0 Then
     'Acciones a ejecutar si n es múltiplo de pcRazonCM
Else
     'Acciones a ejecutar si n NO es múltiplo de pcRazonCM
End If

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:

  If n Mod pcRazonCM = 0 Then
     'Acciones a ejecutar si n es múltiplo de pcRazonCM
    
If nFila = 1 Then
         
nFila = pcRazonCM
     Else
         
nFila = nFila - 1
     End if

Else
     'Acciones a ejecutar si n NO es múltiplo de pcRazonCM
End If

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:

  1. Escribe el código para las acciones a ejecutar si n NO es múltiplo de pcRazonCM, de manera que cumpla con el método de relleno de CM's.
  2. Comprueba las líneas de código escritas hasta ahora, aunque el programa funciona, existe un error que probablemente ya has detectado. Si no es así, trata de encontrarlo y una vez que lo encuentres, documéntalo y propón la solución.
  3. Una vez terminado y comprobado el código, guarda los cambios y posteriormente envíame por e-mail tu proyecto y la respuesta al número 2. Si no sabes como hacerlo pulsa aquí para las instrucciones detalladas.

Si consideras que ya estás preparado, puedes acceder al examen de la Lección II



Hit Counter