/* NW | NE * ------- * SW | SE * * */ void rotate_blank(cardinal_direction starting_reference, int number_movements, bool clockwise) { if (number_movements == 0) return; switch (starting_reference) { case NE: move_blank(clockwise ? down : left); rotate_blank(clockwise ? SE : NW, number_movements - 1, clockwise); return; case SE: move_blank(clockwise ? left : up); rotate_blank(clockwise ? SW : NE, number_movements - 1, clockwise); return; case SW: move_blank(clockwise ? up : right); rotate_blank(clockwise ? NW : SE, number_movements - 1, clockwise); return; case NW: move_blank(clockwise ? right : down); rotate_blank(clockwise ? NE : SW, number_movements - 1, clockwise); return; default: return; } }
int main(int argc, char *argv[]) { int **s_board; int n, i, ch; tile blank; if(argc != 2) { printf("Usage: %s <shuffle board order>\n", argv[0]); exit(1); } n = atoi(argv[1]); s_board = (int **)calloc(n, sizeof(int *)); for(i = 0;i < n; ++i) s_board[i] = (int *)calloc(n, sizeof(int)); init_board(s_board, n, &blank); initscr(); keypad(stdscr, TRUE); cbreak(); shuffle_board(s_board, n); while((ch = getch()) != KEY_F(1)) { switch(ch) { case KEY_LEFT: move_blank(RIGHT, s_board, n, &blank); break; case KEY_RIGHT: move_blank(LEFT, s_board, n, &blank); break; case KEY_UP: move_blank(DOWN, s_board, n, &blank); break; case KEY_DOWN: move_blank(UP, s_board, n, &blank); break; } shuffle_board(s_board, n); if(check_win(s_board, n, &blank) == TRUE) { mvprintw(24, 0, "You Win !!!\n"); refresh(); break; } } endwin(); return 0; }
/* TODO Attempt to reduce this function's complexity * * Move blank tile to the right of the target tile * * tile_row - target tile's row * tile_col - target tile's collumn * */ void move_blank_2_position(int tile_row, int tile_col) { if (tile_col == empty_col) { if (tile_col < d - 1) { move_blank(right); while (empty_row < tile_row) move_blank(down); while (empty_row > tile_row) move_blank(up); } else { move_blank(down); // Verify this condition move_blank(left); while (empty_row < tile_row) move_blank(down); while (empty_row > tile_row) move_blank(up); move_blank(right); } return; } else { if (tile_col < d - 1) { if (empty_row == tile_row) { while (empty_col < tile_col) move_blank(right); } else { while (empty_col < tile_col + 1) move_blank(right); } while (empty_row < tile_row) move_blank(down); while (empty_row > tile_row) move_blank(up); while (empty_col > tile_col + 1) move_blank(left); } else { while (empty_row < tile_row) move_blank(down); while (empty_col < tile_col - 1) move_blank(right); while (empty_row > tile_row) move_blank(up); move_blank(right); } } return; }
void fix_bottom_corner(int iteration) { int larger_tile = d * (d - 1) + iteration + 1; int smaller_tile = larger_tile - d; int tile_row, tile_col; int target_row, target_col; look_4_tile(larger_tile, &tile_row, &tile_col); move_blank_2_position(tile_row, tile_col); // Move larger tile to position [d - 2][iteration + 1] target_row = d - 2; target_col = iteration + 1; #if DEBUG sprintf(str, "Moving tile %d to position [d - 2][iteration + 1]\n",larger_tile); god_mode_debug(str); #endif move_tile_2_position(target_row, target_col); // If smaller_tile is in position [d - 2][iteration], reorder tiles if (board[d - 2][iteration] == smaller_tile) { #if DEBUG sprintf(str, "Tile %d in position [d - 2][iteration]\n",smaller_tile); god_mode_debug(str); sprintf(str, "Reordering tiles\n"); god_mode_debug(str); #endif // Reorder tiles move_blank(left); rotate_blank(NE, 3, true); move_blank(right); move_blank(right); rotate_blank(NE, 2, true); move_blank(left); rotate_blank(SW, 3, true); rotate_blank(SW, 2, false); #if DEBUG sprintf(str, "Reordering complete\n"); god_mode_debug(str); #endif } else // Else move larger tile to position [d - 2][iteration] { #if DEBUG sprintf(str, "Moving tile %d to position [d - 2][iteration]\n",larger_tile); god_mode_debug(str); #endif // Move larger tile to position [d - 2][iteration] move_tile(left); #if DEBUG sprintf(str, "Moving tile %d to position [d - 2][iteration + 1]\n",smaller_tile); god_mode_debug(str); #endif // Move smaller tile to position [d - 2][iteration + 1] look_4_tile(smaller_tile, &tile_row, &tile_col); move_blank_2_position(tile_row, tile_col); target_col = iteration + 1; move_tile_2_position(target_row, target_col); } #if DEBUG sprintf(str, "Rotating corner tiles\n"); god_mode_debug(str); #endif // Rotate tiles to fix corner rotate_blank(NE, 2, true); rotate_blank(SE, 3, true); }
void god_mode() { for (int i = 0; i < d - 3; i++) { #if DEBUG sprintf(str, "Filling %dth top row\n",i); god_mode_debug(str); #endif // Fix top row fix_top_row(i); #if DEBUG sprintf(str, "Fix top corner\n"); god_mode_debug(str); #endif // Fix top corner fix_top_corner(i); // Fix left collumn fix_left_collumn(i); #if DEBUG sprintf(str, "Fix bottom corner\n"); god_mode_debug(str); #endif // Fix bottom corner fix_bottom_corner(i); } #if DEBUG // Solve 3 x 3 puzzle god_mode_debug("Solving 3 x 3 puzzle\n"); #endif search_node head_node; head_node.previous = NULL; for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { head_node.board[i][j] = board[i + d - 3][j + d - 3]; } } head_node.g = 0; lifo * solution = NULL; #if DEBUG god_mode_debug("Calling a_star_search\n"); #endif a_star_search(&head_node, &solution); if (solution == NULL) printf("solution is NULL\n"); #if DEBUG god_mode_debug("Solution for 3 x 3 puzzle retrieved, begginning tiles movements\n"); #endif lifo_entry * entry = solution->head; lifo_entry * aux; while (solution->total_entries > 0) { switch(entry->node->move) { case up: move_blank(up); break; case down: move_blank(down); break; case left: move_blank(left); break; case right: move_blank(right); break; } aux = entry->next; free(entry); entry = aux; solution->head = entry; solution->total_entries--; } #if DEBUG god_mode_debug("3 x 3 puzzle solved\n"); #endif return; }