diff --git a/cost.c b/cost.c index 2373a6f..a82d6ad 100644 --- a/cost.c +++ b/cost.c @@ -12,6 +12,15 @@ void find_coord(Puzzle *puzzle, int value, int *x, int *y) { } } -int manhattan(int x1, int y1, int x2, int y2) { - return abs(x1 - x2) + abs(y1 - y2); +int manhattan_cost(Puzzle *current, Puzzle *goal) { + int cost = 0; + for (int j = 0; j < PUZZLE_DIMENSION; j++) { + if (current->board[j] != 0) { + int x1, y1, x2, y2; + find_coord(current, current->board[j], &x1, &y1); + find_coord(goal, current->board[j], &x2, &y2); + cost += abs(x1 - x2) + abs(y1 - y2); + } + } + return cost; } diff --git a/cost.h b/cost.h index c6cb43d..9258e97 100644 --- a/cost.h +++ b/cost.h @@ -4,6 +4,6 @@ #include "puzzle.h" void find_coord(Puzzle *puzzle, int value, int *x, int *y); -int manhattan(int x1, int y1, int x2, int y2); +int manhattan_cost(Puzzle *current, Puzzle *goal); #endif // COST_H_ diff --git a/node.c b/node.c index 8b446e8..7695b05 100644 --- a/node.c +++ b/node.c @@ -8,15 +8,16 @@ Node *generate_child_node(const Node *parent, const Direction direction) { return NULL; } + Node *child = (Node *)malloc(sizeof(Node)); + if (!child) return NULL; + Puzzle *new_state = (Puzzle *)malloc(sizeof(Puzzle)); if (!new_state) return NULL; *new_state = *(parent->state); - move(new_state, direction); - - Node *child = (Node *)malloc(sizeof(Node)); - if (!child) { + // Free new_state if move fails + if (!move(new_state, direction)) { free(new_state); return NULL; } @@ -24,22 +25,22 @@ Node *generate_child_node(const Node *parent, const Direction direction) { child->parent = (Node *)parent; child->state = new_state; child->move = direction; - child->cost = 0; + child->cost = parent->cost + 1; return child; } Node **generate_children(const Node *parent, int *num_children) { Node **children = (Node **)malloc(DIRECTION_COUNT * sizeof(Node *)); + if (!children) return NULL; + *num_children = 0; Direction directions[DIRECTION_COUNT] = {UP, DOWN, LEFT, RIGHT}; for (int i = 0; i < DIRECTION_COUNT; i++) { Node *child = generate_child_node(parent, directions[i]); - if (child != NULL) { - children[(*num_children)++] = child; - } + if (child) children[(*num_children)++] = child; } return children; diff --git a/puzzle.c b/puzzle.c index acf50dc..b1146a4 100644 --- a/puzzle.c +++ b/puzzle.c @@ -85,7 +85,7 @@ int is_valid_move(const Puzzle *p, const Direction direction) { } } -void move(Puzzle *p, const Direction direction) { +int move(Puzzle *p, const Direction direction) { int blank_row = p->blank_index / PUZZLE_SIZE; int blank_col = p->blank_index % PUZZLE_SIZE; @@ -106,16 +106,18 @@ void move(Puzzle *p, const Direction direction) { new_col++; break; case NONE: - return; + return 0; // No move made } if (new_row < 0 || new_row >= PUZZLE_SIZE || new_col < 0 || new_col >= PUZZLE_SIZE) { - return; + return 0; // Move is out of bounds } int new_index = new_row * PUZZLE_SIZE + new_col; swap(&p->board[p->blank_index], &p->board[new_index]); p->blank_index = new_index; + + return 1; // Move successful } void print_puzzle(const Puzzle *p, int debug) { diff --git a/puzzle.h b/puzzle.h index ed8bbce..f64acc3 100644 --- a/puzzle.h +++ b/puzzle.h @@ -19,7 +19,7 @@ int get_blank_index(const Puzzle *p); int get_inversion_count(const Puzzle puzzle); int is_solvable(const Puzzle puzzle); int is_valid_move(const Puzzle *p, const Direction direction); -void move(Puzzle *p, const Direction direction); +int move(Puzzle *p, const Direction direction); void print_puzzle(const Puzzle *p, int debug); void shuffle(Puzzle *p); void swap(int *a, int *b); diff --git a/solve/bfs.c b/solve/bfs.c index 24c30b8..da3b3df 100644 --- a/solve/bfs.c +++ b/solve/bfs.c @@ -31,16 +31,21 @@ Node* bfs_solve(Puzzle* start, Puzzle* goal) { Node* current = dequeue(queue); + // Check if the goal state is reached if (compare_puzzles(current->state, goal)) { // Free the remaining nodes in the queue while (!is_queue_empty(queue)) { Node* temp = dequeue(queue); - free(temp); + free(temp->state); // Free the state associated with the node + free(temp); // Free the node itself } free_queue(queue); free_hashset(&visited); // Free the HashSet memory + + // Print statistics printf("Solution found at depth %d after expanding %d nodes.\n", depth, nodes_expanded); - return current; // Found the goal + + return current; // Return the solution node } // Generate the children nodes of the current node @@ -50,22 +55,15 @@ Node* bfs_solve(Puzzle* start, Puzzle* goal) { for (int i = 0; i < num_children; i++) { // Calculate cost of the child node - int x1, y1, x2, y2; - - for (int j = 0; j < PUZZLE_DIMENSION; j++) { - if (current->state->board[j] != 0) { - find_coord(current->state, current->state->board[j], &x1, &y1); - find_coord(goal, current->state->board[j], &x2, &y2); - children[i]->cost += manhattan(x1, y1, x2, y2); - } - } + children[i]->cost = manhattan_cost(children[i]->state, goal); // Check if the child state has been visited if (!contains(&visited, children[i]->state)) { enqueue(queue, children[i]); // Enqueue unvisited child insert(&visited, children[i]->state); // Mark as visited } else { - free(children[i]); // Free memory for already visited child + free(children[i]->state); // Free state memory for already visited child + free(children[i]); // Free memory for already visited child } }