added game over screen

This commit is contained in:
2024-12-21 13:58:45 +03:00
parent 3e368fffb7
commit 713874fc27

View File

@@ -42,9 +42,10 @@ void free_minefield(Minefield* mf);
char cell_char(cell c); char cell_char(cell c);
void print_minefield(Minefield *mf, FILE *stream); void print_minefield(Minefield *mf, FILE *stream);
void draw_minefield(Minefield* mf); void draw_minefield(Minefield* mf);
void draw_time(Minefield* mf, float time);
cell* clicked_cell(Minefield* mf, int x, int y); cell* clicked_cell(Minefield* mf, int x, int y);
void expose_cell(Minefield* mf, int r, int c); void expose_cell(Minefield* mf, int r, int c);
void handle_click(Minefield* mf); bool handle_click(Minefield* mf);
typedef enum screens { typedef enum screens {
DEFAULT_SCREEN, DEFAULT_SCREEN,
@@ -54,7 +55,7 @@ typedef enum screens {
} Screen; } Screen;
Screen game_loop(Minefield* mf); Screen game_loop(Minefield* mf);
/* Screen game_over(Minefield* mf); */ Screen game_over_loop(Minefield* mf);
Screen help_loop(Minefield *mf); Screen help_loop(Minefield *mf);
Screen (*screen_fn(Screen scr))(Minefield *); Screen (*screen_fn(Screen scr))(Minefield *);
@@ -65,14 +66,14 @@ const int screenHeight = 450;
float cell_size; float cell_size;
int mark_count; int mark_count;
bool dead; bool dead;
bool quit; float end_time;
Screen (*loop)(Minefield*);
int main(){ int main(){
srand(time(NULL)); srand(time(NULL));
Minefield mf = make_minefield(10, 20, 30); Minefield mf = make_minefield(10, 20, 30);
/* print_minefield(&mf, stdout); */ /* print_minefield(&mf, stdout); */
dead = false; dead = false;
quit = false;
mark_count = 0; mark_count = 0;
{ {
float width = (float) screenWidth / mf.col; float width = (float) screenWidth / mf.col;
@@ -85,8 +86,7 @@ int main(){
Screen screen = GAME_LOOP; Screen screen = GAME_LOOP;
Screen temp_screen; Screen temp_screen;
Screen (*loop)(Minefield*); while(!WindowShouldClose()){
while(!WindowShouldClose() && !quit){
loop = screen_fn(screen); loop = screen_fn(screen);
temp_screen = (*loop)(&mf); temp_screen = (*loop)(&mf);
last_screen = screen; last_screen = screen;
@@ -99,19 +99,20 @@ int main(){
} }
Screen game_loop(Minefield* mf){ Screen game_loop(Minefield* mf){
while(!WindowShouldClose() && !quit){ while(!WindowShouldClose()){
if (IsKeyPressed(KEY_H)){ if (IsKeyPressed(KEY_H)){
return HELP; return HELP;
} }
if (!dead){ if (handle_click(mf)){
handle_click(mf); return GAME_OVER;
} }
BeginDrawing(); BeginDrawing();
ClearBackground(RAYWHITE); ClearBackground(RAYWHITE);
draw_minefield(mf); draw_minefield(mf);
draw_time(mf, GetTime());
EndDrawing(); EndDrawing();
} }
return DEFAULT_SCREEN; return DEFAULT_SCREEN;
@@ -129,14 +130,31 @@ Screen help_loop(Minefield *mf) {
return last_screen; return last_screen;
} }
Screen game_over_loop(Minefield* mf){
char* end_text = dead ? "You Died!" : "You Win!";
while(!WindowShouldClose()){
if (IsKeyPressed(KEY_H)){
return HELP;
}
BeginDrawing();
ClearBackground(RAYWHITE);
draw_minefield(mf);
draw_time(mf, end_time);
DrawText(end_text, screenWidth / 2, screenHeight / 2, 30, BLACK);
EndDrawing();
}
return DEFAULT_SCREEN;
}
Screen (*screen_fn(Screen scr))(Minefield *) { Screen (*screen_fn(Screen scr))(Minefield *) {
switch (scr) { switch (scr) {
case GAME_LOOP: case GAME_OVER:
return game_loop; return game_over_loop;
/* case GAME_OVER: */
/* return game_loop; */
case HELP: case HELP:
return help_loop; return help_loop;
case GAME_LOOP:
default: default:
return game_loop; return game_loop;
} }
@@ -229,10 +247,13 @@ void draw_minefield(Minefield* mf){
} }
} }
} }
}
void draw_time(Minefield* mf, float time){
char time_str[20]; char time_str[20];
float time = GetTime(); float t = time;
snprintf(time_str, 20, "%02d.%02d - %d/%d", snprintf(time_str, 20, "%02d.%02d - %d/%d",
(int) time / 60, (int) time % 60, (int) t / 60, (int) t % 60,
mark_count, mf->mine_count); mark_count, mf->mine_count);
DrawText(time_str, screenWidth / 2 - 20, screenHeight - 30, 20, BLACK); DrawText(time_str, screenWidth / 2 - 20, screenHeight - 30, 20, BLACK);
} }
@@ -263,23 +284,24 @@ void expose_cell(Minefield* mf, int r, int c){
} }
} }
void handle_click(Minefield* mf){ bool handle_click(Minefield* mf){
if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT)){ if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT)){
int r = GetMouseY() / cell_size; int r = GetMouseY() / cell_size;
int c = GetMouseX() / cell_size; int c = GetMouseX() / cell_size;
if (!(r >= 0 && r < mf->row && c >= 0 && c < mf->col)) { if (!(r >= 0 && r < mf->row && c >= 0 && c < mf->col)) {
printf("Click outside range, (%d, %d)\n", r, c); printf("Click outside range, (%d, %d)\n", r, c);
return; return false;
} }
cell cell = get_cell(mf, r, c); cell cell = get_cell(mf, r, c);
if (cell & MARKED){ if (cell & MARKED){
return; return false;
} else if (cell & MINE){ } else if (cell & MINE){
printf("DIED\n"); printf("DIED\n");
expose_cell(mf, r, c); expose_cell(mf, r, c);
dead = true; end_time = GetTime();
return dead = true;
} else { } else {
expose_cell(mf, r, c); expose_cell(mf, r, c);
} }
@@ -289,25 +311,22 @@ void handle_click(Minefield* mf){
if (!(r >= 0 && r < mf->row && c >= 0 && c < mf->col)) { if (!(r >= 0 && r < mf->row && c >= 0 && c < mf->col)) {
printf("Click outside range, (%d, %d)\n", r, c); printf("Click outside range, (%d, %d)\n", r, c);
return; return false;
} }
mark_count += mf->cells[r * mf->col + c] & MARKED ? -1 : 1; mark_count += mf->cells[r * mf->col + c] & MARKED ? -1 : 1;
mf->cells[r * mf->col + c] ^= MARKED; mf->cells[r * mf->col + c] ^= MARKED;
bool sol = true;
if (mark_count == mf->mine_count){ if (mark_count == mf->mine_count){
for (int i = 0; i < mf->row * mf->col; i++){ for (int i = 0; i < mf->row * mf->col; i++){
cell cel = mf->cells[i] & (MARKED | MINE); cell cel = mf->cells[i] & (MARKED | MINE);
if (cel & MARKED && !(cel & MINE)){ if (cel & MARKED && !(cel & MINE)){
sol = false; return false;
break;
} }
} }
if (sol){ end_time = GetTime();
printf("Solved\n"); return true;
quit = true;
}
} }
} }
return false;
} }