1 | #include <stdlib.h> |
2 | #include <time.h> |
3 |
|
4 | #include "../state.h" |
5 |
|
6 | int16_t *nearby_cells(uint16_t s, uint8_t w, uint8_t h) { |
7 | int16_t *cells = malloc(sizeof(int16_t) * 9); |
8 | cells[0] = s - w - 1; |
9 | cells[1] = s - w; |
10 | cells[2] = s - w + 1; |
11 | cells[3] = s - 1; |
12 | cells[4] = s; |
13 | cells[5] = s + 1; |
14 | cells[6] = s + w - 1; |
15 | cells[7] = s + w; |
16 | cells[8] = s + w + 1; |
17 | if (s % w == 0) { // left edge |
18 | cells[0] = s; |
19 | cells[3] = s; |
20 | cells[6] = s; |
21 | } |
22 | if ((s + 1) % w == 0) { // right edge |
23 | cells[2] = s; |
24 | cells[5] = s; |
25 | cells[8] = s; |
26 | } |
27 | if (s < w) { // top edge |
28 | cells[0] = s; |
29 | cells[1] = s; |
30 | cells[2] = s; |
31 | } |
32 | if (s > w * (h - 1)) { // bottom edge |
33 | cells[6] = s; |
34 | cells[7] = s; |
35 | cells[8] = s; |
36 | } |
37 | return cells; |
38 | } |
39 |
|
40 | void new_game(game_board *board) { |
41 | // generate board |
42 | board->mines_left = board->mine_count; |
43 | board->cells = calloc(board->width * board->height, sizeof(game_board_cell)); |
44 |
|
45 | // open start |
46 | uint16_t s = board->current_cell; |
47 |
|
48 | int16_t *open_start_cells = nearby_cells(s, board->width, board->height); |
49 |
|
50 | for (int cell = 0; cell < 9; cell++) { |
51 | board->cells[open_start_cells[cell]].is_bomb = 0; |
52 | board->cells[open_start_cells[cell]].opened = 1; |
53 | } |
54 |
|
55 | free(open_start_cells); |
56 |
|
57 | // generate mines |
58 | int mines_generated = 0; |
59 | uint16_t end = board->width * board->height; |
60 |
|
61 | srand(time(0)); |
62 |
|
63 | while (mines_generated < board->mine_count) { |
64 | int n = rand() % end; |
65 | if (!board->cells[n].is_bomb && !board->cells[n].opened) { |
66 | board->cells[n].is_bomb = 1; |
67 | mines_generated++; |
68 | } |
69 | } |
70 |
|
71 | // get surrounding mine counts |
72 | for (int i = 0; i < end; i++) { |
73 | if (board->cells[i].is_bomb) continue; |
74 | int16_t *close_cells = nearby_cells(i, board->width, board->height); |
75 | for (int j = 0; j < 9; j++) { |
76 | int16_t close_cell = close_cells[j]; |
77 | if (close_cell != i && board->cells[close_cell].is_bomb) board->cells[i].surrounding_bomb_count++; |
78 | } |
79 | free(close_cells); |
80 | } |
81 | } |
82 |
|
83 | void game(game_state *state, int ch) { |
84 | if (ch == 0) { // create new game |
85 | new_game(state->board); |
86 | } |
87 | } |
88 |
|