4 #include "constantstrings.h"
6 #define MAX_PUZZLE_SIZE 20
7 #define MAX_CLUE_LENGTH 150
9 /* Enum to define terminal colours */
31 typedef char String
[MAX_CLUE_LENGTH
];
33 /* The main puzzle struct type */
35 char chars
[MAX_PUZZLE_SIZE
][MAX_PUZZLE_SIZE
];
36 int start_across_word
[MAX_PUZZLE_SIZE
][MAX_PUZZLE_SIZE
];
37 int start_down_word
[MAX_PUZZLE_SIZE
][MAX_PUZZLE_SIZE
];
38 String clue_across
[MAX_PUZZLE_SIZE
][MAX_PUZZLE_SIZE
];
39 String clue_down
[MAX_PUZZLE_SIZE
][MAX_PUZZLE_SIZE
];
52 /* Set the terminal colour */
53 void set_color (enum COLOR fg
, enum COLOR bg
, enum ATTR at
) {
54 printf ("\x1B[%d;%d;%dm", fg
+30, bg
+40, at
);
57 /* Reset the terminal colour */
62 /* check if previous row is blank or not */
63 bool prev_row_blank (Puzzle
*p
, int r
, int c
)
65 if (r
== 0) return true;
66 if (p
->chars
[r
-1][c
] == ' ' || p
->chars
[r
-1][c
] == '#') return true;
69 /* check if next row is blank or not */
70 bool next_row_blank (Puzzle
*p
, int r
, int c
)
72 if (r
== p
->grid_size
- 1) return true;
73 if (p
->chars
[r
+1][c
] == ' ' || p
->chars
[r
+1][c
] == '#') return true;
76 /* check if previous col is blank or not */
77 bool prev_col_blank (Puzzle
*p
, int r
, int c
)
79 if (c
== 0) return true;
80 if (p
->chars
[r
][c
-1] == ' ' || p
->chars
[r
][c
-1] == '#') return true;
83 /* check if the next col is blank or not */
84 bool next_col_blank (Puzzle
*p
, int r
, int c
)
86 if (c
== p
->grid_size
-1) return true;
87 if (p
->chars
[r
][c
+1] == ' ' || p
->chars
[r
][c
+1] == '#') return true;
91 /* unfreeze the grid - mak editing possible to change words */
92 void unfreeze_puzzle (Puzzle
*p
)
94 for (int i
= 0; i
< p
->grid_size
; i
++)
96 for (int j
= 0; j
< p
->grid_size
; j
++)
98 if (p
->chars
[i
][j
] == '#')
101 p
->start_across_word
[i
][j
] = -1;
102 p
->start_down_word
[i
][j
] = -1;
105 p
->grid_frozen
= false;
108 /* freeze the grid - make editing impossible because it finalizes the
109 across and down words in the grid */
110 void freeze_puzzle (Puzzle
*p
)
113 bool across_word_start
, down_word_start
;
114 for (int i
= 0; i
< p
->grid_size
; i
++)
116 for (int j
= 0; j
< p
->grid_size
; j
++)
118 across_word_start
= false;
119 down_word_start
= false;
120 /* if it is a blank cell - cover it with a block */
121 if (p
->chars
[i
][j
] == ' ')
122 p
->chars
[i
][j
] = '#';
123 /* it is not a blank cell - check all possibilities */
126 bool prev_row
= prev_row_blank (p
, i
, j
);
127 bool next_row
= next_row_blank (p
, i
, j
);
128 bool prev_col
= prev_col_blank (p
, i
, j
);
129 bool next_col
= next_col_blank (p
, i
, j
);
130 if (prev_row
&& ! next_row
)
131 down_word_start
= true;
132 if (prev_col
&& ! next_col
)
133 across_word_start
= true;
136 if (across_word_start
== true)
137 p
->start_across_word
[i
][j
] = word_num
;
139 p
->start_across_word
[i
][j
] = -1;
140 if (down_word_start
== true)
141 p
->start_down_word
[i
][j
] = word_num
;
143 p
->start_down_word
[i
][j
] = -1;
144 if (across_word_start
== true || down_word_start
== true)
148 p
->grid_frozen
= true;
151 /* reset the entire grid */
152 void init_puzzle (Puzzle
*p
, int grid_size
)
154 p
->grid_size
= grid_size
;
155 p
->grid_frozen
= false;
156 for (int i
= 0; i
< p
->grid_size
; i
++)
158 for (int j
= 0; j
< p
->grid_size
; j
++)
160 p
->chars
[i
][j
] = ' ';
161 p
->start_across_word
[i
][j
] = -1;
162 p
->start_down_word
[i
][j
] = -1;
163 strcpy (p
->clue_across
[i
][j
], "");
164 strcpy (p
->clue_down
[i
][j
], "");
169 /* save the puzzle */
170 void save_puzzle (Puzzle
*puzzle
, const char* file
) {
172 outfile
= fopen (file
, "wb");
175 fprintf (stderr
, "%s\n", ERROR_WRITING_FILE
);
178 fwrite (puzzle
, sizeof (*puzzle
), 1, outfile
);
182 /* read the puzzle */
183 Puzzle
load_puzzle (const char* file
) {
186 infile
= fopen (file
, "rb");
189 fprintf (stderr
, "%s\n", ERROR_READING_FILE
);
192 fread (&p
, sizeof(p
), 1, infile
);
197 /* display the puzzle */
198 void print_puzzle (Puzzle
*p
)
201 set_color (WHITE
, CYAN
, NORMAL
);
203 for (int i
= 0; i
< p
->grid_size
; i
++)
207 for (int i
= 0; i
< p
->grid_size
; i
++)
209 set_color (WHITE
, CYAN
, NORMAL
);
211 for (int j
= 0; j
< p
->grid_size
; j
++)
213 if (p
->chars
[i
][j
] == '#') {
214 set_color (WHITE
, BLACK
, NORMAL
);
219 if (p
->start_across_word
[i
][j
] != -1 ||
220 p
->start_down_word
[i
][j
] != -1)
222 set_color (BLUE
, WHITE
, NORMAL
);
223 if (p
->start_across_word
[i
][j
] != -1)
224 printf ("%-2d", p
->start_across_word
[i
][j
]);
226 printf ("%-2d", p
->start_down_word
[i
][j
]);
230 set_color (BLACK
, WHITE
,NORMAL
);
234 set_color (BLACK
, WHITE
, BOLD
);
235 printf ("%c", p
->chars
[i
][j
]);
241 /* print the clues if set */
242 if (p
->grid_frozen
== true)
244 printf ("\x1B[1mACROSS - CLUES\x1B[0m\n");
245 for (int i
= 0; i
< p
->grid_size
; i
++)
247 for (int j
= 0; j
< p
->grid_size
; j
++)
249 if (p
->start_across_word
[i
][j
] != -1)
251 printf ("%d - %s; ", p
->start_across_word
[i
][j
],
252 p
->clue_across
[i
][j
]);
256 printf ("\n\x1B[1mDOWN - CLUES\x1B[0m\n");
257 for (int i
= 0; i
< p
->grid_size
; i
++)
259 for (int j
= 0; j
< p
->grid_size
; j
++)
261 if (p
->start_down_word
[i
][j
] != -1)
263 printf ("%d - %s; ", p
->start_down_word
[i
][j
],
272 /* function to check if a word is valid or not */
273 bool is_valid_word (const char *word
)
275 for (int i
= 0; i
< strlen (word
); i
++)
276 if (! isalpha (word
[i
]))
283 /* function to set a clue for an across word */
284 bool set_clue (Puzzle
*p
, String clue
, int index
, enum ORIENTATION order
)
286 for (int i
= 0; i
< p
->grid_size
; i
++)
288 for (int j
= 0; j
< p
->grid_size
; j
++)
292 if (p
->start_across_word
[i
][j
] == index
)
294 strcpy (p
->clue_across
[i
][j
], clue
);
298 else if (order
== DOWN
)
300 if (p
->start_down_word
[i
][j
] == index
)
302 strcpy (p
->clue_down
[i
][j
], clue
);
311 /* function to print a menu */
312 void print_menu (enum COLOR fg
, enum COLOR bg
, const char* title
,
313 char **items
, int num_items
, int padding
)
316 printf ("\e[1;1H\e[2J");
317 set_color (fg
, bg
, NORMAL
);
319 for (int i
= 0; i
< padding
; i
++)
322 reset_color (); printf ("\n");
323 set_color (fg
, bg
, BOLD
);
324 printf ("\u2551%-*s\u2551", padding
, title
);
325 reset_color (); printf ("\n");
326 set_color (fg
, bg
, NORMAL
);
328 for (int i
= 0; i
< padding
; i
++)
331 reset_color (); printf ("\n");
332 for (int i
= 0; i
< num_items
; i
++)
334 set_color (fg
, bg
, NORMAL
);
335 printf ("\u2551%-*s\u2551", padding
, items
[i
]);
336 reset_color (); printf ("\n");
338 set_color (fg
, bg
, NORMAL
);
340 for (int i
= 0; i
< padding
; i
++)
343 reset_color (); printf ("\n");