bde57c364d95e88728e9b74ded17db4ae047a87a
4 #include "constantstrings.h"
6 #define MAX_PUZZLE_SIZE 20
7 #define MAX_CLUE_LENGTH 150
9 /* Enum to define terminal colours */
21 typedef char String
[MAX_CLUE_LENGTH
];
23 /* The main puzzle struct type */
25 char chars
[MAX_PUZZLE_SIZE
][MAX_PUZZLE_SIZE
];
26 int start_across_word
[MAX_PUZZLE_SIZE
][MAX_PUZZLE_SIZE
];
27 int start_down_word
[MAX_PUZZLE_SIZE
][MAX_PUZZLE_SIZE
];
28 String clue_across
[MAX_PUZZLE_SIZE
][MAX_PUZZLE_SIZE
];
29 String clue_down
[MAX_PUZZLE_SIZE
][MAX_PUZZLE_SIZE
];
42 /* Set the terminal colour */
43 void set_color (enum COLOR fg
, enum COLOR bg
) {
44 printf ("\x1B[%d;%dm", fg
+30, bg
+40);
47 /* Reset the terminal colour */
52 /* check if previous row is blank or not */
53 bool prev_row_blank (Puzzle
*p
, int r
, int c
)
55 if (r
== 0) return true;
56 if (p
->chars
[r
-1][c
] == ' ' || p
->chars
[r
-1][c
] == '#') return true;
59 /* check if next row is blank or not */
60 bool next_row_blank (Puzzle
*p
, int r
, int c
)
62 if (r
== p
->grid_size
- 1) return true;
63 if (p
->chars
[r
+1][c
] == ' ' || p
->chars
[r
+1][c
] == '#') return true;
66 /* check if previous col is blank or not */
67 bool prev_col_blank (Puzzle
*p
, int r
, int c
)
69 if (c
== 0) return true;
70 if (p
->chars
[r
][c
-1] == ' ' || p
->chars
[r
][c
-1] == '#') return true;
73 /* check if the next col is blank or not */
74 bool next_col_blank (Puzzle
*p
, int r
, int c
)
76 if (c
== p
->grid_size
-1) return true;
77 if (p
->chars
[r
][c
+1] == ' ' || p
->chars
[r
][c
+1] == '#') return true;
81 /* unfreeze the grid - mak editing possible to change words */
82 void unfreeze_puzzle (Puzzle
*p
)
84 for (int i
= 0; i
< p
->grid_size
; i
++)
86 for (int j
= 0; j
< p
->grid_size
; j
++)
88 if (p
->chars
[i
][j
] == '#')
91 p
->start_across_word
[i
][j
] = -1;
92 p
->start_down_word
[i
][j
] = -1;
95 p
->grid_frozen
= false;
98 /* freeze the grid - make editing impossible because it finalizes the
99 across and down words in the grid */
100 void freeze_puzzle (Puzzle
*p
)
103 bool across_word_start
, down_word_start
;
104 for (int i
= 0; i
< p
->grid_size
; i
++)
106 for (int j
= 0; j
< p
->grid_size
; j
++)
108 across_word_start
= false;
109 down_word_start
= false;
110 /* if it is a blank cell - cover it with a block */
111 if (p
->chars
[i
][j
] == ' ')
112 p
->chars
[i
][j
] = '#';
113 /* it is not a blank cell - check all possibilities */
116 bool prev_row
= prev_row_blank (p
, i
, j
);
117 bool next_row
= next_row_blank (p
, i
, j
);
118 bool prev_col
= prev_col_blank (p
, i
, j
);
119 bool next_col
= next_col_blank (p
, i
, j
);
120 if (prev_row
&& ! next_row
)
121 down_word_start
= true;
122 if (prev_col
&& ! next_col
)
123 across_word_start
= true;
126 if (across_word_start
== true)
127 p
->start_across_word
[i
][j
] = word_num
;
129 p
->start_across_word
[i
][j
] = -1;
130 if (down_word_start
== true)
131 p
->start_down_word
[i
][j
] = word_num
;
133 p
->start_down_word
[i
][j
] = -1;
134 if (across_word_start
== true || down_word_start
== true)
138 p
->grid_frozen
= true;
141 /* reset the entire grid */
142 void init_puzzle (Puzzle
*p
, int grid_size
)
144 p
->grid_size
= grid_size
;
145 p
->grid_frozen
= false;
146 for (int i
= 0; i
< p
->grid_size
; i
++)
148 for (int j
= 0; j
< p
->grid_size
; j
++)
150 p
->chars
[i
][j
] = ' ';
151 p
->start_across_word
[i
][j
] = -1;
152 p
->start_down_word
[i
][j
] = -1;
153 strcpy (p
->clue_across
[i
][j
], "");
154 strcpy (p
->clue_down
[i
][j
], "");
159 /* save the puzzle */
160 void save_puzzle (Puzzle
*puzzle
, const char* file
) {
162 outfile
= fopen (file
, "wb");
165 fprintf (stderr
, "%s\n", ERROR_WRITING_FILE
);
168 fwrite (puzzle
, sizeof (*puzzle
), 1, outfile
);
172 /* read the puzzle */
173 Puzzle
load_puzzle (const char* file
) {
176 infile
= fopen (file
, "rb");
179 fprintf (stderr
, "%s\n", ERROR_READING_FILE
);
182 fread (&p
, sizeof(p
), 1, infile
);
187 /* display the puzzle */
188 void print_puzzle (Puzzle
*p
)
191 set_color (WHITE
, CYAN
);
193 for (int i
= 0; i
< p
->grid_size
; i
++)
197 for (int i
= 0; i
< p
->grid_size
; i
++)
199 set_color (WHITE
, CYAN
);
201 for (int j
= 0; j
< p
->grid_size
; j
++)
203 if (p
->chars
[i
][j
] == '#') {
204 set_color (WHITE
, BLACK
);
209 if (p
->start_across_word
[i
][j
] != -1 ||
210 p
->start_down_word
[i
][j
] != -1)
212 set_color (BLUE
, WHITE
);
213 if (p
->start_across_word
[i
][j
] != -1)
214 printf ("%-2d", p
->start_across_word
[i
][j
]);
216 printf ("%-2d", p
->start_down_word
[i
][j
]);
220 set_color (BLACK
, WHITE
);
224 set_color (BLACK
, WHITE
);
225 printf ("%c", p
->chars
[i
][j
]);
231 /* print the clues if set */
232 if (p
->grid_frozen
== true)
234 printf ("ACROSS - CLUES\n");
235 for (int i
= 0; i
< p
->grid_size
; i
++)
237 for (int j
= 0; j
< p
->grid_size
; j
++)
239 if (p
->start_across_word
[i
][j
] != -1)
241 printf ("%d - %s; ", p
->start_across_word
[i
][j
],
242 p
->clue_across
[i
][j
]);
246 printf ("\nDOWN - CLUES\n");
247 for (int i
= 0; i
< p
->grid_size
; i
++)
249 for (int j
= 0; j
< p
->grid_size
; j
++)
251 if (p
->start_down_word
[i
][j
] != -1)
253 printf ("%d - %s; ", p
->start_down_word
[i
][j
],
262 /* function to check if a word is valid or not */
263 bool is_valid_word (const char *word
)
265 for (int i
= 0; i
< strlen (word
); i
++)
266 if (! isalpha (word
[i
]))
272 /* function set a clue for an across word */
273 bool set_across_clue (Puzzle
*p
, String clue
, int index
)
275 for (int i
= 0; i
< p
->grid_size
; i
++)
277 for (int j
= 0; j
< p
->grid_size
; j
++)
279 if (p
->start_across_word
[i
][j
] == index
)
281 strcpy (p
->clue_across
[i
][j
], clue
);
289 /* function to print a menu */
290 void print_menu (enum COLOR fg
, enum COLOR bg
, const char* title
,
291 char **items
, int num_items
, int padding
)
294 printf ("\e[1;1H\e[2J");
297 for (int i
= 0; i
< padding
; i
++)
300 reset_color (); printf ("\n");
302 printf ("\u2551%-*s\u2551", padding
, title
);
303 reset_color (); printf ("\n");
306 for (int i
= 0; i
< padding
; i
++)
309 reset_color (); printf ("\n");
310 for (int i
= 0; i
< num_items
; i
++)
313 printf ("\u2551%-*s\u2551", padding
, items
[i
]);
314 reset_color (); printf ("\n");
318 for (int i
= 0; i
< padding
; i
++)
321 reset_color (); printf ("\n");