-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathgame.c
More file actions
233 lines (205 loc) · 6.33 KB
/
game.c
File metadata and controls
233 lines (205 loc) · 6.33 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
#include "game.h"
#include <assert.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
typedef struct {
int nb_bombs_around; // number of bombs around the square, -1 if it's a bomb
bool flag; // True if there is a flag on the square, false else
bool is_shown; // True if nb_bombs_around has been revealed, false else
} square; // a case (i,j)
struct game_s {
int nb_rows;
int nb_cols;
int nb_bombs; // total number of bombs in the game
square **grid; // Game grid, composed of squares
int nb_flags;
};
void game_print(game g) {
assert(g != NULL);
for (int i = 0; i < get_nb_rows(g); i++) {
for (int j = 0; j < get_nb_cols(g); j++) {
printf("%i ", get_number_bombs_around(g, i, j));
}
printf("\n");
}
printf("\n");
for (int i = 0; i < get_nb_rows(g); i++) {
for (int j = 0; j < get_nb_cols(g); j++) {
printf("%i ", is_shown(g, i, j));
}
printf("\n");
}
}
/* Returns the number of bombs around the square of the cas (i,j) */
int get_number_bombs_around(game g, int i, int j) {
assert(g != NULL);
return g->grid[i][j].nb_bombs_around;
}
int get_nb_rows(game g) {
assert(g != NULL);
return g->nb_rows;
}
int get_nb_cols(game g) {
assert(g != NULL);
return g->nb_cols;
}
int get_nb_bombs(game g) {
assert(g != NULL);
return g->nb_bombs;
}
/* Sets the number of bombs around the cas (i,j) to nb */
void set_number_bombs_around(game g, int i, int j, int nb) { g->grid[i][j].nb_bombs_around = nb; }
/* Returns true if the case (i,j) is in the grid, False else */
bool is_inside_grid(game g, int i, int j) { return (i >= 0 && j >= 0 && i < get_nb_rows(g) && j < get_nb_cols(g)); }
/********** Retuns the number of bombs around the case (i,j) *********/
int number_bombs_around(game g, int i, int j) {
int cpt = 0;
for (int k = i - 1; k <= i + 1; k++) {
for (int l = j - 1; l <= j + 1; l++) {
if (is_inside_grid(g, k, l) && g->grid[k][l].nb_bombs_around == -1 && (k != i || l != j)) { // if the case(k,l)!=(i,j) and there is a bomb in the case (k,l)
cpt++;
}
}
}
return cpt;
}
/******** Fills the grid with bombs and fills numbers in the others cases ***********/
void init_grid(game g, int x, int y) {
for (int i = 0; i < get_nb_rows(g); i++) {
for (int j = 0; j < get_nb_cols(g); j++) {
g->grid[i][j].flag = false; // no flags yet
set_number_bombs_around(g, i, j, 10); // impossible number -> to delete
g->grid[i][j].is_shown = false;
}
}
set_number_bombs_around(g, x, y, 0); // no bomb where the user has clicked
// No bomb around where the user has clicked
for (int k = x - 1; k <= x + 1; k++) {
for (int l = y - 1; l <= y + 1; l++) {
if (is_inside_grid(g, k, l) && (k != x || l != y)) {
set_number_bombs_around(g, k, l, 11);
}
}
}
/* Pose random bombs */
int tmp_x, tmp_y;
for (int n = 0; n < get_nb_bombs(g); n++) {
srand(time(NULL));
do {
tmp_x = rand();
// printf("rand_x=%d\n", tmp_x);
tmp_x = tmp_x % get_nb_rows(g);
tmp_y = rand();
// printf("rand_y=%d\n", tmp_y);
tmp_y = tmp_y % get_nb_cols(g);
} while (get_number_bombs_around(g, tmp_x, tmp_y) < 1 || get_number_bombs_around(g, tmp_x, tmp_y) == 11);
// printf("n=%d, x=%d, y=%d\n",n,tmp_x,tmp_y);
set_number_bombs_around(g, tmp_x, tmp_y, -1);
}
/* Filling grid in function of bombs */
for (int i = 0; i < get_nb_rows(g); i++) {
for (int j = 0; j < get_nb_cols(g); j++) {
if (get_number_bombs_around(g, i, j) == 10 || get_number_bombs_around(g, i, j) == 11) {
int nb = number_bombs_around(g, i, j);
set_number_bombs_around(g, i, j, nb);
}
}
}
}
/*** Allocation of the game structure ****/
game game_init(int nb_rows, int nb_cols, int nb_bombs, int x, int y) {
game g = malloc(sizeof(struct game_s));
assert(g != NULL);
g->grid = calloc(nb_rows, sizeof(square *));
if (g->grid == NULL) {
free(g);
fprintf(stderr, "Erreur d'allocation.\n");
exit(EXIT_FAILURE);
}
for (int i = 0; i < nb_rows; i++) {
g->grid[i] = calloc(nb_cols, sizeof(square));
if (g->grid[i] == NULL) {
for (int j = 0; j < i; j++) {
free(g->grid[j]);
}
free(g->grid);
free(g);
fprintf(stderr, "Erreur d'allocation.\n");
exit(EXIT_FAILURE);
}
}
g->nb_rows = nb_rows;
g->nb_cols = nb_cols;
g->nb_bombs = nb_bombs;
g->nb_flags = 0;
init_grid(g, x, y); // initialize the grid in function of the game parameters
return g;
}
void game_delete(game g) {
if (g == NULL) {
return;
}
for (int i = 0; i < get_nb_rows(g); i++) {
if (g->grid[i] != NULL) {
free(g->grid[i]);
}
}
if (g->grid != NULL) {
free(g->grid);
}
free(g);
}
/* Return true if there is a flag in the case (i,j), False else */
bool is_flagged(game g, int i, int j) { return g->grid[i][j].flag; }
/* Puts a flag in case (i,j) */
void pose_flag(game g, int i, int j) {
g->grid[i][j].flag = true;
g->nb_flags++;
}
/* Removes the flag in case (i,j) */
void remove_flag(game g, int i, int j) {
g->grid[i][j].flag = false;
g->nb_flags--;
}
int get_nb_flags(game g) {
if (g == NULL) {
return 0;
}
return g->nb_flags;
}
/* Returns true if the number in the case (i,j) has been revealed, False else */
bool is_shown(game g, int i, int j) {
assert(g != NULL);
return g->grid[i][j].is_shown;
}
/* Reveals the number in case (i,j) */
void show(game g, int i, int j) {
assert(g != NULL);
assert(g->grid != NULL);
g->grid[i][j].is_shown = !is_flagged(g, i, j);
}
/* (Recursive) Reveals case and the others around if the case is a zero */
void reveal_case(game g, int i, int j) {
show(g, i, j); // reveals current case
for (int k = i - 1; k <= i + 1; k++) {
for (int l = j - 1; l <= j + 1; l++) {
if (is_inside_grid(g, k, l) && (k != i || l != j) && !is_shown(g, k, l) && get_number_bombs_around(g, i, j) == 0) {
reveal_case(g, k, l);
}
}
}
}
/* Return True if the player has won the Game, False else */
bool has_won(game g) {
assert(g != NULL);
for (uint i = 0; i < g->nb_rows; i++) {
for (uint j = 0; j < g->nb_cols; j++) {
if ((get_number_bombs_around(g, i, j) == -1 && !is_flagged(g, i, j)) || (get_number_bombs_around(g, i, j) != -1 && !is_shown(g, i, j))) {
return false;
}
}
}
return true;
}