--- /dev/null
+#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
--- /dev/null
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include <stdbool.h>
+#include <string.h>
+#include <ctype.h>
+
+#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 ());
+}
--- /dev/null
+#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