commit 5ca06ffd6199159763d1f51d40039f550cdd560b
parent 0bd88c4be3d352ddd23b26bf9d300769aea91fef
Author: Samdal <samdal@protonmail.com>
Date: Sun, 2 May 2021 22:32:22 +0200
bugs, polish, end screen
Diffstat:
M | main.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);
}