From ac48d84a816b518b32ab63ad823421e8e83a578d Mon Sep 17 00:00:00 2001 From: Camden Dixie O'Brien Date: Sat, 22 Mar 2025 13:33:38 +0000 Subject: [PATCH] Refactor to extract update() function --- main.c | 104 +++++++++++++++++++++++++++++++++++---------------------- 1 file changed, 64 insertions(+), 40 deletions(-) diff --git a/main.c b/main.c index b6a63a4..6d103cd 100644 --- a/main.c +++ b/main.c @@ -17,6 +17,17 @@ enum { UNKNOWN = 0xfe, KILLER = 0xfd }; +typedef enum { + FOUND_MINE, + FOUND_SAFE, + FOUND_NOTHING, +} update_res_t; + +typedef struct { + int mines, unknown; + puzz_t field; +} state_t; + static void setadj(puzz_t field, int x, int y, uint8_t from, uint8_t to) { for (int yp = y - 1; yp < y + 2; ++yp) { @@ -46,53 +57,66 @@ static void getadj(puzz_t field, int *x, int *y, uint8_t val) assert(false); } +static update_res_t update(state_t *state, int *x_out, int *y_out) +{ + state->mines = state->unknown = 0; + for (int y = 0; y < HEIGHT; ++y) { + for (int x = 0; x < WIDTH; ++x) { + state->mines += state->field[x][y] == MINE ? 1 : 0; + state->unknown += state->field[x][y] == UNKNOWN ? 1 : 0; + } + } + for (int y = 0; y < HEIGHT; ++y) { + for (int x = 0; x < WIDTH; ++x) { + if (state->field[x][y] == UNKNOWN || state->field[x][y] == MINE) + continue; + + const int mines = countadj(state->field, x, y, MINE); + const int unknowns = countadj(state->field, x, y, UNKNOWN); + if (unknowns == 0) + continue; + + if (mines + unknowns == state->field[x][y]) { + setadj(state->field, x, y, UNKNOWN, MINE); + return FOUND_MINE; + } + + if (mines == state->field[x][y]) { + getadj(state->field, &x, &y, UNKNOWN); + *x_out = x; + *y_out = y; + return FOUND_SAFE; + } + } + } + + return FOUND_NOTHING; +} + static status_t solve(void) { - puzz_t field; - memset(field, UNKNOWN, sizeof(field)); + state_t state = { .mines = 0, .unknown = WIDTH * HEIGHT }; + memset(state.field, UNKNOWN, sizeof(puzz_t)); + + int x = rand() % WIDTH; + int y = rand() % HEIGHT; status_t status; - int total_mines = 0, total_unknowns = WIDTH * HEIGHT; do { - int x = rand() % WIDTH; - int y = rand() % HEIGHT; - - probe: - if (field[x][y] != MINE && (status = probe(x, y, field)) == DEAD) { - field[x][y] = KILLER; + if (state.field[x][y] != MINE + && (status = probe(x, y, state.field)) == DEAD) break; + + update_res_t update_res; + do + update_res = update(&state, &x, &y); + while (update_res == FOUND_MINE); + + if (update_res == FOUND_NOTHING) { + x = rand() % WIDTH; + y = rand() % HEIGHT; } - - update: - total_mines = total_unknowns = 0; - for (y = 0; y < HEIGHT; ++y) { - for (x = 0; x < WIDTH; ++x) { - total_mines += field[x][y] == MINE ? 1 : 0; - total_unknowns += field[x][y] == UNKNOWN ? 1 : 0; - } - } - for (y = 0; y < HEIGHT; ++y) { - for (x = 0; x < WIDTH; ++x) { - if (field[x][y] == UNKNOWN || field[x][y] == MINE) - continue; - - const int mines = countadj(field, x, y, MINE); - const int unknowns = countadj(field, x, y, UNKNOWN); - if (unknowns == 0) - continue; - - if (mines + unknowns == field[x][y]) { - setadj(field, x, y, UNKNOWN, MINE); - goto update; - } - - if (mines == field[x][y]) { - getadj(field, &x, &y, UNKNOWN); - goto probe; - } - } - } - } while (total_mines < NMINES); + } while (state.mines < NMINES); return status; }