/* * Copyright (c) Camden Dixie O'Brien * SPDX-License-Identifier: AGPL-3.0-only */ #include "puzz.h" #include #include #include #include #include enum { NO = 0, YES = 1 }; static puzz_t soln; static puzz_t scanned; void gen(void) { memset(soln, 0, sizeof(soln)); for (int i = 0; i < NMINES; ++i) { int x, y; do { x = rand() % WIDTH; y = rand() % HEIGHT; } while (soln[x][y] == MINE); soln[x][y] = MINE; } for (int y = 0; y < HEIGHT; ++y) { for (int x = 0; x < WIDTH; ++x) { if (soln[x][y] == MINE) continue; soln[x][y] = countadj(soln, x, y, MINE); } } } void print(puzz_t puzz) { for (int y = 0; y < HEIGHT; ++y) { for (int x = 0; x < WIDTH; ++x) { char c; switch (puzz[x][y]) { case MINE: c = 'x'; break; case UNKNOWN: c = '.'; break; default: c = '0' + puzz[x][y]; break; } putchar(c); } putchar('\n'); } putchar('\n'); } void printsoln(void) { puts("Solution:"); print(soln); } static void scan_copy(int x, int y, puzz_t out) { assert(x >= 0 && x < WIDTH); assert(y >= 0 && y < HEIGHT); out[x][y] = soln[x][y]; scanned[x][y] = YES; if (soln[x][y] != 0) return; for (int yp = y - 1; yp < y + 2; ++yp) { for (int xp = x - 1; xp < x + 2; ++xp) { if (xp < 0 || xp >= WIDTH || yp < 0 || yp >= HEIGHT || scanned[xp][yp] == YES) continue; scan_copy(xp, yp, out); } } } status_t probe(int x, int y, puzz_t out) { assert(x >= 0 && x < WIDTH); assert(y >= 0 && y < HEIGHT); if (soln[x][y] == MINE) return DEAD; memset(scanned, NO, sizeof(scanned)); scan_copy(x, y, out); return OK; } status_t check(puzz_t puzz) { for (int y = 0; y < HEIGHT; ++y) { for (int x = 0; x < WIDTH; ++x) { if (puzz[x][y] != UNKNOWN && puzz[x][y] != soln[x][y]) return INCORRECT; } } return OK; } int countadj(puzz_t field, int x, int y, uint8_t val) { int n = 0; for (int yp = y - 1; yp < y + 2; ++yp) { for (int xp = x - 1; xp < x + 2; ++xp) { if (xp < 0 || xp >= WIDTH || yp < 0 || yp >= HEIGHT || (xp == x && yp == y)) continue; n += field[xp][yp] == val ? 1 : 0; } } return n; }