minesweeper

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs

commit 5ca06ffd6199159763d1f51d40039f550cdd560b
parent 0bd88c4be3d352ddd23b26bf9d300769aea91fef
Author: Samdal <samdal@protonmail.com>
Date:   Sun,  2 May 2021 22:32:22 +0200

bugs, polish, end screen

Diffstat:
Mmain.c | 141+++++++++++++++++++++++++++++++++++++++++++++++++++----------------------------
1 file changed, 91 insertions(+), 50 deletions(-)

diff --git a/main.c b/main.c @@ -2,26 +2,29 @@ #include <stdlib.h> // Global variables -static bool mouseInput; +#define DEFAULT_BOARD_X 30 +#define DEFAULT_BOARD_Y 20 +#define DEFAULT_BOMBS 70 static Vector2 squareSize; -static int TilesX = 20; -static int TilesY = 20; -static int TotalBombs = 40; +static int TilesX = DEFAULT_BOARD_X; +static int TilesY = DEFAULT_BOARD_Y; +static int TotalBombs = DEFAULT_BOMBS; typedef struct Bombs { int x, y; } Bomb; static Bomb *bombPos; // all bombs position -static bool *shown; // if a tile is hidden -static bool *flags; // if a tile is flagged +static bool **shown; // if a tile is hidden +static bool **flags; // if a tile is flagged +static bool gameOver = false; // function declerations static void ExplodeAllBombs(void); static void NewGame(void); static void UpdateGame(void); static void DrawGame(void); -static void ClearNeighbours(int x, int y); -static bool HasNeighbours(int x, int y); -static void DrawTile(int x, int y); +static void ClearNeighbours(const int *x, const int *y); +static bool HasNeighbours(const int *x, const int *y); +static void DrawTile(const int *x, const int *y); int main(int argc, char *argv[]) { // Set game area and bomb amount with command line args @@ -31,20 +34,26 @@ int main(int argc, char *argv[]) { case 3: TilesY = strtol(argv[2], NULL, 0); if (TilesY <= 0) - TilesY = 20; + TilesY = DEFAULT_BOARD_Y; case 2: TilesX = strtol(argv[1], NULL, 0); if (TilesX <= 0) - TilesX = 20; + TilesX = DEFAULT_BOARD_X; if ((argc == 4) && (TotalBombs <= 0 || TotalBombs >= TilesX * TilesY)) TotalBombs = (TilesX * TilesY) / 7; } - int boardsize = TilesX * TilesY * sizeof(bool); - shown = malloc(boardsize); - flags = malloc(boardsize); + shown = malloc(TilesX * sizeof(bool *)); + flags = malloc(TilesX * sizeof(bool *)); + shown[0] = malloc(TilesX * TilesY * sizeof(bool)); + flags[0] = malloc(TilesX * TilesY * sizeof(bool)); + for (int i = 1; i < TilesX; i++) { + shown[i] = shown[0] + i * TilesY; + flags[i] = flags[0] + i * TilesY; + } bombPos = malloc(TotalBombs * sizeof(Bomb)); - if (bombPos == NULL || shown == NULL || flags == NULL) - return 255; // if memory allocation failed + if (bombPos == NULL || shown == NULL || shown[0] == NULL || flags == NULL || + flags[0] == NULL) + return 255; // memory allocation failed SetConfigFlags(FLAG_WINDOW_RESIZABLE); SetConfigFlags(FLAG_VSYNC_HINT); @@ -58,7 +67,10 @@ int main(int argc, char *argv[]) { // close down and free memory free(bombPos); + free(shown[0]); + free(flags[0]); free(shown); + free(flags); CloseWindow(); return 0; } @@ -71,9 +83,10 @@ void NewGame(void) { } for (int x = 0; x < TilesX; x++) for (int y = 0; y < TilesY; y++) { - shown[x * TilesX + y] = false; - flags[x * TilesX + y] = false; + shown[x][y] = false; + flags[x][y] = false; } + gameOver = false; // place bombs (with no duplicates) for (int i = 0; i < TotalBombs; i++) { @@ -88,50 +101,67 @@ void NewGame(void) { void ExplodeAllBombs(void) { for (int i = 0; i < TotalBombs; i++) - shown[bombPos[i].x * TilesX + bombPos[i].y] = true; + shown[bombPos[i].x][bombPos[i].y] = true; + gameOver = true; } void UpdateGame(void) { - Vector2 mouse = GetMousePosition(); - int mouseX = mouse.x / squareSize.x; - int mouseY = mouse.y / squareSize.y; - int mouseTile = mouseX * TilesX + mouseY; - if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON) && !flags[mouseTile]) { - shown[mouseX * TilesX + mouseY] = true; - if (!HasNeighbours(mouseX, mouseY)) - ClearNeighbours(mouseX, mouseY); + const Vector2 mouse = GetMousePosition(); + const int mouseX = mouse.x / squareSize.x; + const int mouseY = mouse.y / squareSize.y; + if (gameOver) { + if (IsKeyPressed(KEY_SPACE)) { + gameOver = false; + NewGame(); + } + } else if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON) && + !flags[mouseX][mouseY]) { + shown[mouseX][mouseY] = true; + if (!HasNeighbours(&mouseX, &mouseY)) + ClearNeighbours(&mouseX, &mouseY); else for (int i = 0; i < TotalBombs; i++) if (bombPos[i].x == mouseX && bombPos[i].y == mouseY) { ExplodeAllBombs(); break; } + + // calulate if game has ended + int count = 0; + for (int x = 0; x < TilesX; x++) + for (int y = 0; y < TilesY; y++) + if (!shown[x][y]) + count++; + if (count == TotalBombs) + gameOver = true; + } else if (IsMouseButtonPressed(MOUSE_RIGHT_BUTTON)) - if (!shown[mouseTile]) - flags[mouseTile] = !flags[mouseTile]; + if (!shown[mouseX][mouseY]) + flags[mouseX][mouseY] = !flags[mouseX][mouseY]; } -void ClearNeighbours(int x, int y) { +void ClearNeighbours(const int *x, const int *y) { for (int nX = -1; nX <= 1; nX++) { - int xPos = x + nX; + const int xPos = *x + nX; if (xPos < 0 || xPos >= TilesX) continue; for (int nY = -1; nY <= 1; nY++) { - int yPos = y + nY; - int tile = xPos * TilesX + yPos; - if (yPos < 0 || yPos >= TilesY || shown[tile] || flags[tile]) + const int yPos = *y + nY; + if (yPos < 0 || yPos >= TilesY || shown[xPos][yPos] || flags[xPos][yPos]) continue; - shown[tile] = true; - if (!HasNeighbours(xPos, yPos)) - ClearNeighbours(xPos, yPos); // recurse if tile has no neighbours + shown[xPos][yPos] = true; + if (!HasNeighbours(&xPos, &yPos)) + ClearNeighbours(&xPos, &yPos); // recurse if tile has no neighbours } } } -bool HasNeighbours(int x, int y) { +bool HasNeighbours(const int *x, const int *y) { for (int i = 0; i < TotalBombs; i++) - if ((bombPos[i].x == x - 1 || bombPos[i].x == x + 1 || bombPos[i].x == x) && - (bombPos[i].y == y - 1 || bombPos[i].y == y + 1 || bombPos[i].y == y)) + if ((bombPos[i].x == *x - 1 || bombPos[i].x == *x + 1 || + bombPos[i].x == *x) && + (bombPos[i].y == *y - 1 || bombPos[i].y == *y + 1 || + bombPos[i].y == *y)) return true; return false; } @@ -142,34 +172,45 @@ void DrawGame(void) { ClearBackground(GRAY); for (int x = 0; x < TilesX; x++) for (int y = 0; y < TilesY; y++) - if (shown[x * TilesX + y]) - DrawTile(x, y); - else if (flags[x * TilesX + y]) + if (shown[x][y]) + DrawTile(&x, &y); + else if (flags[x][y]) DrawText("?", (x + 0.35f) * squareSize.x, (y + 0.2f) * squareSize.y, squareSize.y * 0.6f, GREEN); + + if (gameOver) { + float xsize = TilesX * 0.2f * squareSize.x; + float ysize = TilesY * 0.2f * squareSize.y; + float fsize = TilesX * 0.1f * squareSize.x; + DrawText("GAME OVER!", xsize, ysize, fsize, GOLD); + DrawText("(press SPACE to replay)", xsize, (TilesY * 0.5f) * squareSize.y, + fsize * 0.5f, GOLD); + } EndDrawing(); } -void DrawTile(int x, int y) { +void DrawTile(const int *x, const int *y) { // find naboring bombs int nearby = 0; for (int i = 0; i < TotalBombs; i++) { - if ((bombPos[i].x == x - 1 || bombPos[i].x == x + 1 || bombPos[i].x == x) && - (bombPos[i].y == y - 1 || bombPos[i].y == y + 1 || bombPos[i].y == y)) + if ((bombPos[i].x == *x - 1 || bombPos[i].x == *x + 1 || + bombPos[i].x == *x) && + (bombPos[i].y == *y - 1 || bombPos[i].y == *y + 1 || + bombPos[i].y == *y)) nearby++; - if (bombPos[i].x == x && bombPos[i].y == y) { - DrawText("x", (x + 0.35f) * squareSize.x, (y + 0.2f) * squareSize.y, + if (bombPos[i].x == *x && bombPos[i].y == *y) { + DrawText("x", (*x + 0.35f) * squareSize.x, (*y + 0.2f) * squareSize.y, squareSize.y * 0.6f, RED); return; } } - Vector2 rectpos = {squareSize.x * (float)x, squareSize.y * (float)y}; + const Vector2 rectpos = {squareSize.x * (float)*x, squareSize.y * (float)*y}; DrawRectangleV(rectpos, squareSize, RAYWHITE); if (nearby == 0) return; const char c[] = {nearby + '0', '\0'}; - DrawText(c, (x + 0.35f) * squareSize.x, (y + 0.2f) * squareSize.y, + DrawText(c, (*x + 0.35f) * squareSize.x, (*y + 0.2f) * squareSize.y, squareSize.y * 0.6f, BLACK); }