First commit
authorHarishankar <v.harishankar@gmail.com>
Wed, 29 Apr 2020 10:02:07 +0000 (15:32 +0530)
committerHarishankar <v.harishankar@gmail.com>
Wed, 29 Apr 2020 10:02:07 +0000 (15:32 +0530)
First commit of the wordblox crossword puzzle maker

constantstrings.h [new file with mode: 0644]
wordblox.c [new file with mode: 0644]
wordblox.h [new file with mode: 0644]

diff --git a/constantstrings.h b/constantstrings.h
new file mode 100644 (file)
index 0000000..4c1baa2
--- /dev/null
@@ -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 (file)
index 0000000..174346d
--- /dev/null
@@ -0,0 +1,218 @@
+#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 ());
+}
diff --git a/wordblox.h b/wordblox.h
new file mode 100644 (file)
index 0000000..50033bc
--- /dev/null
@@ -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