Skip to content

Instantly share code, notes, and snippets.

@jgomo3
Last active August 29, 2015 14:01
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jgomo3/836e6a539546f3673398 to your computer and use it in GitHub Desktop.
Save jgomo3/836e6a539546f3673398 to your computer and use it in GitHub Desktop.
Recomendaciones para realizar el proyecto 2 de Algoritmos y Programación II-2013

Recomendaciones para el proyecto 2

Ésta es una lista de recomendaciones que me atrevo a realizar a los alumnos del primer semestre de Computación de la UCV (II-2013) acerca de cómo desarrollar el producto que se les exige en el segundo proyecto de la materia Algoritmos y Programación.

Estas recomendaciones están basadas en mi experiencia al realizar mi propia solución y las múltiples preguntas que he recibido por correo electrónico al respecto.

Entonces, aviso: gran parte de las recomendaciones aquí expuestas están totalmente visiadas por la solución que le dí personalmente al problema. Eso no quiere decir que la solución que otros hayan dado al problema estén erradas.

Escribo esto entonces porque puede ser de interés a quienes no hayan avanzado lo suficiente en su propio proyecto. Sin embargo, creo que puede ser de interés para quienes ya estén avanzados o ya hayan terminado, comparar mi diseño con el de ellos. Por mera curiosidad.

El proyecto en cuestión puede leerse en la página de la materia.

Usen dos matrices de 20 x 20

Esta primera recomendación es en realidad 2.

Usen dos matrices

Una matriz de 20 x 20 enteros, que yo llamo "lógico", tendría el tablero "destapado", es decir, el "rompecabezas". En cada casilla de este, habría un número que indique la cantidad de minas que tiene alrededor (0-8) o un -1 si se trata de una mina.

La otra matriz de 20 x 20 carácteres, que yo llamo "fachada", empezaría el juego lleno de "numerales" (#), y luego de cada jugada válida, el numeral que ocupa la casilla jugada se sustituiría por el número que esté en el tablero "lógico" en la misma posición, o un "asterisco" (*) en caso de que fuera una mina.

Usen matrices de 20 x 20

Ambas matrices, tanto la de enteros como la de carácteres (tablero "lógico" y "fachada" respectivamente) deberían ser declaradas de tamaño fijo 20 x 20.

Primero:

20 x 20 no es gran cosa (400 casillas).

Segundo:

Para poder definir la matriz de tamaño N x N1, hay que esperar a que el programa "lea" el valor de N. Cuando esto sucede, la memoria necesaria para poder establecer la matriz se reservará "en tiempo de ejecución", es decir, se reservará la memoria cuando el programa está corriendo. A esto se le conoce como manejo dinámico de memoria. Esta técnica no la hemos visto con su justa explicación en clases y tiene muchas implicaciones.

En cambio, al establecer la matriz de 20 x 20, la memoria se reserva de una vez al "cargar" el programa (recien empezando) y no es necesaria entonces ningúna técnica de manejo dinámico de memoria.

Entonces, con la matriz de 20 x 20, se tiene la memoria garantizada para cualquier caso de N. Es decir, si N = 4, una matriz de 4 x 4 entra fácilmente en la memoria que se reservó para una matriz de 20 x 20. Con sólo pensar que la matriz sí es de N x N, y no de 20 x 20, es decri: engañarse a sí mismo; entonces el resto del programa no sufre ningún cambio.

En conclusión: Hagan las matrices de 20 x 20, y programen pensando que son de N x N.

Hagan muchas funciones

Creo que en esto es lo que más he insistido durante la materia. La idea principal es dividir el gran problema (el proyecto) en muchos problemas y subproblemas más pequeños.

Les mostraré la función main de mi solución:

int main() {
    int tablero_l[20][20]; // lógico
    char tablero_f[20][20]; // fachada
    int N, M;

    obtener_configuracion(N, M);
    blanquear_tablero(tablero_f, N);
    colocar_minas(tablero_l, N, M);
    inicializar_tablero(tablero_l, N);
    jugar(tablero_l, tablero_f, N, M);

    return 0;
}

En C++, para establecer que un parámetro formal es pasado por referencia, se prefija la variable que establece el parámetro con un "ampersand" (&). Sin embargo, los arreglos (y por ende, las matrices) son siempre pasados por referencia; es decir, no se necesita el "ampersand".

En la función main de ejemplo, se invocan 5 acciones. La primera acción que se invoca es obtener_configuracion. Lo que hace esa acción es simplemente asignarle a las variables N y M los valores que el programa "lee" (con cin). Entonces, en este caso, los parámetros son pasados por referencia. Así, la definición de esta acción sería algo como:

void obtener_configuracion(int &N, int &M) {
    ...
}

La segunda acción invocada es blanquear_tablero. Lo que hace esta acción es llenar de "numerale" el tablero fachada. Esa acción recibe el tablero fachada por referencia, y N por valor. N es muy importante porque es lo que nos permite saber las dimensiones del tablero (independiente de que se haya reservado 20 x 20 casillas de memoria). Entonces, la definición de esta acción sería algo como:

void blanquear_tableros(char t[][20], int N) {
    ...
}

Nótese lo siguiente:

  1. El primer parámetro, que es la matriz de carácteres, es pasada por referencia2 y sin embargo no hay ningún "ampersand" prefijado en ninguna variable. Así funcionan los arreglos, son siempre pasados por referencia.
  2. Cuando se pasan los arreglos como parámetros, la primera dimensión puede obviarse, como se ve en el ejemplo, pero las susecivas dimensiones no; por eso el 20 que se aprecia en el ejemplo. Esto es debido a la manera en que se implementan los arreglos multidimensionales en C++, que en realidad son arreglos unidimensionales.
  3. N se pasa por valor. Por eso no hay "ampernsand" (&).

Comparto un diagrama que describe cómo dividí el problema en subproblemas. Cada caja representa algún procedimiento, y la flecha que va de un procedimiento a otro indica que el primero depende o hace uso del segundo.

image


  1. N es la dimensión establecida por el proyecto. Es una entrada.

  2. En realidad esto es un efecto colateral del manejo de apuntadores, pero puede entenderse simplemente como pase por referencia.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment