You are on page 1of 7

Ejemplo: Solucin de un Laberinto

Descripcin Se presenta un programa que resuelve laberintos en forma recursiva. El laberinto a resolver se representa mediante una matriz de nmeros enteros, y su configuracin est dada por la inicializacin que se haga a dicha matriz. Por esto, para cambiar el laberinto ser necesario cambiar el cdigo del programa. Una vez que se haya introducido el concepto de archivo ser posible ampliar este programa para que sea ms til, almacenando distintas configuraciones de laberinto en distintos archivos.

Diseo A continuacin se aplicar nuestra metodologa para la solucin de problemas para disear el programa mencionado. 1. Definicin del problema Conceptualizacin: El problema se ubica en un contexto en el que se debe buscar una solucin a un laberinto con una entrada y una salida, y con movimientos vlidos en cuatro direcciones (no diagonales). En el caso de este ejemplo, el contexto est limitado a una aplicacin de computador, en la que el laberinto est representado mediante una matriz de nmeros enteros. Objetivo: Partiendo de la entrada del laberinto, sealar una ruta que nos gue hasta la salida. Por ejemplo, dado el siguiente laberinto:

Una solucin que nos permitira alcanzar nuestro objetivo sera la ruta mostrada con asteriscos en la siguiente figura:

Descripcin general de la solucin: El problema se resolver haciendo uso de la recursividad. La solucin se basa en una tarea o funcin que se llamar recursivamente para intentar solucionar el laberinto a partir de una posicin particular. Desde cualquier lugar dentro del laberinto se intentar resolverlo primero intentando hacia izquierda, luego a la derecha, luego arriba y finalmente abajo. Para hacer estos intentos se emplear la funcin recursiva. El procedimiento parte de la posicin de entrada. Se utilizarn marcas que sern dejadas en el camino para no intentar por caminos por los que ya se pas y, en particular, no volver atrs salvo si se determina que no hay solucin por el camino que se sigue hasta ahora. Elementos involucrados: No existen elementos externos involucrados en la bsqueda de la solucin. El nico elemento activo es el computador en s llevando a cabo su trabajo. En el problema participan tambin los siguientes elementos pasivos: la matriz que representa el laberinto la ubicacin de la entrada la ubicacin de la salida 2. Conceptualizacin de la solucin Variables: Como se mencion, el laberinto estar representado mediante una matriz de nmeros enteros: lab. Adems, la posicin de la entrada en el laberinto estar dada por las coordenadas dentro de la matriz, representadas por las variables x0, y0, para la fila y la columna, respectivamente. De manera similar, la posicin de la salida del laberinto se guardar en xf, yf Todas estas variables sern globales. Cada posicin de la matriz puede estar en uno de tres estados: parte del muro (ladrillo) camino libre no visitado camino libre visitado

En el programa en C, la declaracin de las variables y constantes globales se har de la siguiente manera: /* Constantes que definen la dimension del laberinto */ #define FILAS 13 #define COLUMNAS 21 /* Caracteres que se almacenan en las posiciones del laberinto: */

/* ASCII 219 es un cuadro relleno que se usa para las paredes */ /* ' ' es un espacio en blanco, para los caminos libres */ /* '*' es la marca que senala las posiciones visitadas (camino) */ #define L 219 #define E ' ' #define MARCA '*' /* Constantes logicas para valor de retorno de funciones */ #define TRUE 1 #define FALSE 0 /* Matriz global que representa el laberinto. En la inicializacion, */ /* L representa un ladrillo en la pared y E un espacio en blanco */ int lab[FILAS][COLUMNAS] = { { L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L }, { E, E, E, L, E, L, E, L, E, L, E, E, E, L, E, E, E, E, E, E, L }, { L, L, E, L, E, E, E, L, E, E, E, L, E, L, E, L, E, E, L, E, L }, { L, E, E, E, E, L, E, L, L, L, E, L, E, L, E, L, L, E, L, E, L }, { L, E, L, L, L, L, E, L, E, L, E, L, E, L, L, L, E, E, L, E, L }, { L, E, E, E, L, E, E, L, E, L, E, L, E, E, E, E, E, L, L, E, L }, { L, E, L, L, L, L, L, L, E, L, E, L, L, E, L, E, E, E, E, E, L }, { L, E, E, E, E, E, E, E, E, E, E, E, L, E, L, E, L, L, E, L, L }, { L, L, L, L, L, L, L, L, L, L, L, E, L, E, L, E, E, L, E, L, L }, { L, E, E, E, E, E, E, E, L, E, E, E, L, L, L, L, L, L, E, L, L }, { L, E, L, L, L, L, L, E, E, E, L, L, L, E, L, E, E, E, E, E, L }, { L, E, E, L, E, E, E, E, L, E, E, L, E, E, E, E, L, L, L, E, E }, { L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L, L } }; La inicializacin de la matriz que aqu se muestra corresponde al laberinto presentado en la figura del inicio. Los caminos estn formados de espacios libres (E's). Observe el contorno del laberinto, formado por L's, y los puntos de entrada y salida. En la implementacin de las distintas subtareas se hace uso de otras variables locales, propias de la funcin de cada subtarea. Descomposicin en Tareas: El problema global puede descomponerse en las siguientes tareas. Como las variables ms importantes se manejan en forma global, no es necesario pasarlas como parmetros. Este es el caso de la variable lab, la matriz que representa el laberinto. Cada una de las tareas aqu definidas se implementar como una funcin en el programa en C. Para una mejor comprensin, se incluye el cdigo en C que corresponde a cada una de estas funciones. valida Parmetros: fila y columna de la posicin Valor de retorno: valor booleano que indica si la posicin es vlida Descripcin: Esta funcin analiza una posicin dentro del laberinto, especificada por la fila y columna recibidas como parmetro, y deduce si es una posicin vlida para recorrer. Bsicamente debe verificar que no est fuera de los lmites del laberinto, que no se trate de una posicin en la que hay pared, y que no se trate de una posicin previamente visitada. Algoritmo: 1. Inicialmente resultado vale VERDADERO 2. Si la posicin dada est fuera del laberinto 2.1. Cambiar resultado a FALSO 3. Si la posicin dada es pared o ya fue visitada

3.1. Cambiar resultado a FALSO Cdigo en C: int valida(int f, int c) { int resultado = TRUE; /* Se supone inicialmente valida */ /* Controla si la posicion esta fuera del laberinto */ if ((f<0) || (f>=FILAS) || (c<0) || (c>=COLUMNAS)) resultado = FALSE; /* Controla si la posicion ya fue visitada o es muro */ if (lab[f][c] == MARCA || lab[f][c] == L) resultado = FALSE; return(resultado); } recorrer Parmetros: fila y columna (fil y col) desde donde se empieza el recorrido. Valor de retorno: TRUE o FALSE que indica si se logr resolver el laberinto o no. Descripcin: Tarea recursiva que recorre el laberinto a partir de una posicion dada por la fila y columna pasadas como parametro y devuelve un valor booleano que indica si se logro llegar a la salida. El caso base de la recursividad (condicion de termino) es que las coordenadas correspondan con la salida del laberinto. En caso contrario, se procede a marcar la casilla y a intentar en las distintas direcciones (izquierda, derecha, arriba y abajo), asegurandose primero que en esa direccion haya una casilla valida (no ladrillo, no fuera del laberinto y no visitada). En caso en que ninguna direccion nos lleva a la salida, se desmarca la casilla actual (pues se va a retroceder) y se devuelve falso como valor de retorno. Las marcas sirven tambin para senalar la ruta que conforma la solucion, una vez alcanzada. Algoritmo: 1. Inicialmente listo vale FALSO 2. Se marca la casilla 3. Si la posicin es el fin del laberinto 3.1. Retornar VERDADERO 4. Si no se ha solucionado (listo vale FALSO) y la posicin de la izquierda es vlida 4.1. Llamar a recorrer recursivamente con la casilla de la izquierda como parmetro y guardar valor de retorno en listo, para ver si se resolvi el laberinto a partir de ah. 5. Si no se ha solucionado (listo vale FALSO) y la posicin de la derecha es vlida 5.1. Llamar a recorrer recursivamente con la casilla de la derecha como parmetro y guardar valor de retorno en listo, para ver si se resolvi el laberinto a partir de ah. 6. Si no se ha solucionado (listo vale FALSO) y la posicin de arriba es vlida 6.1. Llamar a recorrer recursivamente con la casilla de arriba como parmetro y guardar valor de retorno en listo, para ver si se resolvi el laberinto a partir de ah. 7. Si no se ha solucionado (listo vale FALSO) y la posicin de abajo es vlida 7.1. Llamar a recorrer recursivamente con la casilla de abajo como parmetro y guardar valor de retorno en listo, para ver si se resolvi el laberinto a partir de ah. 8. Si no se logr resolver el laberinto en ninguna direccin (listo todava vale FALSO) 8.1. Quitar marca de la casilla (pues no formar parte del camino) 9. Retornar listo indicando si se pudo resolver o no el laberinto Cdigo en C: int recorrer(int fil, int col) {

int listo = FALSE; /* Indica si se ha encontrado la salida */ /* Se marca la casilla como visitada */ lab[fil][col] = MARCA; /* Se controla la condicion de termino de recursividad: */ /* " Llegamos a la salida? " */ if (fil == xf && col == yf) return(TRUE); if (!listo && valida(fil,col-1)) listo = recorre(fil,col-1); if (!listo && valida(fil,col+1)) listo = recorre(fil,col+1); if (!listo && valida(fil-1,col)) listo = recorre(fil-1,col); if (!listo && valida(fil+1,col)) listo = recorre(fil+1,col); /* Intento a la izquierda */ /* Intento a la derecha */ /* Intento hacia arriba */ /* Intento hacia abajo */

/* Si no se logro resolver el laberinto desde esta posicion, se */ /* desmarca la casilla pues no sera parte de la solucion. En este */ /* caso se retornara falso lo que provocara que se retroceda. */ if (!listo) lab[fil][col] = E; /* Se retorna TRUE/FALSE dependiendo de si se encontro solucion */ return(listo);

desplegar Parmetros: no tiene Valor de retorno: no tiene Descripcin: Despliega en la pantalla el laberinto Algoritmo: 1. Iterar i por todas las filas 1.1. Iterar j por todas las columnas 1.1.1. Desplegar posicin i,j 1.2. Cambiar de lnea pues termin una fila Cdigo en C: void desplegar() { int i, j; printf("\n"); for (i=0; i<FILAS; i++) { for (j=0; j<COLUMNAS; j++) { printf("%c", lab[i][j]); } printf("\n"); } return;

3. Especificacin del algoritmo El algoritmo principal debe llamar a la tarea que recorre el laberinto, especificando como posicin la entrada: ( x0 , y0 ). Antes y despus de la resolucin se despliega el laberinto. La segunda vez incluir el camino que forma la solucin (las posiciones que fueron marcadas y no desmarcadas posteriormente).

Algoritmo: 1. Desplegar el laberinto sin resolver 2. Recorrer desde la entrada del laberinto: ( x0 , y0 ) 3. Si no se pudo resolver 3.1. Desplegar un mensaje indicando que no hay solucin 4. Desplegar el laberinto una vez resuelto (con el camino)

Cdigo en C: main() { int ok; /* Para saber si se obtuvo solucion */ desplegar(); /* Despliega el laberinto sin resolver */ /* Resuelve el laberinto desde la entrada: (x0,y0) */ ok = recorrer(x0,y0); if (!ok) /* Si no se pudo resolver se envia un mensaje */ printf("\nLaberinto sin solucion\n"); } desplegar(); /* Despliega el laberinto resuelto (con el camino) */

4. Validacin del algoritmo La validacin de un algoritmo recursivo requiere verificar que la condicin de trmino se cumplir en algn momento. En caso contrario, el algoritmo se llamar a s mismo recursivamente hasta que el stack se agote y el programa colapse (error de ejecucin). En este caso, la condicin de trmino se alcanza cuando se logra llegar a la salida del laberinto o cuando se han probado todas las posibles direcciones (izquierda, derecha, arriba y abajo) y an as no se ha encontrado solucin. En este caso, el algoritmo recursivo se ha planteado de una forma bastante segura. El procedimiento siempre termina, ya sea positiva o negativamente, encontrando la solucin o desistiendo de encontrarla, respectivamente. Por otra parte, es necesario definir dominios que caractericen situaciones distintas bajo las cuales se puede ejecutar el algoritmo. Dominios: Deben definirse dominios en los que, tanto la entrada como la salida del laberinto, se encuentren en distintas posiciones, incluso del mismo lado o hasta contiguas. Validacin: Ejecutando en algoritmo para los dominios definidos debe verificarse que la solucin cumple con la especificacin planteada y por lo tanto alcanza el objetivo propuesto.

5. Limitaciones del algoritmo

A simple vista el algoritmo no tiene limitaciones importantes. Sin embargo, no existe una prueba formal de esto, por lo que se deja como ejercicio analizar la solucin propuesta a fin de determinar potenciales limitaciones.

You might also like