From 0dd9b1cd908b90236fba38ef4d7402c8fbcbb99b Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Mon, 18 Dec 2006 23:41:26 -0800 Subject: [PATCH] Fix to not give hints by putting answers found so far in their alphabetical position. Instead all found answers now appear alphabetically before the blanks corresponding to all unfound answers. Part of implementing this was adding new of_length interfaces to dict in place (or in addition) to the previous by_length interfaces. The new interfaces are much more useful, (allowing length-limited queries without any implicit looping). --- dict.c | 187 ++++++++++++++++++++++++++++----------------------- dict.h | 27 ++++++-- rack-fancy.c | 67 ++++++++++++++---- 3 files changed, 176 insertions(+), 105 deletions(-) diff --git a/dict.c b/dict.c index a842fa9..b23da18 100644 --- a/dict.c +++ b/dict.c @@ -189,34 +189,35 @@ trie_find (trie_t *trie, } static int -trie_count (trie_t *trie, - trie_predicate_t predicate) +trie_count_if (trie_t *trie, + trie_predicate_t predicate) { int i; int count = 0; - if ((predicate) (trie)) + if (predicate == NULL || (predicate) (trie)) count = 1; for (i = 0; i < 26; i++) { if (trie->next[i] == NULL) continue; - count += trie_count (trie->next[i], predicate); + count += trie_count_if (trie->next[i], predicate); } return count; } static int -trie_for_each (trie_t *trie, - string_t *string, - trie_predicate_t predicate, - int length, - int min_length, - int max_length, - dict_action_t action, - void *closure) +trie_for_each_of_length_if (trie_t *trie, + dict_action_t action, + void *closure, + int min_length, + int max_length, + trie_predicate_t predicate, + string_t *string, + int length) + { char c; int i; @@ -240,9 +241,11 @@ trie_for_each (trie_t *trie, c = TRIE_INDEX_TO_CHAR (i); string_append_char (string, c); - count += trie_for_each (trie->next[i], string, predicate, - length + 1, min_length, max_length, - action, closure); + count += trie_for_each_of_length_if (trie->next[i], + action, closure, + min_length, max_length, + predicate, + string, length + 1); string_chop (string); } @@ -367,66 +370,39 @@ dict_predicate (trie_t *trie) } int -dict_count (dict_t *dict, - dict_entry_predicate_t predicate) -{ - dict_entry_predicate = predicate; - return trie_count (dict, dict_predicate); -} - -int -dict_for_each_if (dict_t *dict, - dict_action_t action, - void *closure, - dict_entry_predicate_t predicate) - +dict_count_if (dict_t *dict, + dict_entry_predicate_t predicate) { - int count; - string_t string; - - string_init (&string); - dict_entry_predicate = predicate; - count = trie_for_each (dict, &string, dict_predicate, - 0, 0, -1, action, closure); - - string_fini (&string); - - return count; + return trie_count_if (dict, dict_predicate); } int -dict_for_each (dict_t *dict, - dict_action_t action, - void *closure) +dict_count (dict_t *dict) { - return dict_for_each_if (dict, action, closure, NULL); + return dict_count_if (dict, NULL); } int -dict_for_each_by_length_if (dict_t *dict, +dict_for_each_of_length_if (dict_t *dict, dict_action_t action, void *closure, + int min_length, + int max_length, dict_entry_predicate_t predicate) { - int length, total, words, count = 0; + int count; string_t string; string_init (&string); dict_entry_predicate = predicate; - total = trie_count (dict, dict_predicate); - - length = 1; - do { - words = trie_for_each (dict, &string, dict_predicate, - 0, length, length, - action, closure); - if (words) - count += words; - length++; - } while (count < total); + count = trie_for_each_of_length_if (dict, + action, closure, + min_length, max_length, + dict_predicate, + &string, 0); string_fini (&string); @@ -434,65 +410,104 @@ dict_for_each_by_length_if (dict_t *dict, } int -dict_for_each_by_length (dict_t *dict, +dict_for_each_of_length (dict_t *dict, dict_action_t action, - void *closure) + void *closure, + int min_length, + int max_length) { - return dict_for_each_by_length_if (dict, action, closure, NULL); + return dict_for_each_of_length_if (dict, + action, closure, + min_length, max_length, + NULL); +} + +int +dict_for_each_if (dict_t *dict, + dict_action_t action, + void *closure, + dict_entry_predicate_t predicate) + +{ + return dict_for_each_of_length_if (dict, + action, closure, + 0, 0, + predicate); +} + +int +dict_for_each (dict_t *dict, + dict_action_t action, + void *closure) +{ + return dict_for_each_if (dict, action, closure, NULL); } static void dict_action_print (void *closure, char *word, dict_entry_t *entry) { - int *length_of_last = closure; - int length = strlen (word); + int *first = closure; - if (length == *length_of_last) + if (*first) + *first = 0; + else printf(" "); - else if (*length_of_last) - printf("\n"); printf ("%s", word); - - *length_of_last = length; } int -dict_print (dict_t *dict) +dict_print_of_length_if (dict_t *dict, + int min_length, + int max_length, + dict_entry_predicate_t predicate) { - int length_of_last = 0; + int first = TRUE; - return dict_for_each (dict, - dict_action_print, &length_of_last); + return dict_for_each_of_length_if (dict, + dict_action_print, &first, + min_length, max_length, + predicate); } int -dict_print_by_length (dict_t *dict) +dict_print_by_length_if (dict_t *dict, + dict_entry_predicate_t predicate) { - int length_of_last = 0; + int length, total, words, count = 0; + + total = dict_count_if (dict, predicate); + + length = 1; + do { + words = dict_print_of_length_if (dict, length, length, predicate); + if (words) { + count += words; + printf ("\n"); + } + length++; + } while (count < total); - return dict_for_each_by_length (dict, - dict_action_print, &length_of_last); + return count; +} + +int +dict_print_of_length (dict_t *dict, + int min_length, + int max_length) +{ + return dict_print_of_length_if (dict, min_length, max_length, NULL); } int dict_print_if (dict_t *dict, dict_entry_predicate_t predicate) { - int length_of_last = 0; - - return dict_for_each_if (dict, - dict_action_print, &length_of_last, - predicate); + return dict_print_of_length_if (dict, 0, 0, predicate); } int -dict_print_by_length_if (dict_t *dict, - dict_entry_predicate_t predicate) +dict_print (dict_t *dict) { - int length_of_last = 0; - - return dict_for_each_by_length_if (dict, - dict_action_print, &length_of_last, - predicate); + return dict_print_if (dict, NULL); } diff --git a/dict.h b/dict.h index ab962c2..6221651 100644 --- a/dict.h +++ b/dict.h @@ -68,8 +68,11 @@ typedef bool_t (*dict_entry_predicate_t) (dict_entry_t entry); int -dict_count (dict_t *dict, - dict_entry_predicate_t predicate); +dict_count_if (dict_t *dict, + dict_entry_predicate_t predicate); + +int +dict_count (dict_t *dict); /* Querying a dictionary entry. The dict interface uses 1 bit. * All of the remaining bits are available for application use. @@ -83,12 +86,20 @@ int dict_print (dict_t *dict); int -dict_print_by_length (dict_t *dict); +dict_print_of_length (dict_t *dict, + int min_length, + int max_length); int dict_print_if (dict_t *dict, dict_entry_predicate_t predicate); +int +dict_print_of_length_if (dict_t *dict, + int min_length, + int max_length, + dict_entry_predicate_t predicate); + int dict_print_by_length_if (dict_t *dict, dict_entry_predicate_t predicate); @@ -102,9 +113,11 @@ dict_for_each (dict_t *dict, void *closure); int -dict_for_each_by_length (dict_t *dict, +dict_for_each_of_length (dict_t *dict, dict_action_t action, - void *closure); + void *closure, + int min_length, + int max_length); int dict_for_each_if (dict_t *dict, @@ -113,9 +126,11 @@ dict_for_each_if (dict_t *dict, dict_entry_predicate_t predicate); int -dict_for_each_by_length_if (dict_t *dict, +dict_for_each_of_length_if (dict_t *dict, dict_action_t action, void *closure, + int min_length, + int max_length, dict_entry_predicate_t predicate); /* Character-by-character perusal of the dictionary */ diff --git a/rack-fancy.c b/rack-fancy.c index 8027963..834492a 100644 --- a/rack-fancy.c +++ b/rack-fancy.c @@ -48,6 +48,7 @@ typedef struct _rack bag_t bag; dict_t dict; dict_t solution; + int solution_total; GooCanvasItem *solution_item; gboolean done; } rack_t; @@ -69,6 +70,13 @@ rack_tile_position (int i, int *x, int *y) *y += (LETTER_SIZE + LETTER_PAD); } +typedef enum dict_paint_cursor_show +{ + DICT_PAINT_CURSOR_SHOW_FOUND, + DICT_PAINT_CURSOR_SHOW_UNFOUND_BLANKS, + DICT_PAINT_CURSOR_SHOW_ALL +} dict_paint_cursor_show_t; + typedef struct _dict_paint_cursor { cairo_t *cr; @@ -77,7 +85,7 @@ typedef struct _dict_paint_cursor int y; int max_column_width; int max_y; - gboolean show_all; + dict_paint_cursor_show_t show; } dict_paint_cursor_t; static void @@ -86,21 +94,38 @@ dict_paint_action (void *closure, char *word, dict_entry_t *entry) dict_paint_cursor_t *cursor = closure; cairo_t *cr = cursor->cr; double new_x, new_y; + int found, show_blanks = FALSE; if (strlen (word) < 3) return; - cairo_move_to (cr, cursor->x, cursor->y); - if (*entry & RACK_DICT_ENTRY_FOUND || cursor->show_all) { - if (*entry & RACK_DICT_ENTRY_FOUND) - cairo_set_source_rgb (cr, 0, 0, 0); /* black */ - else + found = *entry & RACK_DICT_ENTRY_FOUND; + + cairo_set_source_rgb (cr, 0, 0, 0); /* black */ + + switch (cursor->show) { + case DICT_PAINT_CURSOR_SHOW_FOUND: + if (! found) + return; + break; + case DICT_PAINT_CURSOR_SHOW_UNFOUND_BLANKS: + if (found) + return; + show_blanks = TRUE; + break; + case DICT_PAINT_CURSOR_SHOW_ALL: + if (! found) cairo_set_source_rgb (cr, 1, 0, 0); /* red */ - cairo_show_text (cr, word); - } else { + break; + } + + cairo_move_to (cr, cursor->x, cursor->y); + if (show_blanks) { int i, length = strlen (word); for (i = 0; i < length; i++) cairo_show_text (cr, "_"); + } else { + cairo_show_text (cr, word); } cairo_get_current_point (cr, &new_x, &new_y); if (new_x > cursor->max_column_width) @@ -120,6 +145,7 @@ dict_paint (cairo_t *cr, void *closure, double width, double height) { rack_t *rack = closure; dict_paint_cursor_t cursor; + int length, count; cairo_save (cr); cairo_set_source_rgb (cr, 0.0, 0.0, 0.0); /* black */ @@ -136,11 +162,24 @@ dict_paint (cairo_t *cr, void *closure, double width, double height) cursor.max_column_width = 0; cursor.max_y = height; - cursor.show_all = rack->done; - - dict_for_each_by_length (&rack->solution, - dict_paint_action, - &cursor); + length = 1; + count = 0; + do { + if (rack->done) + cursor.show = DICT_PAINT_CURSOR_SHOW_ALL; + else + cursor.show = DICT_PAINT_CURSOR_SHOW_FOUND; + count += dict_for_each_of_length (&rack->solution, + dict_paint_action, &cursor, + length, length); + if (! rack->done) { + cursor.show = DICT_PAINT_CURSOR_SHOW_UNFOUND_BLANKS; + dict_for_each_of_length (&rack->solution, + dict_paint_action, &cursor, + length, length); + } + length++; + } while (count < rack->solution_total); cairo_restore (cr); } @@ -285,6 +324,7 @@ rack_init (rack_t *rack, dict_add_words_from_file (&rack->dict, "words.txt"); dict_init (&rack->solution); + rack->solution_total = 0; for (i = 0; i < MAX_TILES; i++) rack->tiles[i] = tile_create (root, 'A', i); @@ -321,6 +361,7 @@ rack_new_game (rack_t *rack) dict_init (&rack->solution); subanagram_expand (word, &rack->dict, &rack->solution); + rack->solution_total = dict_count (&rack->solution); goo_canvas_item_simple_changed (GOO_CANVAS_ITEM_SIMPLE (rack->solution_item), FALSE); } -- 2.43.0