11#include " bfs.hpp"
2- #include < godot_cpp/variant/utility_functions.hpp>
3- #include < iostream>
4- using namespace std ;
5-
6- vector<SearchNode> bfs::generate_next_bfs (const Board& initial_board, const SearchNode& current_node) {
7- vector<SearchNode> successors;
8- const vector<Piece>& current_pieces = current_node.pieces ;
9-
10- for (size_t piece_idx = 0 ; piece_idx < current_pieces.size (); ++piece_idx) {
11- const Piece& piece_to_move = current_pieces[piece_idx];
12- if (piece_to_move.id == ' K' ) continue ; // jangan gerakin exit
13-
14- // direction: -1 = kiri/atas, 1 = kanan/bawah
15- for (int direction = -1 ; direction <= 1 ; direction += 2 ) {
16- if (direction == 0 ) continue ;
17- for (int steps = 1 ; ; ++steps) {
18- vector<Piece> next_pieces_state = current_pieces;
19- Piece& piece_moved = next_pieces_state[piece_idx];
20-
21- Coordinates new_top_left_coordinate = piece_to_move.coordinates ;
22- bool move = true ;
23-
24- if (piece_to_move.is_vertical ) {
25- for (int s = 1 ; s <= steps; ++s) {
26- int y;
27- if (direction > 0 ) { // bergerak ke bawah
28- y = piece_to_move.coordinates .y + piece_to_move.size - 1 + s;
29- }
30- else { // bergerak ke atas
31- y = piece_to_move.coordinates .y - s;
32- }
33- if (!Utils::is_cell_clear (initial_board, y, piece_to_move.coordinates .x , current_pieces, piece_to_move.id )) {
34- move = false ;
35- break ;
36- }
37- }
38- if (move) {
39- piece_moved.coordinates .y += (direction * steps);
40- }
41- }
42- else { // bergerak horizontal
43- for (int s = 1 ; s <= steps; ++s) {
44- int x;
45- if (direction > 0 ) { // bergerak ke kanan
46- x = piece_to_move.coordinates .x + piece_to_move.size - 1 + s;
47- }
48- else { // bergerak ke kiri
49- x = piece_to_move.coordinates .x - s;
50- }
51- if (!Utils::is_cell_clear (initial_board, piece_to_move.coordinates .y , x, current_pieces, piece_to_move.id )) {
52- move = false ;
53- break ;
54- }
55- }
56- if (move) {
57- piece_moved.coordinates .x += (direction * steps);
58- }
59- }
60-
61- if (!move) {
62- break ;
63- }
64-
65- vector<PieceMove> next_path = current_node.path ;
66- PieceMove current_pm;
67- current_pm.old_coordinates = piece_to_move.coordinates ;
68- current_pm.new_coordinates = piece_moved.coordinates ;
69- next_path.push_back (current_pm);
70-
71- int val = Utils::calculate (initial_board, next_pieces_state);
72-
73- successors.emplace_back (next_pieces_state, initial_board, next_path, val, piece_to_move.id , piece_to_move.coordinates );
74- }
75- }
76- }
77- return successors;
78- }
2+ #include " ../../utils/utils.hpp"
793
804Solution bfs::search_bfs (const Board& initial_board, const std::vector<Piece>& initial_pieces) {
81- auto time_start = chrono::high_resolution_clock::now ();
82-
83- // inisialisasi
84- Solution result;
85- result.is_solved = false ;
86- result.node = 0 ;
87-
88- priority_queue<SearchNode, vector<SearchNode>, greater<SearchNode>> pq;
89- set<string> visited;
90- int initial_h = Utils::calculate (initial_board, initial_pieces);
91- SearchNode initial_node (initial_pieces, initial_board, {}, initial_h);
92- pq.push (initial_node);
93-
94- godot::UtilityFunctions::print (" GBFS: Initial heuristic: " , initial_h);
95-
96- while (!pq.empty ()) {
97- SearchNode current_node = pq.top ();
98- pq.pop ();
99-
100- result.node ++;
101-
102- string current_state_str = Utils::state_to_string (current_node.pieces );
103- if (visited.count (current_state_str)) {
104- continue ;
105- }
106- visited.insert (current_state_str);
107-
108- godot::UtilityFunctions::print (" GBFS: Exploring node. Heuristic: " , current_node.val , " . Path length: " , current_node.path .size ());
109- if (current_node.piece_moved != ' ' ) {
110- godot::UtilityFunctions::print (" Moved piece: " , String::utf8 (¤t_node.piece_moved , 1 ) , " from (" , current_node.original_pos_moved_piece .x , " ," , current_node.original_pos_moved_piece .y , " ) to (" , current_node.pieces [0 ].coordinates .x , " ," , current_node.pieces [0 ].coordinates .y , " )" );
111- }
5+ Utils::SearchParams bfs_params;
6+ bfs_params.algorithm_name = " BFS" ;
1127
8+ bfs_params.calculate_initial_val = [](const Board& board, const vector<Piece>& pieces) {
9+ return Utils::calculate (board, pieces);
10+ };
11311
114- if (Utils::is_exit (initial_board, current_node.pieces )) {
115- result.is_solved = true ;
116- result.moves = current_node.path ;
117- godot::UtilityFunctions::print (" GBFS: Solution Found! Moves: " , result.moves .size (), " Nodes visited: " , result.node );
118- break ;
119- }
12+ bfs_params.successor_val = [](const Board& board_state, const vector<Piece>& next_pieces_state, const SearchNode&) {
13+ return Utils::calculate (board_state, next_pieces_state);
14+ };
12015
121- vector<SearchNode> next = generate_next_bfs (initial_board, current_node);
122- for (const auto & next_node : next) {
123- string next_state_str = Utils::state_to_string (next_node.pieces );
124- if (!visited.count (next_state_str)) {
125- pq.push (next_node);
126- }
127- }
128- }
16+ bfs_params.get_node_exploration = [](const SearchNode& node) {
17+ return godot::String (" Heuristic: " ) + godot::String::num_int64 (node.val );
18+ };
12919
130- auto time_end = chrono::high_resolution_clock::now ();
131- result.duration = chrono::duration<double , milli>(time_end - time_start);
132-
133- if (!result.is_solved ) {
134- godot::UtilityFunctions::print (" GBFS: No solution found. Nodes visited: " , result.node );
135- }
20+ bfs_params.get_solution_details = [](const SearchNode&, const Solution& sol) {
21+ return godot::String (" Moves: " ) + godot::String::num_int64 (sol.moves .size ());
22+ };
13623
137- return result ;
24+ return Utils::search (initial_board, initial_pieces, bfs_params) ;
13825}
0 commit comments