#include #include #include #include #include "grid.h" #include "snake.h" Grid *allocate_grid(int n, int m) { Grid *g = malloc(sizeof(Grid)); int i; if (!g) { fprintf(stderr, "Error: could not allocate Grid.\n"); exit(EXIT_FAILURE); } g->nbl = n; g->nbc = m; g->grid = malloc(n * sizeof(char *)); if (!g->grid) { fprintf(stderr, "Error: could not allocate g->grid.\n"); exit(EXIT_FAILURE); } for (i = 0; i < n; i++) { g->grid[i] = calloc(m + 2, sizeof(char)); if (!g->grid[i]) { fprintf(stderr, "Error: could not allocate row.\n"); exit(EXIT_FAILURE); } } return g; } void free_grid(Grid *g) { int i; if (!g) return; for (i = 0; i < g->nbl; i++) { free(g->grid[i]); } free(g->grid); free(g); } void debug_grid(Grid *g) { int i; for (i = 0; i < g->nbl; i++) { printf("%s\n", g->grid[i]); } } int compute_size(Grid *g, int w, int h) { int size_width = w / g->nbc; int size_height = h / g->nbl; return (size_width < size_height) ? size_width : size_height; } void draw_grid(Grid *g) { int i, j; int window_width = MLV_get_window_width(); int window_height = MLV_get_window_height(); int cell_size = compute_size(g, window_width, window_height); MLV_Image *image_wall, *image_fruit, *image_snake, *image_snake_head, *image_boost, *image_empty; image_wall = MLV_load_image("./assets/wall.png"); image_fruit = MLV_load_image("./assets/fruit.png"); image_snake = MLV_load_image("./assets/snake.png"); image_snake_head = MLV_load_image("./assets/snake_head.png"); image_boost = MLV_load_image("./assets/boost.png"); image_empty = MLV_load_image("./assets/grass.png"); if (image_wall != NULL) { MLV_resize_image_with_proportions(image_wall, cell_size, cell_size); } if (image_fruit != NULL) { MLV_resize_image_with_proportions(image_fruit, cell_size, cell_size); } if (image_snake != NULL) { MLV_resize_image_with_proportions(image_snake, cell_size, cell_size); } if (image_snake_head != NULL) { MLV_resize_image_with_proportions(image_snake_head, cell_size, cell_size); } if (image_boost != NULL) { MLV_resize_image_with_proportions(image_boost, cell_size, cell_size); } if (image_empty != NULL) { MLV_resize_image_with_proportions(image_empty, cell_size, cell_size); } MLV_draw_filled_rectangle(0, 0, window_width, window_height, MLV_COLOR_BLACK); for (i = 0; i < g->nbl; i++) { for (j = 0; j < g->nbc; j++) { int x = j * cell_size; int y = i * cell_size; switch (g->grid[i][j]) { case WALL: if (image_wall == NULL) { MLV_draw_filled_rectangle(x, y, cell_size, cell_size, MLV_COLOR_BROWN); } else { MLV_draw_image(image_wall, x, y); } break; case EMPTY: if (image_empty != NULL) { MLV_draw_image(image_empty, x, y); } else { MLV_draw_filled_rectangle(x, y, cell_size, cell_size, MLV_COLOR_WHITE); } break; case FRUIT: if (image_fruit == NULL) { MLV_draw_filled_rectangle(x, y, cell_size, cell_size, MLV_COLOR_RED); } else { MLV_draw_image(image_fruit, x, y); } break; case SNAKE: if (image_snake == NULL) { MLV_draw_filled_rectangle(x, y, cell_size, cell_size, MLV_COLOR_GREEN); } else { MLV_draw_image(image_snake, x, y); } break; case SNAKEHEAD: if (image_snake == NULL) { MLV_draw_filled_rectangle(x, y, cell_size, cell_size, MLV_COLOR_GREEN); } else { MLV_draw_image(image_snake_head, x, y); } break; case BOOST: if (image_boost == NULL) { MLV_draw_filled_rectangle(x, y, cell_size, cell_size, MLV_COLOR_YELLOW); } else { MLV_draw_image(image_boost, x, y); } break; default: MLV_draw_filled_rectangle(x, y, cell_size, cell_size, MLV_COLOR_BLACK); break; } } } } void place_snake(Grid *g, struct SnakeStruct *snake) { Position *current = snake->segments_list; if (current != NULL) { g->grid[current->y][current->x] = SNAKEHEAD; current = current->next; } while (current != NULL) { g->grid[current->y][current->x] = SNAKE; current = current->next; } } Element move_snake(struct SnakeStruct *snake, Grid *g) { Position *tail = snake->segments_list; Position *head; Element element_at_head; while (tail->next != NULL) { tail = tail->next; } g->grid[tail->y][tail->x] = EMPTY; crawl(snake, g); head = snake->segments_list; element_at_head = g->grid[head->y][head->x]; g->grid[head->y][head->x] = SNAKEHEAD; if (head->next != NULL) { g->grid[head->next->y][head->next->x] = SNAKE; } return element_at_head; } int count_nb_lines(FILE *stream) { int count = 0; char buffer[256]; while (fgets(buffer, sizeof(buffer), stream)) { count++; } rewind(stream); return count; } int count_fruits(FILE *stream, Grid *g) { int i, j, nb_fruit = 0; for (i = 0; i < g->nbl; i++) { if (!fgets(g->grid[i], g->nbc + 2, stream)) { fprintf(stderr, "Error: Stream does not contain enough lines\n"); exit(EXIT_FAILURE); } g->grid[i][strcspn(g->grid[i], "\n")] = '\0'; for (j = 0; j < g->nbc; j++) { if (g->grid[i][j] == FRUIT) { nb_fruit++; } } } return nb_fruit; } void copy(const char *src, char *dst) { int i = 0; while (src[i] != '\0' && src[i] != '\n') { dst[i] = src[i]; i++; } dst[i] = '\0'; } static bool are_adjacent(Position *a, Position *b) { return (a->x == b->x && abs(a->y - b->y) == 1) || (a->y == b->y && abs(a->x - b->x) == 1); } int is_snake_connected(struct SnakeStruct *snake) { Position *current = snake->segments_list; while (current && current->next) { if (!are_adjacent(current, current->next)) { return 0; } current = current->next; } return 1; } void read_snake_from_grid(Grid *g, struct SnakeStruct *snake) { Position *positions = malloc(g->nbl * g->nbc * sizeof(Position)); int positions_count = 0; Position *head = NULL; Position *current; int i; int *used = NULL; for (i = 0; i < g->nbl; i++) { int j; for (j = 0; j < g->nbc; j++) { if (g->grid[i][j] == SNAKE || g->grid[i][j] == SNAKEHEAD) { positions[positions_count].x = j; positions[positions_count].y = i; positions[positions_count].next = NULL; if (g->grid[i][j] == SNAKEHEAD) { head = &positions[positions_count]; } positions_count++; } } } if (head == NULL) { fprintf(stderr, "Error: Snake head (S) not found in the grid.\n"); free(positions); exit(EXIT_FAILURE); } used = malloc(positions_count * sizeof(int)); if (!used) { fprintf(stderr, "Error: Could not allocate memory for used array.\n"); free(positions); exit(EXIT_FAILURE); } for (i = 0; i < positions_count; i++) { used[i] = 0; } add_segment(snake, head->x, head->y); used[head - positions] = 1; current = head; while (1) { int found = 0; int j; for (j = 0; j < positions_count; j++) { if (!used[j] && are_adjacent(current, &positions[j])) { add_segment(snake, positions[j].x, positions[j].y); used[j] = 1; current = &positions[j]; found = 1; break; } } if (!found) { break; } } for (i = 0; i < positions_count; i++) { if (!used[i]) { fprintf(stderr, "Error: Snake is not fully connected in the grid.\n"); free(positions); exit(EXIT_FAILURE); } } snake->dir = determine_initial_direction(g, snake->segments_list); free(positions); free(used); }