impl bfs
This commit is contained in:
parent
c6dfd8f9da
commit
59c984d5ea
3 changed files with 158 additions and 7 deletions
|
@ -1,6 +1,8 @@
|
|||
#ifndef MYSOK_H
|
||||
#define MYSOK_H
|
||||
|
||||
#include <iostream>
|
||||
#include <queue>
|
||||
#include <string>
|
||||
|
||||
#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
|
||||
|
|
|
@ -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<int>(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<bfsNode> 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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Reference in a new issue