Implementar un programa que resuelva un mapa en grilla, encontrando recursivamente un camino desde un punto de inicio hasta una salida.
El trabajo integra contenidos de repaso y recursividad:
El programa debe leer un mapa desde un archivo de entrada, calcular la mejor ruta posible y escribir el resultado en un archivo de salida.
La búsqueda debe hacerse de forma recursiva, explorando alternativas hasta encontrar la mejor solución según las reglas del enunciado.
En el mapa hay:
IS#.0 a 9 (su valor suma puntaje)Se puede mover en 4 direcciones:
Restricciones:
Entre todas las rutas válidas de I a S, se elige:
Para que el resultado sea determinístico y fácil de testear, usar este orden lexicográfico de movimientos:
A = ArribaB = AbajoD = DerechaI = IzquierdaEl archivo de entrada contendrá:
filas columnasfilas líneas con exactamente columnas caracteres cada unaCaracteres permitidos dentro de la grilla:
I, S, #, ., 0 a 9Condiciones esperadas del archivo:
IS6 7
I2..#..
.#3.#S.
..#..#.
1..4...
.##..5.
...#...
Si existe al menos un camino válido:
RESULTADO: ENCONTRADO
PUNTAJE: <puntaje_total>
PASOS: <cantidad_de_pasos>
MOVIMIENTOS: <secuencia>
CAMINO: (f1,c1) -> (f2,c2) -> ... -> (fk,ck)
Si no existe camino:
RESULTADO: SIN_CAMINO
Convenciones:
PASOS es la cantidad de movimientos, por lo tanto si el camino tiene k posiciones, entonces pasos = k - 1Se recomienda una organización similar a la siguiente:
struct Posicion {
unsigned int fila;
unsigned int columna;
};
struct Mapa {
char **celdas;
int filas;
int columnas;
struct Posicion inicio;
struct Posicion salida;
};
struct Solucion {
bool encontrada;
int puntaje;
int pasos;
char *movimientos;
struct Posicion *camino;
int largo_camino;
};
A la hora de escribir las aserciones, el archivo generado debe ser igual al archivo esperado. Para ello, pueden usar esta función:
bool file_eq(const char *archivo_esperado, const char *archivo_generado) {
FILE *esperado = fopen(archivo_esperado, "r");
FILE *generado = fopen(archivo_generado, "r");
if (!esperado || !generado) {
if (esperado) fclose(esperado);
if (generado) fclose(generado);
return false;
}
char linea_esperada[256];
char linea_generada[256];
bool son_iguales = true;
while (fgets(linea_esperada, sizeof(linea_esperada), esperado) != NULL) {
if (fgets(linea_generada, sizeof(linea_generada), generado) == NULL) {
son_iguales = false;
break;
}
if (strcmp(linea_esperada, linea_generada) != 0) {
son_iguales = false;
break;
}
}
if (fgets(linea_generada, sizeof(linea_generada), generado) != NULL) {
son_iguales = false;
}
fclose(esperado);
fclose(generado);
return son_iguales;
}
int main() {
imprimir_titulo("TP Integrador - Ruta de Rescate en Mina");
resolver_ruta_mina("archivos/prueba1_entrada.txt", "archivos/prueba1_salida.txt");
assert(file_eq("archivos/prueba1_salida_esperada.txt", "archivos/prueba1_salida.txt"));
resolver_ruta_mina("archivos/prueba2_entrada.txt", "archivos/prueba2_salida.txt");
assert(file_eq("archivos/prueba2_salida_esperada.txt", "archivos/prueba2_salida.txt"));
return 0;
}
Se recomienda incluir al menos estos casos:
Los archivos deben colocarse dentro de la carpeta archivos de la práctica de recursividad.
Agregar debajo de enable_testing() en el archivo CMakeLists.txt:
# Copiar los archivos de datos
file(GLOB DATA_FILES "archivos/*.txt")
foreach (DATA_FILE ${DATA_FILES})
get_filename_component(FILE_NAME ${DATA_FILE} NAME)
configure_file(${DATA_FILE} archivos/${FILE_NAME} COPYONLY)
endforeach ()
El trabajo será evaluado según:
test_tp_ruta_mina.c.Según lo indicado en la guía de trabajos prácticos.