diff options
Diffstat (limited to 'comp1511')
| -rw-r--r-- | comp1511/cs_beats/beats.c | 412 | ||||
| -rw-r--r-- | comp1511/cs_beats/test_beats.c | 190 | ||||
| -rw-r--r-- | comp1511/minesweeper/minesweeper.c | 326 |
3 files changed, 928 insertions, 0 deletions
diff --git a/comp1511/cs_beats/beats.c b/comp1511/cs_beats/beats.c new file mode 100644 index 0000000..2f26898 --- /dev/null +++ b/comp1511/cs_beats/beats.c @@ -0,0 +1,412 @@ +// Assignment 2 20T1 COMP1511: CS bEats +// beats.c +// +// The purpose of this program is to categorise music input. +// +// Version 1.0.0: Assignment released. +// Version 1.0.1: Fix default return value of add_musical_note_to_beat. + +#include <assert.h> +#include <ctype.h> +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> + +#include "beats.h" + +struct track { + struct beat *head; + struct beat *cur; +}; + +struct beat { + struct note *notes; + struct beat *next; +}; + +struct note { + int oct; + int key; + struct note *next; +}; + +//////////////////////////////////////////////////////////////////////// +// User Defined Functions // +//////////////////////////////////////////////////////////////////////// + +// Returns a value representing the pitch. +static int get_pitch(const int octave, const int key) { + return (octave * 12) + (key); +} + +// Return a malloced beat with fields initialised. +struct beat *create_beat() { + Beat new_beat = malloc(sizeof(struct beat)); + assert(new_beat != NULL); + + new_beat->next = NULL; + new_beat->notes = NULL; + + return new_beat; +} + +// Returns the tail of a note linked list. +static struct note *get_note_tail(struct note *nhead) { + if (nhead == NULL) { + return NULL; + } + struct note *ret = nhead; + while (ret->next != NULL) { + ret = ret->next; + } + return ret; +} + +// Returns the tail of a beat linked list. +static struct beat *get_beat_tail(struct beat *bhead) { + if (bhead == NULL) { + return NULL; + } + struct beat *ret = bhead; + while (ret->next != NULL) { + ret = ret->next; + } + return ret; +} + +// Returns a malloced Note with fields initialised. +static struct note *create_note() { + struct note *ret = malloc(sizeof(struct note)); + assert(ret != NULL); + + ret->oct = 0; + ret->key = 0; + ret->next = NULL; + return ret; +} + +// Inserts a note into a linked list of notes before the target note. +static void insert_note_before(struct beat *beat, struct note *note, + struct note *target) { + if (beat->notes == target) { + beat->notes = note; + note->next = target; + return; + } + for (struct note *i = beat->notes; i != NULL; i = i->next) { + if (i->next == target) { + i->next = note; + note->next = target; + return; + } + } +} + +//////////////////////////////////////////////////////////////////////// +// Stage 1 Functions // +//////////////////////////////////////////////////////////////////////// + +// Add a note to the end of a beat. +int add_note_to_beat(struct beat *const beat, const int oct, const int key) { + if (oct < 0 || oct >= 10) { + return INVALID_OCTAVE; + } + if (key < 0 || key >= 12) { + return INVALID_KEY; + } + + struct note *ntail = get_note_tail(beat->notes); + if (ntail != NULL) { + if (get_pitch(oct, key) <= get_pitch(ntail->oct, ntail->key)) { + return NOT_HIGHEST_NOTE; + } + } + struct note *new_note = create_note(); + new_note->oct = oct; + new_note->key = key; + new_note->next = NULL; + + if (ntail == NULL) { + beat->notes = new_note; + } else { + ntail->next = new_note; + } + return VALID_NOTE; +} + +// Print the contents of a beat. +void print_beat(struct beat *const beat) { + if (beat == NULL) { + return; + } + if (beat->notes == NULL) { + printf("\n"); + return; + } + for (struct note *i = beat->notes; i != NULL; i = i->next) { + printf("%d ", i->oct); + if (i->key >= 10) { + printf("%d", i->key % 12); + } else { + printf("%d%d", i->key / 12, i->key % 12); + } + if (i->next) { + printf(" | "); + } + } + printf("\n"); +} + +// Count the number of notes in a beat that are in a given octave. +int count_notes_in_octave(struct beat *const beat, int oct) { + if (beat->notes == NULL) { + return 0; + } + int notes = 0; + for (struct note *i = beat->notes; i != NULL; i = i->next) { + if (i->oct == oct) { + ++notes; + } + } + return notes; +} + +//////////////////////////////////////////////////////////////////////// +// Stage 2 Functions // +//////////////////////////////////////////////////////////////////////// + +// Return a malloced track with fields initialized. +struct track *create_track(void) { + struct track *ret = malloc(sizeof(struct track)); + ret->head = NULL; + ret->cur = NULL; + return ret; +} + +// Add a beat after the current beat in a track. +void add_beat_to_track(struct track *track, struct beat *beat) { + if (track->cur != NULL) { // this behaviour may be unwanted + if (track->cur->next != NULL) { + beat->next = track->cur->next; + track->cur->next = beat; + } else { + track->cur->next = beat; + } + } else { + if (track->head == NULL) { + track->head = beat; + } else { + beat->next = track->head; + track->head = beat; + } + } +} + +// Set a track's current beat to the next beat. +int select_next_beat(struct track *track) { + if (track->cur == NULL) { + if (track->head == NULL) { + return TRACK_STOPPED; + } else { + track->cur = track->head; + return TRACK_PLAYING; + } + } else { + if (track->cur->next == NULL) { + track->cur = NULL; + return TRACK_STOPPED; + } else { + track->cur = track->cur->next; + return TRACK_PLAYING; + } + } +} + +// Print the contents of a track. +void print_track(struct track *track) { + if (track->head == NULL) { + return; + } + int count = 1; + for (struct beat *i = track->head; i != NULL; i = i->next) { + if (i == track->cur) { + printf(">"); + } else { + printf(" "); + } + printf("[%d] ", count); + print_beat(i); + ++count; + } +} + +// Count beats after the current beat in a track. +int count_beats_left_in_track(struct track *track) { + int count = 0; + if (track == NULL || track->head == NULL) { + return count; + } + struct beat *i = track->cur; + if (i == NULL) { + i = track->head; + } + for (; i != NULL; i = i->next) { + ++count; + } + if (track->cur) { + --count; + } + return count; +} + +//////////////////////////////////////////////////////////////////////// +// Stage 3 Functions // +//////////////////////////////////////////////////////////////////////// + +// Free the memory of a beat, and any memory it points to. +void free_beat(struct beat *beat) { + if (beat == NULL) { + return; + } + if (beat->notes != NULL) { + struct note *i = beat->notes; + struct note *forwards = i->next; + while (i != NULL) { + forwards = i->next; + free(i); + i = forwards; + } + } + free(beat); +} + +// Free the memory of a track, and any memory it points to. +void free_track(struct track *track) { + if (track == NULL) { + return; + } + if (track->head != NULL) { + struct beat *i = track->head; + struct beat *forwards = i->next; + while (i != NULL) { + forwards = i->next; + free_beat(i); + i = forwards; + } + } + free(track); +} + +// Remove the currently selected beat from a track. +int remove_selected_beat(struct track *track) { + if (track->cur == NULL) { + return TRACK_STOPPED; + } + struct beat *backwards = NULL; + struct beat *forwards = NULL; + for (struct beat *i = track->head; i != NULL; i = i->next) { + if (i == track->cur) { + track->head = i->next; + forwards = i->next; + free_beat(track->cur); + break; + } else if (i->next == track->cur) { + backwards = i; + forwards = i->next->next; + free_beat(track->cur); + backwards->next = forwards; + break; + } + } + if (forwards == NULL) { + track->cur = NULL; + return TRACK_STOPPED; + } else { + track->cur = forwards; + return TRACK_PLAYING; + } +} + +//////////////////////////////////////////////////////////////////////// +// Stage 4 Functions // +//////////////////////////////////////////////////////////////////////// + +// Add note to beat, given its 'musical notation'. +int add_musical_note_to_beat(Beat beat, char *string) { + int oct = string[0] - '0'; + if (oct < 0 || oct > 9) { + return INVALID_MUSICAL_NOTE; + } + int key = 0; + switch (string[1]) { + case 'A': + key = 0; + break; + case 'B': + key = 2; + break; + case 'C': + key = 3; + break; + case 'D': + key = 5; + break; + case 'E': + key = 7; + break; + case 'F': + key = 8; + break; + case 'G': + key = 10; + break; + default: + return INVALID_MUSICAL_NOTE; + } + for (char *c = string + 2; *c != '\0'; ++c) { + if (*c == '#') { + ++key; + } else { + return INVALID_MUSICAL_NOTE; + } + } + int pitch = get_pitch(oct, key); + oct = pitch / 12; + key = pitch % 12; + struct note *tail = get_note_tail(beat->notes); + if (tail == NULL || get_pitch(tail->oct, tail->key) < pitch) { + add_note_to_beat(beat, oct, key); + return VALID_NOTE; + } + struct note *higher = NULL; + for (struct note *i = beat->notes; i != NULL; i = i->next) { + int iter_pitch = get_pitch(i->oct, i->key); + if (iter_pitch == pitch) { + return INVALID_MUSICAL_NOTE; + } else if (iter_pitch > pitch) { + higher = i; + break; + } + } + struct note *note = create_note(); + note->oct = oct; + note->key = key; + insert_note_before(beat, note, higher); + return VALID_NOTE; +} + +//////////////////////////////////////////////////////////////////////// +// Stage 5 Functions // +//////////////////////////////////////////////////////////////////////// + +// Cut a range of beats to the end of a track. +void cut_range_to_end(Track track, int range_length) { + printf("cut_range_to_end not implemented yet."); + return; +} + +// Reverse a list of beats within a range of a track. +int reverse_range(Track track, int range_length) { + printf("reverse_range not implemented yet."); + return 0; +} diff --git a/comp1511/cs_beats/test_beats.c b/comp1511/cs_beats/test_beats.c new file mode 100644 index 0000000..d1eb793 --- /dev/null +++ b/comp1511/cs_beats/test_beats.c @@ -0,0 +1,190 @@ +// Assignment 2 20T1 COMP1511: CS bEats +// test_beats.c +// +// This program was written by YOUR-NAME-HERE (z5555555) +// on INSERT-DATE-HERE +// +// Version 1.0.0: Assignment released. +#include <stdio.h> +#include <stdlib.h> + +#include "beats.h" +#include "test_beats.h" + +// Test function for `add_note_to_beat` +int test_add_note_to_beat(void) { + // Test 1: Rejecting negative inputs. + Beat test_beat = create_beat(); + if (add_note_to_beat(test_beat, -1, -1) != INVALID_OCTAVE) { + return DOES_NOT_MEET_SPEC; + } + if (add_note_to_beat(test_beat, -1, 0) != INVALID_OCTAVE) { + return DOES_NOT_MEET_SPEC; + } + if (add_note_to_beat(test_beat, 1, -1) != INVALID_KEY) { + return DOES_NOT_MEET_SPEC; + } + // Test 2: Rejecting invalid pitch notes. + if (add_note_to_beat(test_beat, 1, 1) != VALID_NOTE) { + return DOES_NOT_MEET_SPEC; + } + if (add_note_to_beat(test_beat, 1, 0) != NOT_HIGHEST_NOTE) { + return DOES_NOT_MEET_SPEC; + } + // Test 3: Accepting valid inputs. + if (add_note_to_beat(test_beat, 1, 2) != VALID_NOTE) { + return DOES_NOT_MEET_SPEC; + } + return MEETS_SPEC; +} + +// Test function for `count_notes_in_octave` this is broken +int test_count_notes_in_octave(void) { + // Test 1: Counting invalid octaves. + Beat test_beat = create_beat(); + add_note_to_beat(test_beat, 1, 1); + if (count_notes_in_octave(test_beat, -1) != 0) { + return DOES_NOT_MEET_SPEC; + } + if (count_notes_in_octave(test_beat, 11) != 0) { + return DOES_NOT_MEET_SPEC; + } + // Test 2: Counting valid octaves. + if (count_notes_in_octave(test_beat, 1) != 1) { + return DOES_NOT_MEET_SPEC; + } + if (count_notes_in_octave(test_beat, 1) == 0) { + return DOES_NOT_MEET_SPEC; + } + // Test 3: Counting without any notes + struct beat *empty_beat = create_beat(); + if (count_notes_in_octave(empty_beat, 0) != 0) { + return DOES_NOT_MEET_SPEC; + } + // Test 4: Counting the correct amount + add_note_to_beat(test_beat, 2, 1); + add_note_to_beat(test_beat, 2, 2); + if (count_notes_in_octave(test_beat, 2) != 2) { + return DOES_NOT_MEET_SPEC; + } + add_note_to_beat(test_beat, 2, 3); + if (count_notes_in_octave(test_beat, 2) != 3) { + return DOES_NOT_MEET_SPEC; + } + return MEETS_SPEC; +} + +// These struct definitions are required for the following tests. +// They access the fields directly instead of using other functions as tests, +// which could be considered unsafe as they are not guaranteed to be correct. +// We only want to test a single function, not other functions indirectly. +struct track { + struct beat *head; + struct beat *cur; +}; + +struct beat { + struct note *notes; + struct beat *next; +}; + +// Test function for `add_beat_to_track` +int test_add_beat_to_track(void) { + // Test 1: Test if the beat gets added correctly. + struct track *test_track = create_track(); + struct beat *test_beat = create_beat(); + add_beat_to_track(test_track, test_beat); + if (test_track->head == NULL) { + return DOES_NOT_MEET_SPEC; + } + // Test 2: Ensure the beat is a shallow copy. + if (test_track->head != test_beat) { + return DOES_NOT_MEET_SPEC; + } + // Test 3: Test if the expected fields are NULL. + if (test_track->cur != NULL) { + return DOES_NOT_MEET_SPEC; + } + if (test_track->head->notes != NULL) { + return DOES_NOT_MEET_SPEC; + } + // Test 4: Ensure adding muliple beats works correctly. + struct beat *test_beat2 = create_beat(); + add_beat_to_track(test_track, test_beat2); + if (test_track->head != test_beat2) { + return DOES_NOT_MEET_SPEC; + } + // Test 5: Ensure the last field is still NULL. + if (test_track->head->next->next != NULL) { + return DOES_NOT_MEET_SPEC; + } + return MEETS_SPEC; +} + +// Test function for `remove_selected_beat` +int test_remove_selected_beat(void) { + // Test 1: Ensure the correct return type on a track with no selected beat. + struct track *test_track = create_track(); + struct beat *test_beat = create_beat(); + add_beat_to_track(test_track, test_beat); + if (remove_selected_beat(test_track) != TRACK_STOPPED) { + return DOES_NOT_MEET_SPEC; + } + // Test 2: Ensure that no beat has been deleted after the previous test. + if (test_track->head == NULL) { + return DOES_NOT_MEET_SPEC; + } + // Test 3: Ensure the track is still playing after the attempted removal. + if (test_track->cur != NULL) { + return DOES_NOT_MEET_SPEC; + } + // Test 4: Ensure the correct return type on a track with a selected beat. + select_next_beat(test_track); + if (remove_selected_beat(test_track) != TRACK_STOPPED) { + return DOES_NOT_MEET_SPEC; + } + // Test 5: Ensure the beat has been deleted correct after the previous test. + if (test_track->head != NULL) { + return DOES_NOT_MEET_SPEC; + } + // Test 6: Ensure the track is not playing after beat removal. + if (test_track->cur != NULL) { + return DOES_NOT_MEET_SPEC; + } + return MEETS_SPEC; +} + +// Another struct definition which is required for testing below. +// This can probably be considered bad practice as struct defintions should not +// be simply copied across multiple files, but compared to the alternative +// of invoking potentially broken functions, this is preferable. +struct note { + int oct; + int key; + struct note *next; +}; + +// Test function for `add_musical_note_to_beat` +int test_add_musical_note_to_beat(void) { + // Test 1: Ensure the beat is added to an empty beat. + struct beat *test_beat = create_beat(); + add_musical_note_to_beat(test_beat, "2C#"); + if (test_beat->notes == NULL) { + return DOES_NOT_MEET_SPEC; + } + // Test 2: Ensure the beat has the correct pitch. + if (test_beat->notes->oct != 2 || test_beat->notes->key != 4) { + return DOES_NOT_MEET_SPEC; + } + // Test 3: Ensure a higher beat is added when appropriate. + add_musical_note_to_beat(test_beat, "2C##"); + if (test_beat->notes->next == NULL) { + return DOES_NOT_MEET_SPEC; + } + // Test 4: Ensure that a lower beat is added when appropriate. + add_musical_note_to_beat(test_beat, "2C"); + if (test_beat->notes->oct != 2 || test_beat->notes->key != 3) { + return DOES_NOT_MEET_SPEC; + } + return MEETS_SPEC; +} diff --git a/comp1511/minesweeper/minesweeper.c b/comp1511/minesweeper/minesweeper.c new file mode 100644 index 0000000..8a892ed --- /dev/null +++ b/comp1511/minesweeper/minesweeper.c @@ -0,0 +1,326 @@ +// Assignment 1 20T1 COMP1511: Minesweeper +// minesweeper.c + +#include <stdio.h> +#include <stdbool.h> + +// Possible square states. +#define VISIBLE_SAFE 0 +#define HIDDEN_SAFE 1 +#define HIDDEN_MINE 2 +#define EXPLODED_MINE 3 + +// The size of the starting grid. +#define SIZE 8 + +// The possible command codes. +#define DETECT_ROW 1 +#define DETECT_COL 2 +#define DETECT_SQUARE 3 +#define REVEAL_SQUARE 4 +#define GAMEPLAY_MODE 5 +#define DEBUG_MODE 6 +#define REVEAL_RADIAL 7 + +// All game states +#define GAME_LOST -1 +#define GAME_ONGOING 0 +#define GAME_WON 1 + +// Miscellaneous values +// Max hints: +#define MAX_HINTS 3 +// Start in debug mode (non-zero for true): +#define DEBUG_DEFAULT 1 + +// Out of bounds check for x and y values. True if valid. +static bool is_valid(const int x, const int y) { + if (x > SIZE - 1 || x < 0) { + return false; + } + if (y > SIZE - 1 || y < 0) { + return false; + } + return true; +} + +// Searches entire minefield for a value. True if found. +static bool search_minefield(const int minefield[SIZE][SIZE], const int search) { + for (int i = 0; i < SIZE; ++i) { + for (int j = 0; j < SIZE; ++j) { + if (minefield[i][j] == search) { + return true; + } + } + } + return false; +} + +// Returns the prior defined game state. +static int get_game_state(const int minefield[SIZE][SIZE]) { + if (search_minefield(minefield, EXPLODED_MINE)) { + return GAME_LOST; + } + else if (search_minefield(minefield, HIDDEN_SAFE)) { + return GAME_ONGOING; + } + return GAME_WON; +} + +// Set the entire minefield to HIDDEN_SAFE. +static void initialise_field(int minefield[SIZE][SIZE]) { + for (int i = 0; i < SIZE; ++i) { + for (int j = 0; j < SIZE; ++j) { + minefield[i][j] = HIDDEN_SAFE; + } + } +} + + +// Prints the count of mines per row. +static void detect_row(const int minefield[SIZE][SIZE], const int arg) { + int count = 0; + for (int i = 0; i < SIZE; ++i) { + if (minefield[arg][i] == HIDDEN_MINE) { + ++count; + } + } + printf("There are %d mine(s) in row %d\n", count, arg); +} + +// Prints the count of mines per column. +static void detect_column(const int minefield[SIZE][SIZE], const int arg) { + int count = 0; + for (int i = 0; i < SIZE; ++i) { + if (minefield[i][arg] == HIDDEN_MINE) { + ++count; + } + } + printf("There are %d mine(s) in column %d\n", count, arg); +} + +// Returns the count of mines within a square, drawn forwards and downwards. +static int detect_square(const int minefield[SIZE][SIZE], + int x, + int y, + int size, + int should_print) { + int count = 0; + for (int i = 0; i < size; ++i) { + for (int j = 0; j < size; ++j) { + if (!(is_valid(x + i, y + j))) { + continue; + } + if (minefield[x + i][y + j] == HIDDEN_MINE) { + ++count; + } + } } + if (should_print) { + printf("There are %d mine(s) in the square centered ", count); + printf("at row %d, column %d of size %d\n", x + 1, y + 1, size); + } + return count; +} + +// Modifies the minefield by revealing a point. Reveals adjacent if possible. +static void reveal_square(int minefield[SIZE][SIZE], + const int x, + const int y) { + if (minefield[x][y] == HIDDEN_MINE) { + minefield[x][y] = EXPLODED_MINE; + return; + } + int tmpx = x - 1; + int tmpy = y - 1; + if (detect_square(minefield, tmpx, tmpy, 3, 0)) { + minefield[x][y] = VISIBLE_SAFE; + return; + } + for (int i = 0; i < 3; ++i) { + for (int j = 0; j < 3; ++j) { + if (is_valid(tmpx + i, tmpy + j)) { + minefield[tmpx + i][tmpy + j] = VISIBLE_SAFE; + } + } + } +} + +// Print out the internal values of the minefield. +// Exploded mines are printed as 'HIDDEN_MINE' int to comply with requirement. +static void print_debug_minefield(const int minefield[SIZE][SIZE]) { + for (int i = 0; i < SIZE; ++i) { + for (int j = 0; j < SIZE; ++j) { + if (minefield[i][j] == EXPLODED_MINE) { + printf("%d ", HIDDEN_MINE ); + } else { + printf("%d ", minefield[i][j]); + } + } + printf("\n"); + } +} + +// Prints the minefield in the "gameplay" style. +// This includes the game state face ASCII glyph. +static void print_gameplay_minefield(const int minefield[SIZE][SIZE], + const int game_state) { + if (game_state == GAME_LOST) { + printf("xx\n/\\\n"); + } else { + printf("..\n\\/\n"); + } + printf(" "); + for (int i = 0; i < SIZE; ++i) { + printf("%d%d ", i / 10, i % 10); + } + printf("\n "); + for (int i = 0; i < SIZE; ++i) { + printf("---"); + } + printf("-\n"); + for (int i = 0; i < SIZE; ++i) { + printf("%d%d |", i / 10, i % 10); + for (int j = 0; j < SIZE; ++j) { + int point = minefield[i][j]; + if (point >= HIDDEN_MINE && game_state == GAME_LOST) { + printf("()"); + } + else if (point >= EXPLODED_MINE && game_state == GAME_WON) { + printf("##"); + } + else if (point == HIDDEN_SAFE) { + printf("##"); + } + else if (point == HIDDEN_MINE) { + printf("##"); + } + else if (point == VISIBLE_SAFE) { + int adjacent = detect_square(minefield, i - 1, j - 1, 3, 0); + if (adjacent) { + printf("%d%d", adjacent / 10, adjacent % 10); + } else { + printf(" "); + } + } + if (j < SIZE - 1) { + printf(" "); + } else { + printf("|"); + } + } + printf("\n"); + } + printf(" "); + for (int i = 0; i < SIZE; ++i) { + printf("---"); + } + printf("-\n"); +} + +// Wrapper function for the debug and game mode styles of printing. +static void print_minefield(const int minefield[SIZE][SIZE], + const int debug_mode, + const int game_state) { + if (debug_mode) { + print_debug_minefield(minefield); + } else { + print_gameplay_minefield(minefield, game_state); + } +} + +int main(void) { + int minefield[SIZE][SIZE]; + initialise_field(minefield); + + printf("Welcome to minesweeper!\nHow many mines? "); + int pair_count = 0; + scanf("%d", &pair_count); + + printf("Enter pairs:\n"); + for (int i = 0; i < pair_count; ++i) { + int x = 0, y = 0; + scanf("%d %d", &x, &y); + if (!is_valid(x, y)) { + continue; + } + minefield[x][y] = HIDDEN_MINE; + } + + printf("Game Started\n"); + int game_state = GAME_ONGOING; + int hints = MAX_HINTS; + int debug_mode = DEBUG_DEFAULT; + while(!(game_state = get_game_state(minefield))) { + print_minefield(minefield, debug_mode, game_state); + int command = 0; + if ((scanf(" %d", &command) <= 0)) { + return 0; + } + switch (command) { + case DETECT_ROW : { + int row = 0; + scanf(" %d", &row); + if (hints <= 0) { + printf("Help already used\n"); + break; + } + detect_row(minefield, row); + --hints; + break; + } + case DETECT_COL : { + int col = 0; + scanf(" %d", &col); + if (hints <= 0) { + printf("Help already used\n"); + break; + } + detect_column(minefield, col); + --hints; + break; + } + case DETECT_SQUARE : { + int x = 0; + int y = 0; + int size = 0; + scanf("%d %d %d", &x, &y, &size); + if (hints <= 0) { + printf("Help already used\n"); + break; + } + detect_square(minefield, x - 1, y - 1, size, 1); + --hints; + break; + } + case REVEAL_SQUARE : { + int x = 0; + int y = 0; + scanf("%d %d", &x, &y); + reveal_square(minefield, x , y); + break; + } + case GAMEPLAY_MODE : { + debug_mode = 0; + printf("Gameplay mode activated\n"); + break; + } + case DEBUG_MODE : { + debug_mode = 1; + printf("Debug mode activated\n"); + break; + } + } + } + // Early exit if the game is suspended. + if (game_state == GAME_ONGOING) { + return 0; + } + + if (game_state == GAME_LOST) { + printf("Game over\n"); + } else { + printf("Game Won!\n"); + } + print_minefield(minefield, debug_mode, game_state); + return 0; +} |
