ALICIA ORDOVÁS SANZ G-10 P-15 El objetivo de esta práctica es diseñar un algoritmo que permita efectuar una versión del juego de la vida. Es un juego de cero jugadores. Se hace uso de las Unidades Estándar Crt y System. La unidad Crt implementa un conjunto de potentes rutinas que proporcionan un control completo de todas las características del PC.En esta práctica se han usado las siguientes: - ClrScr (proc) -> Borra la pantalla y devuelve el cursor a la esquina superior izquierda. - GotoXY (proc) -> Mueve el cursor a las coordenadas dadas dentro de la pantalla. - ReadKey (func) -> Lee un carácter del teclado. - Textcolor (proc) -> Selecciona el color de caracteres de primer plano. Colores de 0 a 15. - Delay (proc) -> Pausa la ejecución un número de milisegundos especificado. - DelLine (proc) -> Borra la línea que contiene al cursor. La Unidad System es la librería en tiempo de ejecución de Turbo Pascal, y se usa de forma automática, no es necesaria declararla en la claúsula Uses.Aquí se ha hecho uso de las siguientes: - IOResult (func) -> Devuelve el estado de la última operación de E/S realizada. - Sentencias de E/S (proc) -> read/readln write/writeln. - Randomize (proc) -> Inicializa el generador de números aleatorios. - Random (func) -> Devuelve un número aleatorio. - UpCase (func) -> Convierte un carácter a mayúscula. - Inc (proc) -> incrementa una variable. También se usa la directiva al compilador {$I}. Se activan con (+) y se desactivan con (-). Para que el programa detecte las entradas/salidas erróneas y no actúe ante un error y IOResult para lograr la robustez de los datos. Se ha definido una constante: max = 20-> es el tamaño máximo permitido para el tablero de juego. En la sección TYPE, se ha definido el vector multidimensional Ttablero, cuyas dimensiones máximas son [1..max, 1..max], y cuyo tipo de dato es byte. El programa tiene un menú con cuatro opciones distintas. Para poder ejecutar cada opción, se han definido una serie de funciones y procedimientos y así lograr el objetivo propuesto. - FUNCTION Menu:integer -> Esta función dibuja por pantalla el menú de juego, y devuelve la opción elegida por el usuario, que es un dato de tipo entero. Para pedir la opción que desea ejecutar, se hace uso de la directiva al compilador {$I} y de la función IOResult para dar robustez a los datos y detectar entradas/salidas erróneas. También se usan los procedimientos gotoxy, delay y delLine. El bucle se repite hasta que la opción elegida es correcta (1-4) La primera opción del menú es GENERAR MUNDO ALEATORIO. Aquí el usuario tiene que introducir el tamaño del tablero entre 4-20 casillas y la probabilidad, entre 1-100 (no incluyo el 0 porque me daba problemas, para la siguiente entrega lo mejoraré) de que cada casilla esté viva al inicio del juego. Luego hay que generar el tablero aleatoriamente [matriz de dos dimensiones]. Hay que tener en cuenta que si el número aleatorio obtenido es menor o igual que la probabilidad introducida, la célula estará encendida. Para ello se han definido: - FUNCTION Dimension_Tablero:integer -> Se ha elegido una función porque quiero que me devuelva el número de casillas del tablero que ha elegido el usuario, que es un dato de tipo entero. Al pedir el tamaño del tablero se hace uso de la directiva al compilador {$I} y de la función IOResult. También se utiliza el procedimiento ClrScr, delay,delLine y gotoxy. El bucle se repite hasta que la dimensión del tablero esté comprendida entre 4-20. - FUNCTION Probabilidad:integer -> Función que pregunta al usuario la probabilidad de que cada casilla esté viva al inicio del juego, y devuelve el valor de la probabilidad elegido por el usuario (valor comprendido entre 1 y 100). El valor devuelto es un dato de tipo entero. Para detectar entradas/salidas erróneas y dar robustez a los datos se utiliza {$I} y IOResult. También se hace uso de los procedimientos ClrScr,gotoxy y delay para mostrar los mensajes por pantalla. La pregunta se repite hasta que no se detecten errores y el valor introducido esté entre 1 y 100. - PROCEDURE Inicializar (var tab:Ttablero; num_cas:integer) -> Procedimiento que inicializa las casillas del tablero a cero. En unas ocasiones se utilizará tab_i(tablero original) y en otras tab_f( variable auxilar). Se utilizan dos bucles FOR, uno para recorrer las filas y otro para recorrer las columnas. - PROCEDURE Rellenar_Tablero (var tab_i:Ttablero; num_cas:integer;prob:integer) -> Procedimiento para rellenar las casillas del tablero de juego. No devuelve ningún valor. De las variables que se le pasan como parámetros, tab_i es una variable de salida y num_cas y prob son variables de entrada, ya que solo se necesitan para leer la información que nontienen. Se llama al procedimiento Inicializar, para rellenar el tablero inicial a 0. Luego, un bucle FOR para recorrer el tablero desde la fila y columna 2 hasta la número de casillas elegidas - 1, ya que los bordes están siempre apagados y por tanto con 0. En este segundo bucle FOR se saca un número aleatorio entre 0 y 1 y se compara con la probabilidad introducida por el usuario. Si el número es menor o igual a la probabilidad, en la casilla correspondiente el tablero se pone un 1 [tab_i[f,c]=1]. - PROCEDURE Mostrar_Tablero (tab_i:Ttablero; num_cas:integer) -> Procedimiento que muestra por pantalla el tablero de juego. Los parámetros utilizados son de entrada, solo las necesito para leer su información y poder mostrarla por pantalla. Se usan dos bucles FOR para recorrer las filas y columnas. Se hace uso del procedimiento ClrScr,gotoxy y textcolor para que muestre por pantalla en verde si están apagadas(0), y en rojo, si están encendidas(1). - PROCEDURE Generar_Mundo_Aleatorio (var tab_i: Ttablero; var num_cas:integer; prob:integer) -> Este procedimiento ejecuta la opción 1 del menú de juego. En el se hace uso de los procedimientos definidos anteriormente. tab_i es una variable de entrada/salida. num_cas es de salida, ya que se rellena dentro de este procedimiento, y se va a usar a lo largo de todo el programa. prob es de entrada, solo se necesita para leer la información que contiene. Para que finalice esta opción,se hace uso de la función readkey para regresar al menú de juego. A continuación se definen las funciones y procedimientos necesarios para poder ejecutar la opción 2 del menú: EJECUCIÓN. En esta opción se le pide al usuario el número de turnos a ejecutar, se le pregunta si desea cambiar las reglas de juego o dejar las que salen por defecto, y si el modo de ejecución lo desea paso a paso (muestra tablero en cada turno) o sólo mostrar el resultado final (muestra el último turno). Para poder ejecutar esto se han definido: - FUNCTION Num_Turnos:integer -> Es una función porque quiero que me devuelva el número de turnos elegidos por el usuario, que es un dato de tipo entero. Si el turno elegido = 0 se vuelve al menú principal: Como me daba problemas, lo he excluido y lo mejoraré para la siguiente entrega. Se hace uso de la directiva {$I} y IOResult para detectar errores y dar robustez. También se usan los procedimientos ClrScr, gotoxy, delay y DelLine. - PROCEDURE Cambio_Reglas (var x,y,z:integer) -> Las variables que se le pasa al procedimiento como parámetros son de entrada/salida, ya que leo lo que contienen y lo modifico. Se hace uso de los procedimientos Clrscr, gotoxy, delay y delLine. Para validar los datos y comprobar que no hay error se usa la función IOResult y la directiva {$I}. Para introducir los valores de x,y,z se hace uso de la estructura REPEAT...UNTIL. - FUNCTION Modo_Ejecución:char -> Función porque me devuelve el valor de la respuesta elegida, que es un dato de tipo caracter, ya que hasta que no se pulsa P (para ejecutarlo paso a paso) o R (para mostrar solo el resultado) no continúa. Se hace uso de la función upcase y readkey, para que transforme la respuesta introducida a mayúsculas y la lea. - PROCEDURE Copia (var tab_i:Ttablero; tab_f:Ttablero; num_cas:integer) -> Este procedimiento copia el tablero de juego y poder ir modificándolo en cada turno. tab_i es variable de salida, ya que se va modificando en cada turno, y tab_f es de entrada, ya que solo la necesito para leer su información. num_cas es de entrada, se leen las casillas y se copian. Se usan dos bucles FOR para copiar el tablero por filas y columnas. El resultado es copiar tab_f sobre tab_i. - PROCEDURE Juego (var tab_i:Ttablero; tab_f:Ttablero; num_cas,turno,x,y,z:integer;modo:char) -> tab_i es una variable de salida, porque es la que se va modificando en cada turno, tab_f es de entrada y es la variable auxiliar para decirle el estado de la siguiente jugada. El resto también son de entrada porque solo se leen, no se modifican.Primero se llama al procedimiento Inicializar, en este caso se inicializa tab_f, no tab_i, que en este caso es la original. Dentro de este procedure, se definen las variables f,c y t que son los contadores de los bucles FOR para las filas, columnas y turnos. También se crea la variable vivas, que cuenta las células que están encendidas y a, que es para utilizar la función Readlkey. Se recorre el tab_i mirando en cada casilla sus ocho vecinas, y se van contando las encendidas. Aquí se hace uso del procedimiento Inc, para ir incrementando la variable vivas. Y dependiendo del modo de ejecución elegido, se muestra el resultado de una forma u otra. Para mostrar los mensajes por pantalla se hace uso del procedimiento gotoxy. - PROCEDURE Ejecución (var tab_i:Ttablero; tab_f:Ttablero; turno,num_cas:integer) -> Este procedimiento lleva acabo la segunda opción del menú de juego. tab_i es variable de entrada/salida: se lee su información y se modifica, y el resto son de entrada, ya que solo se necesitan para leer su contenido.Aquí inicializo las variables del juego por defecto, porque sino se quieren modificas las reglas, se juega con éstas. En este procedimiento se llama a las funciones/procedimientos descritos anteriormente. Ahora hay que poder ejecutar la tercera opción del menú de juego. Para ello se ha definido una función y un procedimiento que ejecuta la opción 3: - FUNCTION Cargar_Mundo (nombreFich:string; var num_cas:integer):string -> num_cas es una variable de entrada/salida, el número de líneas del fichero será la dimensión del tablero. - PROCEDURE Cargar_Estado_Inicial (var tab_i:Ttablero;var num_cas:integer) -> las dos son variables de entrada/ salida, ya que las leo pero también se modifican. Cuando se llama a la función Cargar_Mundo, le he metido la ruta c:\mundo.txt porque yo lo tenía guardado aquí. De este archivo he borrado la primera línea, así solo aparece el tablero de juego. En este procedimiento también he introducido val(__, __, __) donde se lee el string, se transforma a número y lo guardo en el tablero. Se usa la función readkey para salir. Y finalmente, para poder ejecutar la cuarta opción del menú se ha creado el PROCEDURE Salir -> Al ejecutar esta opción se sale del programa. No devuelve ningún valor, se muestra por pantalla un mensaje de de despedida, y hasta que no se pulsa una tecla (uso de la función ReadKey) no finaliza el programa. También se usa el procedimiento ClrScr y gotoxy. Por último se ha definido el PROCEDURE Inicio -> Es el procedimiento principal del programa, donde dependiendo de la opción elegida por el usuario se ejecutará una opción u otra. Sólo se sale del programa si se pulsa la opción 4, y para el resto de opciones, cuando se acaban de ejecutar se regresa al menú de juego para que el usuario vuelva a elegir la instrucción que desea llevar a cabo. En el programa principal se limpia la pantalla con el procedure ClrScr y se usa el procedimiento Randomize para inicializar el generador de números aleatorios. Finalmente se hace la llamada al procedure inicio que es el que ejecuta todas las opciones del juego. ---------------------------- (añadido tras someter) ---------------------------- 23:16:38 11/12/09 -> Segun los datos introducidos los ficheros son: G10P15D2 -> Los autores del trabajo son: Ordovás Sanz, Alicia Nombres originales de los archivos entregados -> JUEGO_VIDA.PAS, Juego_De_La_Vida.txt