#include "raylib.h" #include #include #include #include "../util.h" typedef char cell; #define MINE 0b10000000 #define MARKED 0b01000000 #define EXPOSED 0b00100000 #define NUMBERED 0b00000111 /* cell is a char (8 bits) 0000 0000 ^^^ ^^^ ||| number of mine neigbours |||> 1 if exposed (revealed) ||> 1 if marked |> 1 if mine */ typedef struct minefield_t { int row; int col; cell* cells; } Minefield; static inline cell get_cell(Minefield* mf, int r, int c){ return mf->cells[r * mf->col + c]; } static inline cell set_cell(Minefield* mf, int r, int c, cell cell){ return mf->cells[r * mf->col + c] = cell; } Minefield make_minefield(int row, int col, int mine_count){ Minefield mf = {.row = row, .col = col}; int size = mf.row * mf.col; mf.cells = (cell *)calloc(size, sizeof(cell)); // 0 initialization for (int i = 0; i < size; i++) { mf.cells[i] = 0; } // Place mines /* float prob = (float) mine_count / f.row * f.col; */ for (int m = mine_count; m > 0;){ for (int i = 0; i < size; i++){ if (!(mf.cells[i] & MINE) && (rand() % size) < mine_count) { mf.cells[i] = MINE; if (--m <= 0) { break; } } } } // Place numbers for (int i = 0; i < mf.row; i++){ for (int j = 0; j < mf.col; j++){ if (!(get_cell(&mf, i, j) & MINE)){ cell c = 0; for (int ii = imax(i - 1, 0); ii < imin(i + 2, mf.row); ii++){ for (int jj = imax(j - 1, 0); jj < imin(j + 2, mf.col); jj++){ if (get_cell(&mf, ii, jj) & MINE){ c++; } } } set_cell(&mf, i, j, c); } } } return mf; } void free_minefield(Minefield* mf){ if (mf){ free(mf->cells); mf->cells = NULL; } } char cell_char(cell c){ if (c & MARKED) { return 'X'; } else if (c & MINE) { return '*'; } else { c &= NUMBERED; return c > 0 ? c + '0' : ' '; } } void print_minefield(Minefield *mf, FILE *stream) { for (int i = 0; i < mf->row; i++) { for (int j = 0; j < mf->col; j++) { fputc('|', stream); cell c = mf->cells[i * mf->col + j]; fputc(cell_char(c), stream); } fputs("|\n", stream); } } const int screenWidth = 800; const int screenHeight = 450; void draw_minefield(Minefield* mf){ float width = (float) screenWidth / mf->col; float height = (float) screenHeight / mf->row; float size = width > height ? height : width; char str[2] = "0"; for (int i = 0; i < mf->row; i++){ for (int j = 0; j < mf->col; j++){ int x = size * j; int y = size * i; DrawRectangleLines(x, y, size, size, BLACK); str[0] = cell_char(mf->cells[i * mf->col + j]); DrawText(str, x + size / 3, y + size / 3, 20, BLACK); } } } int main(){ srand(time(NULL)); Minefield mf = make_minefield(10, 20, 30); print_minefield(&mf, stdout); InitWindow(screenWidth, screenHeight, "Minesweeper"); SetTargetFPS(60); while(!WindowShouldClose()){ BeginDrawing(); ClearBackground(RAYWHITE); draw_minefield(&mf); EndDrawing(); } free_minefield(&mf); return 0; }