diff --git a/TP1/C-Cpp/includes/mysok.h b/TP1/C-Cpp/includes/mysok.h index 2261ada..e82c450 100644 --- a/TP1/C-Cpp/includes/mysok.h +++ b/TP1/C-Cpp/includes/mysok.h @@ -3,11 +3,12 @@ #include #include +#include #include #define NBL 20 #define NBC 20 -#define MAX_CRATES 20 +#define MAX_DEPTH 16 enum movement { MOVE_U = 0, MOVE_D, MOVE_L, MOVE_R, MOVE_W }; @@ -49,8 +50,9 @@ typedef struct { sok_board_t state; int path_len; std::string path; -} bfsNode; +} Node; -int bfs(bfsNode &result); +int bfs(Node &result); +int dfs(Node &result, int depth); #endif diff --git a/TP1/C-Cpp/src/mysok.cpp b/TP1/C-Cpp/src/mysok.cpp index a1c9565..5ad9450 100644 --- a/TP1/C-Cpp/src/mysok.cpp +++ b/TP1/C-Cpp/src/mysok.cpp @@ -99,12 +99,12 @@ void sok_board_t::load(char *_file) { fclose(fp); } -int bfs(bfsNode &result) { +int bfs(Node &result) { // Création de la queue de BFS - std::queue q; + std::queue q; // Ajout de l'état initial à la queue - bfsNode first; + Node first; first.state = result.state; first.path_len = 0; first.path = ""; @@ -113,7 +113,7 @@ int bfs(bfsNode &result) { // Boucle principale de la recherche BFS while (!q.empty()) { // Retrait de l'état en tête de la queue - bfsNode cur = q.front(); + Node cur = q.front(); q.pop(); // Si l'état actuel est celui souhaité (toutes les caisses sur des cibles) @@ -154,7 +154,7 @@ int bfs(bfsNode &result) { next.man1_y = new_man1_y; // On ajoute cet état suivant à la queue - bfsNode next_bfs; + Node next_bfs; next_bfs.state = next; next_bfs.path_len = cur.path_len + 1; next_bfs.path = cur.path + move_str[i] + " "; @@ -205,7 +205,7 @@ int bfs(bfsNode &result) { } // On ajoute l'état suivant à la queue - bfsNode next_bfs; + Node next_bfs; next_bfs.state = next; next_bfs.path_len = cur.path_len + 1; next_bfs.path = cur.path + move_str[i] + " "; @@ -218,3 +218,115 @@ int bfs(bfsNode &result) { // en a pas return -1; } + +int dfs(Node &result, int depth) { + // Si on a atteint la profondeur maximale, on arrête la recherche + if (depth == MAX_DEPTH) { + /* std::cout << "max\n"; */ + return -1; + } + + // Si l'état actuel est celui souhaité (toutes les caisses sur des cibles) + if (result.state.num_crates_free <= 0) { + return 0; + } + + // Parcours des déplacements possibles à partir de l'état actuel + for (int i = 0; i < dsize - 1; ++i) { + // Position de la case du joueur + int man1_x = result.state.man1_x; + int man1_y = result.state.man1_y; + + // Position du joueur après déplacement + int new_man1_x = result.state.man1_x + dx[i]; + int new_man1_y = result.state.man1_y + dy[i]; + + // Si la case devant le joueur est un mur, on ignore ce mouvement + if (result.state.board[new_man1_x][new_man1_y] == WALL) { + continue; + } + + // Si la case devant le joueur est libre ou une cible, on déplace le joueur + if (result.state.board[new_man1_x][new_man1_y] == FREE || + result.state.board[new_man1_x][new_man1_y] == TARGET) { + // On déplace le joueur dans le prochain état + sok_board_t next = result.state; + + // Déplacement joueur, ancienne position + next.board[man1_x][man1_y] = + next.board[man1_x][man1_y] == MAN1_ON_TARGET ? TARGET : FREE; + // Déplacement joueur, nouvelle position + next.board[new_man1_x][new_man1_y] = + next.board[new_man1_x][new_man1_y] == TARGET ? MAN1_ON_TARGET + : MAN1_ON_FREE; + next.man1_x = new_man1_x; + next.man1_y = new_man1_y; + + // On ajoute cet état suivant à la pile + Node next_dfs; + next_dfs.state = next; + next_dfs.path_len = result.path_len + 1; + next_dfs.path = result.path + move_str[i] + " "; + + int res = dfs(next_dfs, depth + 1); + if (res == 0) { + result = next_dfs; + return 0; + } + } + + // Si la case devant le joueur est une caisse, on déplace la caisse et le + // joueur + if (result.state.board[new_man1_x][new_man1_y] == CRATE_ON_FREE || + result.state.board[new_man1_x][new_man1_y] == CRATE_ON_TARGET) { + // Position de la caisse + int cx = new_man1_x; + int cy = new_man1_y; + // Position de la caisse après déplacement + int new_cx = cx + dx[i]; + int new_cy = cy + dy[i]; + + // Si la case derrière la caisse n'est pas accessible, on ignore ce + // mouvement + if (result.state.board[new_cx][new_cy] != TARGET && + result.state.board[new_cx][new_cy] != FREE) { + continue; + } + + // On déplace la caisse et le joueur dans le prochain état + sok_board_t next = result.state; + + // Déplacement caisse, ancienne position + next.board[cx][cy] = + next.board[cx][cy] == CRATE_ON_TARGET ? TARGET : FREE; + // Déplacement caisse, nouvelle position + next.board[new_cx][new_cy] = next.board[new_cx][new_cy] == TARGET + ? CRATE_ON_TARGET + : CRATE_ON_FREE; + // Déplacement joueur, ancienne position + next.board[man1_x][man1_y] = + next.board[man1_x][man1_y] == MAN1_ON_TARGET ? TARGET : FREE; + // Déplacement joueur, nouvelle position + next.board[new_man1_x][new_man1_y] = + next.board[new_man1_x][new_man1_y] == TARGET ? MAN1_ON_TARGET + : MAN1_ON_FREE; + next.man1_x = new_man1_x; + next.man1_y = new_man1_y; + + // On ajoute cet état suivant à la pile + Node next_dfs; + next_dfs.state = next; + next_dfs.path_len = result.path_len + 1; + next_dfs.path = result.path + move_str[i] + " "; + + int res = dfs(next_dfs, depth + 1); + if (res == 0) { + result = next_dfs; + return 0; + } + } + } + + // Aucune solution n'a été trouvée à partir de cet état + return -1; +} diff --git a/TP1/C-Cpp/src/r0.cpp b/TP1/C-Cpp/src/r0.cpp index 6a3fc8d..65eaa35 100644 --- a/TP1/C-Cpp/src/r0.cpp +++ b/TP1/C-Cpp/src/r0.cpp @@ -11,19 +11,26 @@ int main(int _ac, char **_av) { S.load(_av[1]); S.print_board(); - bfsNode result; + Node result; result.state = S; result.path = ""; result.path_len = 0; - if (bfs(result) == -1) { + /* if (bfs(result) == -1) { + std::cout << "Aucune solution trouvée\n"; + } else { + std::cout << "Coups : " << result.path_len << "\n"; + std::cout << "Solution : " << result.path << "\n"; + } */ + + if (dfs(result, 0) == -1) { std::cout << "Aucune solution trouvée\n"; } else { std::cout << "Coups : " << result.path_len << "\n"; std::cout << "Solution : " << result.path << "\n"; } - result.state.print_board(); + // result.state.print_board(); return 0; }