From 59c984d5ea8770a40c9555df8d24b3998eb79e86 Mon Sep 17 00:00:00 2001 From: Mylloon Date: Sun, 19 Feb 2023 17:58:59 +0100 Subject: [PATCH] impl bfs --- TP1/C-Cpp/includes/mysok.h | 17 ++++- TP1/C-Cpp/src/mysok.cpp | 134 +++++++++++++++++++++++++++++++++++-- TP1/C-Cpp/src/r0.cpp | 14 ++++ 3 files changed, 158 insertions(+), 7 deletions(-) diff --git a/TP1/C-Cpp/includes/mysok.h b/TP1/C-Cpp/includes/mysok.h index 986c0dc..2261ada 100644 --- a/TP1/C-Cpp/includes/mysok.h +++ b/TP1/C-Cpp/includes/mysok.h @@ -1,6 +1,8 @@ #ifndef MYSOK_H #define MYSOK_H +#include +#include #include #define NBL 20 @@ -23,7 +25,11 @@ enum board_str { END_OF_LINE = 'a' }; -// const std::string move_str[] = {"Up", "Down", "Left", "Right", "Wait"}; +const std::string move_str[] = {"Up", "Down", "Left", "Right", "Wait"}; + +const int dx[] = {-1, 1, 0, 0, 0}; +const int dy[] = {0, 0, -1, 1, 0}; +const int dsize = 5; struct sok_board_t { int board[NBL][NBC]; @@ -32,10 +38,19 @@ struct sok_board_t { int man1_y; int man2_x; int man2_y; + int num_crates_free; sok_board_t(); void print_board(); void load(char *_file); }; +typedef struct { + sok_board_t state; + int path_len; + std::string path; +} bfsNode; + +int bfs(bfsNode &result); + #endif diff --git a/TP1/C-Cpp/src/mysok.cpp b/TP1/C-Cpp/src/mysok.cpp index 16a4048..801a947 100644 --- a/TP1/C-Cpp/src/mysok.cpp +++ b/TP1/C-Cpp/src/mysok.cpp @@ -1,16 +1,16 @@ #include "../includes/mysok.h" sok_board_t::sok_board_t() { - for (int i = 0; i < NBL; i++) { - for (int j = 0; j < NBC; j++) { + for (int i = 0; i < NBL; ++i) { + for (int j = 0; j < NBC; ++j) { board[i][j] = FREE; } } } void sok_board_t::print_board() { - for (int i = 0; i < board_nbl; i++) { - for (int j = 0; j < NBC; j++) { + for (int i = 0; i < board_nbl; ++i) { + for (int j = 0; j < NBC; ++j) { if (board[i][j] == END_OF_LINE) { break; } @@ -33,11 +33,12 @@ void sok_board_t::load(char *_file) { exit(EXIT_FAILURE); } + num_crates_free = 0; board_nbl = 0; while ((nread = getline(&line, &len, fp)) != -1) { if ((static_cast(nread)) > 0) { bool read_ok = false; - for (int i = 0; i < nread; i++) { + for (int i = 0; i < nread; ++i) { switch (line[i]) { case (FREE): { board[board_nbl][i] = FREE; @@ -54,6 +55,7 @@ void sok_board_t::load(char *_file) { } case (CRATE_ON_FREE): { board[board_nbl][i] = CRATE_ON_FREE; + ++num_crates_free; break; } case (CRATE_ON_TARGET): { @@ -88,7 +90,7 @@ void sok_board_t::load(char *_file) { } if (read_ok) { board[board_nbl][nread - 1] = END_OF_LINE; - board_nbl++; + ++board_nbl; } } } @@ -96,3 +98,123 @@ void sok_board_t::load(char *_file) { free(line); fclose(fp); } + +int bfs(bfsNode &result) { + // Création de la queue de BFS + std::queue q; + + // Ajout de l'état initial à la queue + bfsNode first; + first.state = result.state; + first.path_len = 0; + first.path = ""; + q.push(first); + + // Boucle principale de la recherche BFS + while (!q.empty()) { + // Retrait de l'état en tête de la queue + bfsNode cur = q.front(); + q.pop(); + + // Si l'état actuel est celui souhaité (toutes les caisses sur des cibles) + if (cur.state.num_crates_free <= 0) { + result = cur; + 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 = cur.state.man1_x; + int man1_y = cur.state.man1_y; + + // Position du joueur après déplacement + int new_man1_x = cur.state.man1_x + dx[i]; + int new_man1_y = cur.state.man1_y + dy[i]; + + // Si la case devant le joueur est un mur + if (cur.state.board[new_man1_x][new_man1_y] == WALL) { + continue; + } + + // Si la case devant le joueur est libre + if (cur.state.board[new_man1_x][new_man1_y] == FREE || + cur.state.board[new_man1_x][new_man1_y] == TARGET) { + // On déplace le joueur dans le prochain état + sok_board_t next = cur.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 queue + bfsNode next_bfs; + next_bfs.state = next; + next_bfs.path_len = cur.path_len + 1; + next_bfs.path = cur.path + move_str[i] + " "; + q.push(next_bfs); + } + + // Si la case devant le joueur est une caisse + if (cur.state.board[new_man1_x][new_man1_y] == CRATE_ON_FREE || + cur.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 + if (cur.state.board[new_cx][new_cy] != TARGET || + cur.state.board[new_cx][new_cy] != FREE) { + continue; + } + + // On déplace la caisse et le joueur + sok_board_t next = cur.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 caisse, anciennne position, ie. nouvelle position joueur + next.board[cx][cy] = next.board[cx][cy] == CRATE_ON_TARGET + ? MAN1_ON_TARGET + : MAN1_ON_FREE; + next.man1_x = new_man1_x; + next.man1_y = new_man1_y; + // S'éloigne de l'objectif si on déplace une caisse d'une cible + if (next.board[cx][cy] == MAN1_ON_TARGET) { + ++next.num_crates_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; + // S'approche de l'objectif si on place une caisse sur la cible + if (next.board[new_cx][new_cy] == CRATE_ON_TARGET) { + --next.num_crates_free; + } + + // On ajoute l'état suivant à la queue + bfsNode next_bfs; + next_bfs.state = next; + next_bfs.path_len = cur.path_len + 1; + next_bfs.path = cur.path + move_str[i] + " "; + q.push(next_bfs); + } + } + } + + // Si la queue est vide et qu'on n'a pas trouvé de solution, c'est qu'il n'y + // en a pas + return -1; +} diff --git a/TP1/C-Cpp/src/r0.cpp b/TP1/C-Cpp/src/r0.cpp index 746df83..6a3fc8d 100644 --- a/TP1/C-Cpp/src/r0.cpp +++ b/TP1/C-Cpp/src/r0.cpp @@ -11,5 +11,19 @@ int main(int _ac, char **_av) { S.load(_av[1]); S.print_board(); + bfsNode result; + + result.state = S; + result.path = ""; + result.path_len = 0; + 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"; + } + + result.state.print_board(); + return 0; }