From 3657c15588e4b2607d9225659f66158d92a85262 Mon Sep 17 00:00:00 2001 From: Harishankar Date: Wed, 29 Apr 2020 15:32:07 +0530 Subject: [PATCH] First commit First commit of the wordblox crossword puzzle maker --- constantstrings.h | 36 ++++++++ wordblox.c | 218 ++++++++++++++++++++++++++++++++++++++++++++++ wordblox.h | 176 +++++++++++++++++++++++++++++++++++++ 3 files changed, 430 insertions(+) create mode 100644 constantstrings.h create mode 100644 wordblox.c create mode 100644 wordblox.h diff --git a/constantstrings.h b/constantstrings.h new file mode 100644 index 0000000..4c1baa2 --- /dev/null +++ b/constantstrings.h @@ -0,0 +1,36 @@ +#ifndef __CONSTANTSTRINGS_H +#define __CONSTANTSTRINGS_H + +#define FROZEN_GRID "Grid is frozen. Unfreeze grid first!" +#define EXCEED_GRID_SIZE "Row/col exceeded grid size!" +#define INPUT_ROW "Enter the row: " +#define INPUT_COL "Enter the col: " +#define WORD_TOO_LONG "Word too long" +#define INPUT_WORD "Enter the word: " +#define INPUT_FILE "Enter the file name: " +#define PUZZLE_MENU_TITLE "Edit Puzzle" +#define MAIN_MENU_TITLE "Main Menu" +#define INPUT_GRID_SIZE "Number of rows/columns: " +#define INPUT_CHOICE "Your Choice: " +#define EXCEED_MAX_GRID_SIZE "Exceeds max puzzle size" +#define ERROR_WRITING_FILE "Error writing file" +#define ERROR_READING_FILE "Error reading file" +#define INVALID_WORD "Word contains illegal characters. Only alphabets allowed!" +#define FILE_SAVED "File saved successfully" + +char *MAIN_MENU[] = + {"1. New puzzle", + "2. Open existing puzzle", + "3. Exit"}; + +char *PUZZLE_EDIT_MENU[] = + { "1. Display grid", + "2. Add word across", + "3. Add word down", + "4. Clear Cell", + "5. Freeze grid", + "6. Unfreeze grid", + "7. Save puzzle", + "8. Return to main" }; + +#endif diff --git a/wordblox.c b/wordblox.c new file mode 100644 index 0000000..174346d --- /dev/null +++ b/wordblox.c @@ -0,0 +1,218 @@ +#include +#include +#include +#include +#include +#include + +#include "wordblox.h" +#include "constantstrings.h" + +/* clear a cell in the grid */ +void clear_cell (Puzzle *p) +{ + print_puzzle (p); + int row, col; + printf (INPUT_ROW); + scanf ("%d", &row); + printf (INPUT_COL); + scanf ("%d", &col); + 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) + { + printf (FROZEN_GRID); + char ch = getchar (); + ch = getchar (); + return; + } + char word[MAX_PUZZLE_SIZE]; + int row, col; + printf (INPUT_WORD); + scanf ("%s", word); + if (! is_valid_word (word)) + { + printf (INVALID_WORD); + char ch = getchar (); + ch = getchar (); + return; + } + printf (INPUT_ROW); + scanf ("%d", &row); + printf (INPUT_COL); + scanf ("%d", &col); + 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; + } + + for (int i = row; i < row + strlen(word); i ++) + p->chars[i][col] = toupper(word[i - row]); + + 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) + { + printf (FROZEN_GRID); + return; + } + char word[MAX_PUZZLE_SIZE]; + int row, col; + printf (INPUT_WORD); + scanf ("%s", word); + if (! is_valid_word (word)) + { + printf (INVALID_WORD); + char ch = getchar (); + ch = getchar (); + return; + } + printf (INPUT_ROW); + scanf ("%d", &row); + printf (INPUT_COL); + scanf ("%d", &col); + 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 - col)) + { + printf (WORD_TOO_LONG); + char ch = getchar (); + ch = getchar (); + return; + } + + for (int i = col; i < col+strlen (word); i ++) + p->chars[row][i] = toupper(word[i - col]); + + print_puzzle (p); + char ch = getchar (); + ch = getchar (); +} + +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); + printf (INPUT_CHOICE); + char ch = getchar (); + 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; + } + } +} + +/* open an existing puzzle */ +void open_puzzle () +{ + Puzzle p; + printf (INPUT_FILE); + char filename[256]; + scanf("%s", filename); + p = load_puzzle (filename); + puzzle_editor_loop (&p, filename); +} + +/* create a new blank puzzle */ +void new_puzzle () +{ + Puzzle p; + printf (INPUT_FILE); + char filename[256]; + scanf ("%s", filename); + printf (INPUT_GRID_SIZE); + int size; + scanf ("%d", &size); + if (size > MAX_PUZZLE_SIZE) + { + printf (EXCEED_MAX_GRID_SIZE); + char c = getchar (); c = getchar (); + } + else + { + init_puzzle (&p, size); + puzzle_editor_loop (&p, filename); + } +} + +/* The main loop of the program */ +int main_loop () +{ + /* Print the main menu */ + while (1) + { + print_menu (WHITE, BLUE, MAIN_MENU_TITLE, MAIN_MENU, 3, 50); + printf (INPUT_CHOICE); + char ch = getchar (); + switch (ch) + { + case '1': new_puzzle (); + break; + case '2': open_puzzle (); + break; + case '3': exit (0); + } + } +} + +int main (int argc, char* argv[]) +{ + return (main_loop ()); +} diff --git a/wordblox.h b/wordblox.h new file mode 100644 index 0000000..50033bc --- /dev/null +++ b/wordblox.h @@ -0,0 +1,176 @@ +#ifndef __WORDBLOX_H +#define __WORDBLOX_H + +#include "constantstrings.h" + +#define MAX_PUZZLE_SIZE 20 +#define MAX_CLUE_LENGTH 150 + +/* Enum to define terminal colours */ +enum COLOR { + BLACK = 0, + RED= 1, + GREEN=2, + YELLOW=3, + BLUE=4, + MAGENTA=5, + CYAN=6, + WHITE=7 +}; + +typedef char String[MAX_CLUE_LENGTH]; + +/* The main puzzle struct type */ +typedef struct { + char chars[MAX_PUZZLE_SIZE][MAX_PUZZLE_SIZE]; + int start_across_word[MAX_PUZZLE_SIZE][MAX_PUZZLE_SIZE]; + int start_down_word[MAX_PUZZLE_SIZE][MAX_PUZZLE_SIZE]; + String clue_across[MAX_PUZZLE_SIZE][MAX_PUZZLE_SIZE]; + String clue_down[MAX_PUZZLE_SIZE][MAX_PUZZLE_SIZE]; + int grid_size; + bool grid_frozen; +} Puzzle; + +/* Set the terminal colour */ +void set_color (enum COLOR fg, enum COLOR bg) { + printf ("\x1B[%d;%dm", fg+30, bg+40); +} + +/* Reset the terminal colour */ +void reset_color () { + printf ("\x1B[0m"); +} + +/* reset the entire grid */ +void init_puzzle (Puzzle *p, int grid_size) +{ + p->grid_size = grid_size; + p->grid_frozen = false; + for (int i = 0; i < p->grid_size; i ++) + { + for (int j = 0; j < p->grid_size; j ++) + { + p->chars[i][j] = ' '; + p->start_across_word[i][j] = -1; + p->start_down_word[i][j] = -1; + strcpy (p->clue_across[i][j], ""); + strcpy (p->clue_down[i][j], ""); + } + } +} + +/* save the puzzle */ +void save_puzzle (Puzzle *puzzle, const char* file) { + FILE *outfile; + outfile = fopen (file, "wb"); + if (outfile == NULL) + { + fprintf (stderr, "%s\n", ERROR_WRITING_FILE); + exit (1); + } + fwrite (puzzle, sizeof (*puzzle), 1, outfile); + fclose (outfile); +} + +/* read the puzzle */ +Puzzle load_puzzle (const char* file) { + FILE *infile; + Puzzle p; + infile = fopen (file, "rb"); + if (infile == NULL) + { + fprintf (stderr, "%s\n", ERROR_READING_FILE); + exit (1); + } + fread (&p, sizeof(p), 1, infile); + fclose (infile); + return p; +} + +/* display the puzzle */ +void print_puzzle (Puzzle *p) +{ + set_color (WHITE, CYAN); + printf (" "); + for (int i = 0; i < p->grid_size; i ++) + printf ("%3d", i); + reset_color (); + printf("\n"); + for (int i = 0; i < p->grid_size; i ++) + { + set_color (WHITE, CYAN); + printf ("%3d ", i); + for (int j = 0; j < p->grid_size; j ++) + { + if (p->chars[i][j] == '#') { + set_color (WHITE, BLACK); + printf (" "); + } + else + { + if (p->start_across_word[i][j] != -1) + { + set_color (BLUE, WHITE); + printf ("%2d", p->start_across_word[i][j]); + } + else + { + set_color (BLACK, WHITE); + printf (" "); + } + + set_color (BLACK, WHITE); + printf ("%c", p->chars[i][j]); + } + reset_color (); + } + printf ("\n"); + } +} + +/* function to check if a word is valid or not */ +bool is_valid_word (const char *word) +{ + for (int i = 0; i < strlen (word); i ++) + if (! isalpha (word[i])) + return false; + + return true; +} + +/* function to print a menu */ +void print_menu (enum COLOR fg, enum COLOR bg, const char* title, + char **items, int num_items, int padding) +{ + /* clear screen */ + printf ("\e[1;1H\e[2J"); + set_color (fg, bg); + printf ("\u2554"); + for (int i = 0; i < padding; i ++) + printf ("\u2550"); + printf ("\u2557"); + reset_color (); printf ("\n"); + set_color (fg, bg); + printf ("\u2551%-*s\u2551", padding, title); + reset_color (); printf ("\n"); + set_color (fg, bg); + printf ("\u2560"); + for (int i = 0; i < padding; i ++) + printf ("\u2550"); + printf ("\u2563"); + reset_color (); printf ("\n"); + for (int i = 0; i < num_items; i ++) + { + set_color (fg, bg); + printf ("\u2551%-*s\u2551", padding, items[i]); + reset_color (); printf ("\n"); + } + set_color (fg, bg); + printf ("\u255A"); + for (int i = 0; i < padding; i ++) + printf ("\u2550"); + printf ("\u255D"); + reset_color (); printf ("\n"); +} + +#endif -- 2.20.1