diff --git a/movement/watch_faces/complication/higher_lower_game_face.c b/movement/watch_faces/complication/higher_lower_game_face.c index cf5205cd..bbf456bf 100755 --- a/movement/watch_faces/complication/higher_lower_game_face.c +++ b/movement/watch_faces/complication/higher_lower_game_face.c @@ -43,6 +43,8 @@ #define BOARD_DISPLAY_END 9 #define MIN_CARD_VALUE 2 #define MAX_CARD_VALUE 14 +#define DUPLICATES_OF_CARD 4 +#define DECK_COUNT (DUPLICATES_OF_CARD * (MAX_CARD_VALUE - MIN_CARD_VALUE + 1)) #define FLIP_BOARD_DIRECTION false typedef struct card_t { @@ -73,6 +75,8 @@ static card_t game_board[GAME_BOARD_SIZE] = {0}; static uint8_t guess_position = 0; static uint8_t score = 0; static uint8_t completed_board_count = 0; +static uint8_t _deck[DECK_COUNT]; +static uint8_t _curr_card; static uint8_t generate_random_number(uint8_t num_values) { // Emulator: use rand. Hardware: use arc4random. @@ -83,10 +87,41 @@ static uint8_t generate_random_number(uint8_t num_values) { #endif } +static void stack_deck(uint8_t *array) { + const uint8_t unique_cards = MAX_CARD_VALUE - MIN_CARD_VALUE + 1; + for (uint8_t i = 0; i < unique_cards; i++) + { + for (uint8_t j = 0; j < DUPLICATES_OF_CARD; j++) + array[(i * DUPLICATES_OF_CARD) + j] = MIN_CARD_VALUE + i; + } +} + +static void shuffle_deck(uint8_t *array, uint8_t n) { + // Randomize shuffle with Fisher Yates + uint8_t i, j, tmp; + for (i = n - 1; i > 0; i--) { + j = generate_random_number(0xFF) % (i + 1); + tmp = array[j]; + array[j] = array[i]; + array[i] = tmp; + } +} + +static void reset_deck(void) { + _curr_card = 0; + stack_deck(_deck); + shuffle_deck(_deck, DECK_COUNT); +} + +static uint8_t get_next_card(void) { + if (_curr_card >= DECK_COUNT) reset_deck(); + return _deck[_curr_card++]; +} + static void reset_board(bool first_round) { // First card is random on the first board, and carried over from the last position on subsequent boards const uint8_t first_card_value = first_round - ? generate_random_number(MAX_CARD_VALUE - MIN_CARD_VALUE + 1) + MIN_CARD_VALUE + ? get_next_card() : game_board[GAME_BOARD_SIZE - 1].value; game_board[0].value = first_card_value; @@ -95,7 +130,7 @@ static void reset_board(bool first_round) { // Fill remainder of board for (size_t i = 1; i < GAME_BOARD_SIZE; ++i) { game_board[i] = (card_t) { - .value = generate_random_number(MAX_CARD_VALUE - MIN_CARD_VALUE + 1) + MIN_CARD_VALUE, + .value = get_next_card(), .revealed = false }; } @@ -105,6 +140,7 @@ static void init_game(void) { watch_clear_display(); watch_display_string(TITLE_TEXT, BOARD_DISPLAY_START); watch_display_string("GA", STATUS_DISPLAY_START); + reset_deck(); reset_board(true); score = 0; completed_board_count = 0;