|
|
Adolfo Di Mare
Eduardo Oviedo |
Se presenta el Tipo Abstracto de Datos TTurtle que
implementa las operaciones de la tortuga LOGO en el ámbito
del lenguaje Turbo Pascal v5.0. Al estudiante conocedor del
lenguaje basado en listas LOGO, el uso de Turtle.pas le
facilita el aprender tanto Pascal como el uso de las
técnicas de Programación Estructurada y de
Abstracción de Datos que permite Turbo Pascal. La unidad
Turtle.pas no hace usdo de las facilidades de
Programación Orientada a Objetos de Turbo Pascal v5.5.
|
In this paper we explain the TTurtle Abstract Data
Type, which implements the LOGO turtle using Turbo Pascal v5.0.
Use of this ADT allows students with knowledge of LOGO (a list
based language) to learn Pascal rapidly, as well as the Structured
Programming and the Abstract Data Types techniques allowed by
Turbo Pascal. Using Turtle.pas does not require the
Object Oriented features found in version 5.5 of Turbo
Pascal.
|
Sin embargo, la creciente demanda de servicios de computación requiere del entrenamiento de cada vez más programadores de aplicaciones computacionales. Como las aplicaciones se escriben usando lenguages procedimentales y lenguajes orientados a objetos como Pascal, es muy útil contar con herramientas que permitan convertir a un programador LOGO en un programador de aplicaciones. La unidad Turbo Pascal Turtle.pas descrita en este artículo implementa la mayoría de las primitivas de graficación de LOGO, lo que permite a los estudiantes conocedores de LOGO aprender rápidamente tanto el lenguage Pascal como el uso de abstracción de procedimientos y de abstracción de datos.
En este artículo se discute el Tipo Abstracto de Datos
(ADT) TTurtle
, que implementa la tortuga LOGO en el
ámbito de Turbo Pascal, en versiones posteriores a la
versión 4.0. Se incluyen comentarios de la
implementación de este ADT, sus cualidades y sus
restricciones. También se comenta brevemente la experiencia
obtenida en el uso de este ADT en el segundo curso de
programación de la Escuela de Ciencias de la
Computación e Informática
(ECCI) de la Universidad
de Costa Rica, que recibe a estudiantes que han aprendido
LOGO como su primer lenguage de computación.
La tortuga LOGO se desplaza sobre un sistema de coordenadas
cartesianas superimpuesto a la pantalla, donde el punto
(0,0)
corresponde al centro de la pantalla. La
resolución de gráficación de la pantalla LOGO
es de 320×200
pixeles. Este sistema cartesiano tiene la forma de un toro
geométrico, pues cuando la tortuga se sale por un lado de
la pantalla aparece por el otro, a menos que se le indique lo
contrario. Los límites del plano en que se mueve la tortuga
LOGO son:
x IN [-159..159]
y
y IN [-99..99]
El lugar hacia el cual se va a desplazar la tortuga depende de su
rumbo, que es un número en el intervalo
[0..360]
, que representa el ángulo hacia donde
está mirando la tortuga. El programador puede cambiar el
rumbo de la tortuga, para que se mueva en la pantalla en cualquier
dirección. Si se le indica a la tortuga que se mueva hacia
adelante o hacia atrás, lo hará en la
dirección que indica su rumbo.
Para dibujar, la tortuga puede aceptar órdenes de programación que cambian el estado de su pluma que está colocada en su punto central. El programador LOGO puede crear gráficas multicolores dándole órdenes a la tortuga.
El programador LOGO cuenta con operaciones que le permiten cambiar la forma de la tortuga. También es posible ordenarle a la tortuga que se haga invisible, con lo que pueden crearse efectos interesantes al dibujar. Es posible desactivar la pluma de la tortuga de forma que cuando se desplace de un lugar a otro no dibuje. También es factible poner la pluma en modo de borrar, con lo que la tortuga prodría deshacer todo lo que ha dibujado.
Las operaciones más importantes que tiene una tortuga son: Visible, Invisible, Activar la Pluma, Desactivar la Pluma, Moverse hacia Adelante, Moverse hacia Atrás y Cambiar el Rumbo.
Push()
y
Pop()
, las que pueden ser aplicadas a una variable de
tipo pila.
Todos los procedimientos (operaciones) que actúan sobre una
variable de tipo TTurtle
tienen el siguiente
encabezado:
OPERACION ( {SELF} VAR T : TTurtle [, parámetros]);
Aquí, [parámetros]
son la variables que
se necesitan para efectuar la operación. Por ejemplo, para
ordenarle a la torturga "t1
" que avance
10
posiciones hacia adelante, el programador debe
invocar a la operación
Turtle.Forwd(t1, 10)
.
Al implementar el ADT TTurtle
se usaron los nombres
de operaciones especificados en los gráficos de tortuga de
Turbo Pascal, en su versión 3.0. Aunque pudo haberse
utilizado como base los nombres de la tortuga Logo Writer, o de
cualquier otra versión de LOGO, se escogió usar los
primeros pues es relativamente fácil obtener muchos
programas Turbo Pascal de ejemplo.
A diferencia de las operaciones de la tortuga Turbo Pascal, el
programador debe incluir como argumento a la variable de tipo
TTurtle
cuando invoca cada una de las operaciones de
Turtle.pas. En Turbo Pascal el programador sólo
cuenta con una tortuga, mientras que Turtle.pas le
permite al programador tener hasta 255
tortugas
diferentes en la pantalla (LOGO permite hasta cuatro). Las
operaciones implementadas en Turtle.pas son las
siguientes:
PROCEDURE Forwd (VAR t: TTurtle; d: INTEGER); PROCEDURE Back (VAR t: TTurtle; d: INTEGER); PROCEDURE Home (VAR t: TTurtle); PROCEDURE TurnRight (VAR t: TTurtle; a: INTEGER); PROCEDURE TurnLeft (VAR t: TTurtle; a: INTEGER);
PROCEDURE PenUp (VAR t: TTurtle); PROCEDURE PenDown (VAR t: TTurtle); PROCEDURE ShowTurtle (VAR t: TTurtle); PROCEDURE HideTurtle (VAR t: TTurtle); PROCEDURE EraserUp (VAR t: TTurtle); PROCEDURE EraserDown (VAR t: TTurtle); PROCEDURE SetPenColor (VAR t: TTurtle; c: WORD); PROCEDURE Paint (VAR t: TTurtle); PROCEDURE SetX (VAR t: TTurtle; x: INTEGER); PROCEDURE SetY (VAR t: TTurtle; y: INTEGER); PROCEDURE SetPosition (VAR t: TTurtle; x,y: INTEGER); PROCEDURE SetHome (VAR t: TTurtle; x,y: INTEGER); PROCEDURE SetHeading (VAR t: TTurtle; r: INTEGER); PROCEDURE SetIcon (VAR t: TTurtle; p: TIcon);
FUNCTION Color (VAR t: TTurtle): WORD; FUNCTION Pen (VAR t: TTurtle): BOOLEAN; FUNCTION Erase (VAR t: TTurtle): BOOLEAN; FUNCTION TurtleThere (VAR t: TTurtle): BOOLEAN; FUNCTION XCor (VAR t: TTurtle): INTEGER; FUNCTION YCor (VAR t: TTurtle): INTEGER; FUNCTION Heading (VAR t: TTurtle): INTEGER; FUNCTION Towards (VAR t: TTurtle; x,y:INTEGER): INTEGER; PROCEDURE WriteText (VAR t: TTurtle; s: STRING; f: WORD);
PROCEDURE Init (VAR t: TTurtle); PROCEDURE Clear (VAR t: TTurtle); PROCEDURE Done (VAR t: TTurtle); PROCEDURE Copy (VAR x: TTurtle; VAR y: TTurtle); PROCEDURE Move (VAR x: TTurtle; VAR y: TTurtle); FUNCTION Equal (VAR x: TTurtle; VAR y: TTurtle) : BOOLEAN; PROCEDURE Load (VAR t: TTurtle; VAR F: FILE); PROCEDURE Store (VAR t: TTurtle; VAR F: FILE);
USES
en su programa de la siguiente manera:
USES Turtle {...otras unidades...};
Como para los computadores IBM/pc compatibles existen muchos tipos de pantalla, el código de inicialización de Turtle.pas se encarga de activar el manejador de pantallas adecuado para la pantalla en que se corre el programa. Entre los tipos de pantalla en que puede ser usado Turtle.pas están las pantallas CGA, EGA, VGA, Hércules y PC3270.
En la implementación de Turtle.pas se hace necesario ajustar la resolución gráfica de la pantalla a las coordenadas cartesianas que utiliza la tortuga, de forma que el aspecto del dibujo producido en cada tipo de pantalla sea el mismo. Para evitar complicar mucho la programación, los procedimientos que cambian de coordenadas cartesianas a las coordenadas de la tarjeta gráfica del computador hacen uso de aritmética de punto flotante, lo que en a veces le resta velocidad a las operaciones de dibujo.
Si no se usara aritmética de punto flotante, entonces al hacer curvas con la tortuga no se obtendría una línea continua, debido a los errores de redondeo por usar variables enteras: cuanto más cerrada fuera la curva, más separados quedarían sus puntos. Sin embargo, como se usan aritmética de punto flotante para calcular el movimiento de la tortuga, cuando se hacen curvas muy cerradas la velocidad de la tortuga se reduce notablemente.
Uno de los problemas que se no se ha resuelto es el evitar que cuando una tortuga pase sobre otra la borre o le sobre escriba. Si el programador experimenta problemas a este respecto, deberá ocultar las otras tortugas mientras dibuja con alguna de ellas. En la práctica no conviene usar a más de cincuenta tortugas simultánamente en procesadores INTEL 8088 de 4.77 MHz.
El ícono de la tortuga se almacena en memoria
dinámica pues su tamaño depende de la
resolución de la tarjeta de graficación. Para el
programador un ícono es una matriz de tamaño
8×8
, que está llena de caracteres, en los que
únicamente uno puede representar un pixel vacío (lo
usual es usar el caracter blanco como pixel vacío). De esta
manera, para el programador es sencillo crear nuevos íconos
con un editor de textos para usarlos inmediatamente en su
programa. Si la matriz está llena de puros pixeles
vacíos, entonces el ícono de la tortuga es el
círculo que se usa al inicializarla. Para guardar el
ícono de la tortuga en el disco basta almacenar la
correspondiente matriz de caracteres. El siguiente es un ejemplo
de un ícono.
TYPE TIcon = RECORD vacio : CHAR; icon : ARRAY[1..8] OF STRING[8]; END; CONST Icono_Letra_E : TIcon = (vacio : ' '; { Pixel vacío } icon : ('XXXXXXXX'), ('XXXXXXXX'), ('XXXX '), ('XXXXXXXX'), ('XXXXXXXX'), ('XXXX '), ('XXXXXXXX'), ('XXXXXXXX') );
Para desplegar el ícono de la tortuga es necesario traducir
la matriz 8×8
a la resolución de la
tarjeta graficadora del computador. Por ejemplo, si la
resolución de la tarjeta es de 640×200
, y
como la de LOGO es 320×200
, entonces para
adaptar el dibujo a la tarjeta deberá desplegarse al doble
de ancho (pues 640÷320 = 2
)
pero al mismo alto (200÷200 = 1)
. El
ícono tendrá una dimensión de
(8*2)×(8*1) = 16×8
, y aunque sea
en realidad más ancho que alto, su aspecto al ser
desplegado será el adecuado.
Debido a la forma en que está implementado el procedimiento
Graph.FloodFill()
de la biblioteca BGI, la
operación Paint()
de Turtle.pas
requiere que la región a colorear esté bordeada por
una línea del mismo color, mientras que en LOGO basta que
la región a colorear esté delimitada por regiones de
otro color. En la práctica, esta restricción no ha
causado mayor problema.
Turtle.pas también le permite al programador
imprimir mensajes en pantalla por medio del procedimiento
WriteText(t,s,fuente)
. También se han incluido
operaciones para examinar el estado de la tortuga, como su
posición actual, rumbo, color, estado de la pluma, etc.
La tortuga no se mueve usando los métodos que es usual
encontrar en las bibliotecas de gráficos. En lugar de
definir el punto (x,y)
de destino de la tortuga, el
programador define el rumbo y la distancia a recorrer por la
tortuga. Por eso es necesario cambiar las coordenadas polares,
usadas por el programador de la tortuga, a las cartesianas usadas
por la biblioteca de graficación.
Si la tortuga tiene un rumbo de "ß" grados, y está en
el punto "(x1,y1)
", y debe desplazarse una distancia
"d
", y al recorrer esa distancia d estará en
el punto "(x2,y2)
", donde se cumple la siguiente
relación entre los dos puntos:
x2 = d * cos(ß)
y
y2 = d * sen(ß)
Para implementar el que la pantalla sea un toro geométrico
para la tortuga debe calcularse cuál será el punto
(x2,y2)
de destino, en aquellos casos en que la
tortuga se saldría de la pantalla. Si la distancia de
movimiento es muy grande, puede que incluso la tortuga se salga
varias veces de la pantalla. Para solucionar este problema se hizo
lo siguiente. Primero se calcula el punto (x2,y2)
a
el cual debe desplazarse la tortuga. Si el punto ya está en
la pantalla entonces no hay que hacer nada más. Si el punto
(x2,y2)
no está en la pantalla lo que se hace
es dividir sucesivamente la distancia entre 2 hasta que el punto
(x2,y2)
esté en la pantalla. Una vez hecho
esto se hace avanzar la tortuga hasta el punto
(x2,y2)
. Se repite de nuevo el mismo proceso de
división hasta que la tortuga quede en la orilla de la
pantalla. Cuando la tortuga está en la orilla, entonces lo
que se hace es pasarla al lado contrario de la pantalla.
Para evitar borrar los objetos que hay debajo de la figura de la
tortuga se usó el modo de escritura llamado
XORPut
de la biblioteca BGI, que lo que hace es
colocar una figura sobre un fondo de manera transparente, de forma
que al colocar la figura lo que está debajo se puede seguir
viendo, aunque en video invertido. Por ejemplo, si sobre un fondo
blanco se dibuja una figura negra, al colocarle otra encima por
medio XORPut
, entonces la figura original se
verá de color negro. Una ventaja adicional de usar
XORPut
es que permite restaurar la figura
sobreescrita, lo que es una gran ventaja para implementar la
animación de la tortuga. El problema es que cuando dos
tortugas usan el mismo ícono y una se coloca una encima de
la otra las dos desaparecen de la pantalla.
En algunos programas el uso de los procedimientos de la biblioteca de graficación BGI, Graph.tpu, ha causado molestias menores. Aunque es válido mezclar en el mismo programa operaciones de Graph.tpu y Turtle.pas, en la práctica se trata de no hacerlo para lograr programas más simples de entender. Sin embargo, al usar sólo Turtle.tpu el programador tiene mucho menos control de los gráficos que si usa Graph.tpu, por lo que no puede considerarse a Turtle.pas como un sustituto adecuado de Graph.tpu.
En el futuro se tratará de ampliar las facilidades ofrecidas por Turtle.pas, al conocer mejor la opinión de estudiantes y profesores que la utilicen.
Init()
,
Clear()
y Done()
. Los encabezados para
estos procedimientos son los siguientes:
Init (VAR t: TTurtle); { Constructor } Clear(VAR t: TTurtle); { Reinicializador } Done (VAR t: TTurtle); { Destructor }
Al invocar a la operación Turtle.Init(t)
el
programador inicializa la variable "t
", de tipo
TTurtle
. No es correcto operarar sobre una tortuga
que no haya sido inicializada por medio de Init()
. La
operación Turtle.Done(t)
es el destructor del
ADT tortuga, y su función es retornar al sistema toda la
memoria dinámica asociada a la variable "t
".
Siempre que se ejecuta un Init()
también
deberá ejecutarse el Done()
correspondiente,
pues de lo contrario el programa no será correcto.
La función Clear()
se encarga de reinicializar
a una variable de tipo TTurtle
, y la deja en el
estado que originalmente la puso la operación
Init()
. Done()
en general se encarga de
devolver la memoria dinámica asociada a una variable de
tipo TTurtle
.
Al usar tipos abstractos de datos el programador debe respetar las reglas de ocultamiento de datos. Esto quiere decir que aunque un ADT es un registro Pascal, el programador que usa al ADT no debe accesar los campos de ese registro.
En la implementación de Turtle.pas se usa un truco
para que el programador sepa si está accesando las partes
privadas del ADT, que consiste en incluir un único campo en
el tipo TTurtle
llamado Rep
. Si el
programador en algún momento usa una variable en que
aparece la palabra Rep
, entonces sabrá que
está violando el ocultamiento de datos. Por ejemplo, si
"t
" es una variable de tipo TTurtle
,
aunque el compilador no reporta un error de sintáxis al
usar "t.Rep.color
", el programdor sabrá que no
está usando adecuadamente la variable. El truco para
simular ocultamiento de datos en Turbo Pascal es usar una
declaración de tipos de tipos semejante a la siguiente:
{[])==========================([]} {[]} TYPE {[]} {[]} Rep_Turtle = RECORD {[]} {[]} color : WORD; {[]} {[]} { ..MAS CAMPOS.. } {[]} {[]} END; {[]} {[]} TTurtle = RECORD {[]} {[]} Rep : Rep_Turtle; {[]} {[]} END; {[]} {[])==========================([]}
Todos las operaciones de la tortuga requieren variables de tipo
TTurtle
, y nunca debe usarse el tipo
Rep_Turtle
. Nunca es necesario saber cuáles
son los campos de una tortuga: basta usar sus operaciones.
Otras operaciones importantes son
Copy(x,y)
y Move(x,y)
, que se encargan
de copiar la variable de tipo tortuga "y
" sobre
"x
". La diferencia entre estas dos operaciones es que
para muchos ADTs la operación Move()
toma
menos tiempo de ejecución que Copy()
. Pero hay
que tener en cuenta que Move(x,y)
siempre deja a la
variable "y" reinicializada, como si se hubiera ejecutado la
operación Clear(y)
.
Las operaciones Load()
y Store()
permiten almacenar a una variable tipo tortuga en un archivo Turbo
Pascal sin tipo. De esta manera el programador puede grabar en
disco el estado de la tortuga.
En el programa EX_01.pas se muestra el el uso de un vector con una cantidad grande de tortugas, en las que se ejercitan las operaciones de uso más común de Turtle.pas. Este es uno de los programas de ejemplo que se distribuyen en el diskette que contiene a Turtle.tpu.
EX_01.pas forma un círculo utilizando treinta y seis tortugas, y luego las hace desplazarse hacia la esquina superior izquierda de la pantalla en con un rumbo aleatorio.
El programa EX_02.pas muestra como es posible cambiar el ícono de cuatro tortugas, y para luego hacer que se persigan unas a otras.
Sin embargo, los estudiantes que han usado Turtle.pas se muestran inconformes con el desempeño del ADT tortuga, porque en general su accionar en un programa Turbo Pascal es muy lento: un programa LOGO equivalente es hasta el doble de rápido en las operaciones de graficación. Eventualmente se corregirá esta deficiencia, así como el que las tortugas se borren unas a otras, implementando Turtle.pas en lenguage de máquina o usando una biblioteca de gráficos más eficiente que la biblioteca BGI. Está en proyecto el usar a un tesiario de Licenciatura para que trabaje en esta dirección.
Además, se está pensando en implementar la nueva tortuga como una "Tortuga dinámica". La idea es que el estudiante pueda definir varias tortugas que se muevan en la pantalla de forma autónoma, mientras el programa principal realiza otras tareas. De esta manera será posible introducir a los estudiantes en el uso de programación concurrente en sus primeros años de estudio, con lo que se logrará aumentar al eficiencia de la asimilación de esta importante rama del conocimiento en Ciencias de la Computación.
El código completo de Turtle.pas se encuentra
disponible en Internet, en el archivo empacado
http:// www.di-mare.com
/adolfo/p/src/ turtle.zip
. Ahí hay
documentación más detallada sobre el uso de la
unidad Turtle.pas.
Esta investigación se realizó dentro del proyecto de investigación 326-89-019 "Estudios de la Tecnología de Programación por Objetos y C++", inscrito ante la Vicerrectoría de Investigación de la Universidad de Costa Rica. La Escuela de Ciencias de la Computación e Informática también ha aportado fondos para este trabajo.
[BI-88] | Borland International:
Turbo Pascal Reference Manual version 5.5,
Borland International, California (U.S.A.), 1988.
|
[DiM-88a] | Di Mare, Adolfo:
Convenciones de Programación para Pascal,
Revisión 2, Reporte técnico
ECCI-01-88, ECCI-UCR,
http:// www.di-mare.com /adolfo/p/ convpas.htm ,
1988.
|
[DiM-89] | Di Mare, Adolfo:
Abstracción de Datos en
Pascal, Reporte técnico ECCI-01-89,
ECCI-UCR, 1989.
|
[Pol-92] |
L.Pollet, Patrick (Dr):
Unit that allows turtle graphics in any BGI mode,
disponible por ftp anónimo en
ftp:// garbo.uwasa.fi /pc/turbopas/ turtle10.zip , 1992.
|
[-] | Resumen
|
[1] | Introducción
|
[2] | La Tortuga LOGO
|
[3] | Especificación de Turtle.pas
|
[4] | Implementación y limitaciones de Turtle.pas
|
[5] | Ejemplo de uso de Turtle.pas
|
[6] | Experiencia en el uso de Turtle.pas
|
[7] | Conclusiones
|
[8] | Reconocimientos
|
|
|
Bibliografía
|
|
Indice
|
|
Acerca de los autores
|
|
Acerca de este documento
|
|
Principio
Indice
Final
|
Adolfo Di Mare <adolfo@di-mare.com>
Eduardo Oviedo: fue estudiante del curso Programación II impartido por el profesor Adolfo Di Mare. Estuvo a cargo de realizar toda la implementación de Turtle.pas.
Referencia: | Di Mare, Adolfo & Oviedo, Eduardo:
Turtle: La Tortuga LOGO para Turbo
Pascal, Ponencia presentada en el
V Congreso Internacional de Logo, celebrado en
noviembre de 1991 en San José, Costa Rica,
Escuela de Ciencias de la Computación e Informática,
Universidad de Costa Rica;1991.
|
Internet: |
http://www.di-mare.com/adolfo/p/turtle.htm
http://www.di-mare.com/adolfo/p/src/turtle.zip
|
Autor: | Adolfo Di Mare
<adolfo@di-mare.com>
|
Contacto: | Apdo 4249-1000, San José Costa Rica Tel: (506) 207-4020 Fax: (506) 438-0139 |
Revisión: | ECCI-UCR, Febrero 1998
|
Visitantes: |
|
|