From d29b37aa1b82dbd3c4baa55396521296f4a88ef4 Mon Sep 17 00:00:00 2001 From: Harishankar Date: Wed, 29 Apr 2020 21:16:23 +0530 Subject: [PATCH] Added freeze/unfreeze grid functionality Added functionality for freeze and unfreeze grid and also setting clues for across words --- constantstrings.h | 11 +++- wordblox.c | 140 ++++++++++++++++++++++++++---------------- wordblox.h | 152 +++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 244 insertions(+), 59 deletions(-) diff --git a/constantstrings.h b/constantstrings.h index 4c1baa2..c8d3b58 100644 --- a/constantstrings.h +++ b/constantstrings.h @@ -2,9 +2,12 @@ #define __CONSTANTSTRINGS_H #define FROZEN_GRID "Grid is frozen. Unfreeze grid first!" +#define UNFROZEN_GRID "Grid is unfrozen. Freeze grid first!" #define EXCEED_GRID_SIZE "Row/col exceeded grid size!" #define INPUT_ROW "Enter the row: " #define INPUT_COL "Enter the col: " +#define INPUT_INDEX "Enter the word index: " +#define INPUT_CLUE "Enter the clue: " #define WORD_TOO_LONG "Word too long" #define INPUT_WORD "Enter the word: " #define INPUT_FILE "Enter the file name: " @@ -17,6 +20,7 @@ #define ERROR_READING_FILE "Error reading file" #define INVALID_WORD "Word contains illegal characters. Only alphabets allowed!" #define FILE_SAVED "File saved successfully" +#define NO_WORD_INDEX "No such word with specified index" char *MAIN_MENU[] = {"1. New puzzle", @@ -29,8 +33,9 @@ char *PUZZLE_EDIT_MENU[] = "3. Add word down", "4. Clear Cell", "5. Freeze grid", - "6. Unfreeze grid", - "7. Save puzzle", - "8. Return to main" }; + "6. Unfreeze grid", + "7. Set Clue - Across Word", + "8. Save puzzle", + "9. Return to main menu" }; #endif diff --git a/wordblox.c b/wordblox.c index 174346d..6ad88e1 100644 --- a/wordblox.c +++ b/wordblox.c @@ -8,67 +8,90 @@ #include "wordblox.h" #include "constantstrings.h" +void set_clue_across_word (Puzzle *p) +{ + print_puzzle (p); + if (p->grid_frozen == false) + { + printf (UNFROZEN_GRID); + char ch = getchar (); + return; + } + int index; + String clue; + printf (INPUT_INDEX); + index = get_num (); + printf (INPUT_CLUE); + fgets (clue, MAX_CLUE_LENGTH, stdin); + char* cl = strtok (clue, "\n"); + + bool res = set_across_clue (p, cl, index); + if (res == false) + printf (NO_WORD_INDEX); +} + /* clear a cell in the grid */ void clear_cell (Puzzle *p) { print_puzzle (p); + if (p->grid_frozen == true) + { + printf (FROZEN_GRID); + char ch = getchar (); + return; + } int row, col; printf (INPUT_ROW); - scanf ("%d", &row); + row = get_num (); printf (INPUT_COL); - scanf ("%d", &col); + col = get_num (); if (row >= p->grid_size || col >= p->grid_size) { printf (EXCEED_GRID_SIZE); char ch = getchar (); - ch = getchar (); return; } p->chars[row][col] = ' '; print_puzzle (p); char ch = getchar (); - ch = getchar (); } /* add a down word to the grid */ void add_down_word (Puzzle *p) { print_puzzle (p); - if (p->grid_frozen) + if (p->grid_frozen == true) { printf (FROZEN_GRID); char ch = getchar (); - ch = getchar (); return; } - char word[MAX_PUZZLE_SIZE]; + char wd[MAX_PUZZLE_SIZE]; int row, col; printf (INPUT_WORD); - scanf ("%s", word); + fgets (wd, MAX_PUZZLE_SIZE, stdin); + char *word = strtok (wd, "\n"); if (! is_valid_word (word)) { printf (INVALID_WORD); char ch = getchar (); - ch = getchar (); return; } printf (INPUT_ROW); - scanf ("%d", &row); + row = get_num (); printf (INPUT_COL); - scanf ("%d", &col); + col = get_num (); if (row >= p->grid_size || col >= p->grid_size) { printf (EXCEED_GRID_SIZE); char ch = getchar (); - ch = getchar (); return; } if (strlen (word) > (p->grid_size - row)) { printf (WORD_TOO_LONG); char ch = getchar (); - ch = getchar (); return; } @@ -77,38 +100,37 @@ void add_down_word (Puzzle *p) print_puzzle (p); char ch = getchar (); - ch = getchar (); } /* add an across word to the grid */ void add_across_word (Puzzle *p) { print_puzzle (p); - if (p->grid_frozen) + if (p->grid_frozen == true) { printf (FROZEN_GRID); + char ch = getchar (); return; } - char word[MAX_PUZZLE_SIZE]; + char wd[MAX_PUZZLE_SIZE]; int row, col; printf (INPUT_WORD); - scanf ("%s", word); + fgets (wd, p->grid_size, stdin); + char *word = strtok (wd, "\n"); if (! is_valid_word (word)) { printf (INVALID_WORD); char ch = getchar (); - ch = getchar (); return; } printf (INPUT_ROW); - scanf ("%d", &row); + row = get_num (); printf (INPUT_COL); - scanf ("%d", &col); + col = get_num (); if (row >= p->grid_size || col >= p->grid_size) { printf (EXCEED_GRID_SIZE); char ch = getchar (); - ch = getchar (); return; } @@ -116,7 +138,6 @@ void add_across_word (Puzzle *p) { printf (WORD_TOO_LONG); char ch = getchar (); - ch = getchar (); return; } @@ -125,7 +146,6 @@ void add_across_word (Puzzle *p) print_puzzle (p); char ch = getchar (); - ch = getchar (); } void puzzle_editor_loop (Puzzle *p, const char *filename) @@ -133,28 +153,38 @@ void puzzle_editor_loop (Puzzle *p, const char *filename) bool loop = true; while (loop) { - print_menu (WHITE, RED, PUZZLE_MENU_TITLE, PUZZLE_EDIT_MENU, 8, 50); + print_menu (WHITE, RED, PUZZLE_MENU_TITLE, PUZZLE_EDIT_MENU, 9, 50); printf (INPUT_CHOICE); - char ch = getchar (); + int ch = get_num (); switch (ch) { - case '1': print_puzzle (p); - char ch = getchar (); - ch = getchar (); - break; - case '2': add_across_word (p); - break; - case '3': add_down_word (p); - break; - case '4': clear_cell (p); - break; - case '7': save_puzzle (p, filename); - printf ("%s\n",FILE_SAVED); - ch = getchar (); - ch = getchar (); - break; - case '8': loop = false; - break; + case 1: print_puzzle (p); + char ch = getchar (); + break; + case 2: add_across_word (p); + break; + case 3: add_down_word (p); + break; + case 4: clear_cell (p); + break; + case 5: freeze_puzzle (p); + print_puzzle (p); + ch = getchar (); + break; + case 6: unfreeze_puzzle (p); + print_puzzle (p); + ch = getchar (); + break; + case 7: set_clue_across_word (p); + print_puzzle (p); + ch = getchar (); + break; + case 8: save_puzzle (p, filename); + printf ("%s\n",FILE_SAVED); + ch = getchar (); + break; + case 9: loop = false; + break; } } } @@ -164,8 +194,9 @@ void open_puzzle () { Puzzle p; printf (INPUT_FILE); - char filename[256]; - scanf("%s", filename); + char fname[256]; + fgets(fname, 256, stdin); + char* filename = strtok (fname, "\n"); p = load_puzzle (filename); puzzle_editor_loop (&p, filename); } @@ -175,15 +206,16 @@ void new_puzzle () { Puzzle p; printf (INPUT_FILE); - char filename[256]; - scanf ("%s", filename); + char fname[256]; + fgets (fname, 256, stdin); + char* filename = strtok (fname, "\n"); printf (INPUT_GRID_SIZE); int size; - scanf ("%d", &size); + size = get_num (); if (size > MAX_PUZZLE_SIZE) { printf (EXCEED_MAX_GRID_SIZE); - char c = getchar (); c = getchar (); + char c = getchar (); } else { @@ -200,14 +232,14 @@ int main_loop () { print_menu (WHITE, BLUE, MAIN_MENU_TITLE, MAIN_MENU, 3, 50); printf (INPUT_CHOICE); - char ch = getchar (); + int ch = get_num (); switch (ch) { - case '1': new_puzzle (); - break; - case '2': open_puzzle (); - break; - case '3': exit (0); + case 1: new_puzzle (); + break; + case 2: open_puzzle (); + break; + case 3: exit (0); } } } diff --git a/wordblox.h b/wordblox.h index 50033bc..bde57c3 100644 --- a/wordblox.h +++ b/wordblox.h @@ -31,6 +31,14 @@ typedef struct { bool grid_frozen; } Puzzle; +int get_num () +{ + char s[5]; + fgets (s, 5, stdin); + int n = atoi (s); + return n; +} + /* Set the terminal colour */ void set_color (enum COLOR fg, enum COLOR bg) { printf ("\x1B[%d;%dm", fg+30, bg+40); @@ -41,6 +49,95 @@ void reset_color () { printf ("\x1B[0m"); } +/* check if previous row is blank or not */ +bool prev_row_blank (Puzzle *p, int r, int c) +{ + if (r == 0) return true; + if (p->chars[r-1][c] == ' ' || p->chars[r-1][c] == '#') return true; + return false; +} +/* check if next row is blank or not */ +bool next_row_blank (Puzzle *p, int r, int c) +{ + if (r == p->grid_size - 1) return true; + if (p->chars[r+1][c] == ' ' || p->chars[r+1][c] == '#') return true; + return false; +} +/* check if previous col is blank or not */ +bool prev_col_blank (Puzzle *p, int r, int c) +{ + if (c == 0) return true; + if (p->chars[r][c-1] == ' ' || p->chars[r][c-1] == '#') return true; + return false; +} +/* check if the next col is blank or not */ +bool next_col_blank (Puzzle *p, int r, int c) +{ + if (c == p->grid_size -1) return true; + if (p->chars[r][c+1] == ' ' || p->chars[r][c+1] == '#') return true; + return false; +} + +/* unfreeze the grid - mak editing possible to change words */ +void unfreeze_puzzle (Puzzle *p) +{ + for (int i = 0; i < p->grid_size; i ++) + { + for (int j = 0; j < p->grid_size; j ++) + { + if (p->chars[i][j] == '#') + p->chars[i][j] = ' '; + + p->start_across_word[i][j] = -1; + p->start_down_word[i][j] = -1; + } + } + p->grid_frozen = false; +} + +/* freeze the grid - make editing impossible because it finalizes the + across and down words in the grid */ +void freeze_puzzle (Puzzle *p) +{ + int word_num = 1; + bool across_word_start, down_word_start; + for (int i = 0; i < p->grid_size; i ++) + { + for (int j = 0; j < p->grid_size; j++) + { + across_word_start = false; + down_word_start = false; + /* if it is a blank cell - cover it with a block */ + if (p->chars[i][j] == ' ') + p->chars[i][j] = '#'; + /* it is not a blank cell - check all possibilities */ + else + { + bool prev_row = prev_row_blank (p, i, j); + bool next_row = next_row_blank (p, i, j); + bool prev_col = prev_col_blank (p, i, j); + bool next_col = next_col_blank (p, i, j); + if (prev_row && ! next_row) + down_word_start = true; + if (prev_col && ! next_col) + across_word_start = true; + } + + if (across_word_start == true) + p->start_across_word[i][j] = word_num; + else + p->start_across_word[i][j] = -1; + if (down_word_start == true) + p->start_down_word[i][j] = word_num; + else + p->start_down_word[i][j] = -1; + if (across_word_start == true || down_word_start == true) + word_num ++; + } + } + p->grid_frozen = true; +} + /* reset the entire grid */ void init_puzzle (Puzzle *p, int grid_size) { @@ -90,6 +187,7 @@ Puzzle load_puzzle (const char* file) { /* display the puzzle */ void print_puzzle (Puzzle *p) { + printf ("\n"); set_color (WHITE, CYAN); printf (" "); for (int i = 0; i < p->grid_size; i ++) @@ -108,10 +206,14 @@ void print_puzzle (Puzzle *p) } else { - if (p->start_across_word[i][j] != -1) + if (p->start_across_word[i][j] != -1 || + p->start_down_word[i][j] != -1) { set_color (BLUE, WHITE); - printf ("%2d", p->start_across_word[i][j]); + if (p->start_across_word[i][j] != -1) + printf ("%-2d", p->start_across_word[i][j]); + else + printf ("%-2d", p->start_down_word[i][j]); } else { @@ -126,6 +228,35 @@ void print_puzzle (Puzzle *p) } printf ("\n"); } + /* print the clues if set */ + if (p->grid_frozen == true) + { + printf ("ACROSS - CLUES\n"); + for (int i = 0; i < p->grid_size; i ++) + { + for (int j = 0; j < p->grid_size; j ++) + { + if (p->start_across_word[i][j] != -1) + { + printf ("%d - %s; ", p->start_across_word[i][j], + p->clue_across[i][j]); + } + } + } + printf ("\nDOWN - CLUES\n"); + for (int i = 0; i < p->grid_size; i ++) + { + for (int j = 0; j < p->grid_size; j ++) + { + if (p->start_down_word[i][j] != -1) + { + printf ("%d - %s; ", p->start_down_word[i][j], + p->clue_down[i][j]); + } + } + } + printf ("\n"); + } } /* function to check if a word is valid or not */ @@ -138,6 +269,23 @@ bool is_valid_word (const char *word) return true; } +/* function set a clue for an across word */ +bool set_across_clue (Puzzle *p, String clue, int index) +{ + for (int i = 0; i < p->grid_size; i ++) + { + for (int j = 0; j < p->grid_size; j ++) + { + if (p->start_across_word[i][j] == index) + { + strcpy (p->clue_across[i][j], clue); + return true; + } + } + } + return false; +} + /* function to print a menu */ void print_menu (enum COLOR fg, enum COLOR bg, const char* title, char **items, int num_items, int padding) -- 2.20.1