X-Git-Url: https://git.cworth.org/git?a=blobdiff_plain;f=rack-fancy.c;h=99d0aa0fa9b305ffd8e8255cd781ac9d8a6f2102;hb=ec58ce1cd1f8effe49f12485f65c345d75767dd5;hp=38c125394e9c8aeeaa6f4070cf643dafc8b3f362;hpb=f8d083966703a2b0efb6db1782a14a1a0b5d56f4;p=wordgame diff --git a/rack-fancy.c b/rack-fancy.c index 38c1253..99d0aa0 100644 --- a/rack-fancy.c +++ b/rack-fancy.c @@ -16,9 +16,84 @@ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA." */ #include +#include #include +#include +#include +#include +#include +#include + +#include "word-game.h" #include "demo-item.h" +#define MAX_TILES 7 + +typedef struct _tile +{ + char letter; + int rack_index; + int x, y; + GooCanvasItem *item; + gboolean guessed; +} tile_t; + +typedef struct _rack +{ + tile_t *tiles[MAX_TILES]; + int num_tiles; +} rack_t; + +static rack_t the_rack; + +static char the_guess[MAX_TILES]; +static int the_guess_index = 0; + +#define LETTER_SIZE 60 +#define LETTER_PAD 5 + +static void +rack_tile_position (int i, int *x, int *y) +{ + *x = 20 + i * (LETTER_SIZE + LETTER_PAD); + *y = 85; +} + +static void +guess_tile_position (int i, int *x, int *y) +{ + rack_tile_position (i, x, y); + *y -= (LETTER_SIZE + LETTER_PAD); +} + +static tile_t * +tile_create (GooCanvasItem *parent, + char letter, int rack_index) +{ + tile_t *tile; + + tile = g_malloc (sizeof (tile_t)); + tile->letter = tolower (letter); + tile->rack_index = rack_index; + rack_tile_position (rack_index, &tile->x, &tile->y); + tile->item = goo_demo_item_new (parent, + tile->x, tile->y, + LETTER_SIZE, + toupper (letter), + NULL); + tile->guessed = FALSE; + + return tile; +} + +static void +tile_glide_to (tile_t *tile, int x, int y) +{ + goo_demo_item_glide_to (tile->item, x, y); + tile->x = x; + tile->y = y; +} + static gboolean on_delete_event (GtkWidget *window, GdkEvent *event, @@ -27,6 +102,123 @@ on_delete_event (GtkWidget *window, exit (0); } +static int +rand_within (int num_values) +{ + return (int) ((double) num_values * (rand() / (RAND_MAX + 1.0))); +} + +static void +shuffle (int *array, int length) +{ + int i, r, tmp; + + for (i = 0; i < length; i++) + { + r = i + rand_within (length - i); + tmp = array[i]; + array[i] = array[r]; + array[r] = tmp; + } +} + +static void +rack_init (rack_t *rack, GooCanvasItem *parent, char *word) +{ + int i; + + for (i = 0; i < MIN (MAX_TILES, strlen (word)); i++) + rack->tiles[i] = tile_create (parent, word[i], i); + rack->num_tiles = i; + while (i < MAX_TILES) + rack->tiles[i] = NULL; +} + +static gboolean +rack_shuffle (rack_t *rack) +{ + int indices[MAX_TILES]; + int i, x, y; + + for (i = 0; i < rack->num_tiles; i++) + indices[i] = i; + + shuffle (indices, rack->num_tiles); + + for (i = 0; i < rack->num_tiles; i++) { + rack->tiles[i]->rack_index = indices[i]; + rack_tile_position (indices[i], &x, &y); + tile_glide_to (rack->tiles[i], x, y); + } + + return TRUE; +} + +static gboolean +on_key_press_event (GtkWidget *widget, + GdkEventKey *event, + gpointer user_data) +{ + int i, x, y; + char guess_letter; + rack_t *rack = user_data; + + if (event->keyval == GDK_space) { + for (i = 0; i < rack->num_tiles; i++) { + if (rack->tiles[i]->guessed) { + rack_tile_position (rack->tiles[i]->rack_index, &x, &y); + tile_glide_to (rack->tiles[i], x, y); + rack->tiles[i]->guessed = FALSE; + } + } + the_guess_index = 0; + rack_shuffle (rack); + return TRUE; + } + + if (event->keyval == GDK_BackSpace) { + gboolean found = FALSE; + int found_index; + x = 0; + for (i = 0; i < rack->num_tiles; i++) { + /* XXX: evil stuff here... please refactor a lot */ + if (the_guess[the_guess_index-1] == rack->tiles[i]->letter && + rack->tiles[i]->guessed && + rack->tiles[i]->x > x) + { + found = TRUE; + found_index = i; + } + } + if (found) { + rack_tile_position (rack->tiles[found_index]->rack_index, &x, &y); + tile_glide_to (rack->tiles[found_index], x, y); + rack->tiles[found_index]->guessed = FALSE; + the_guess_index--; + return TRUE; + } + return FALSE; + } + + /* XXX: event->string is deprecated, but the non-deprecated + * input-method stuff (GtkIMContext) is extremely non-obvious to + * use. */ + guess_letter = tolower (event->string[0]); + for (i = 0; i < rack->num_tiles; i++) { + if (guess_letter == rack->tiles[i]->letter && + ! rack->tiles[i]->guessed) + { + guess_tile_position (the_guess_index, &x, &y); + tile_glide_to (rack->tiles[i], x, y); + rack->tiles[i]->guessed = TRUE; + the_guess[the_guess_index++] = guess_letter; + return TRUE; + } + } + + return FALSE; +} + static GtkWidget * create_window (void) { @@ -38,6 +230,10 @@ create_window (void) g_signal_connect (window, "delete_event", (GtkSignalFunc) on_delete_event, NULL); + gtk_widget_add_events (window, GDK_KEY_PRESS_MASK); + g_signal_connect (window, "key_press_event", + (GtkSignalFunc) on_key_press_event, &the_rack); + scrolled_window = gtk_scrolled_window_new (NULL, NULL); gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled_window), GTK_SHADOW_IN); @@ -50,21 +246,11 @@ create_window (void) return scrolled_window; } -static gboolean -on_button_press (GooCanvasItem *item, - GooCanvasItem *target, - GdkEventButton *event, - gpointer data) -{ - g_print ("demo item received button press event\n"); - return TRUE; -} - static void -create_canvas (GtkWidget *parent) +create_canvas (GtkWidget *parent, char *word) { GtkWidget *canvas; - GooCanvasItem *root, *rect; + GooCanvasItem *root; canvas = goo_canvas_new (); gtk_widget_set_size_request (canvas, 400, 400); @@ -74,25 +260,34 @@ create_canvas (GtkWidget *parent) root = goo_canvas_get_root_item (GOO_CANVAS (canvas)); - rect = goo_demo_item_new (root, 30, 20, 50, 30, - "fill-color", "purple", - NULL); - - g_signal_connect (rect, "button_press_event", - (GtkSignalFunc) on_button_press, NULL); - + rack_init (&the_rack, root, word); } int main (int argc, char *argv[]) { + struct timeval tv; + bag_t bag; + char rack[8]; + int i; GtkWidget *window; - gtk_init (&argc, &argv); + gettimeofday (&tv, NULL); + srand (tv.tv_sec ^ tv.tv_usec); + bag_init (&bag); + bag_shuffle (&bag); + + memcpy (rack, bag.tiles, 7); + rack[7] = '\0'; + + for (i = 0; i < 7; i++) + rack[i] = toupper (rack[i]); + + gtk_init (&argc, &argv); window = create_window (); - create_canvas (window); + create_canvas (window, rack); gtk_main ();