// // Copyright (c) 2005,2006 Frlo // #include #include #include #include #define rozmer 8 #define pixlov 40 #define OKRAJ 20 #define PRAZDNE 0 #define BIELY 4 #define CIERNY 2 // musi byt 4 a 2 aby som mohol vypocitat zakazny pohyb dozadu 4-3=1 pre bieleho //a 2-3=-1 pre cierneho #define OZNACENY 1 #define SKOK 8 GtkWidget *window; GtkWidget *drawarea; GtkWidget *vpane, *button; GtkWidget *hwindow; GtkWidget *text; GtkWidget *view; GtkTextBuffer *buffer; GdkGC *gc; GdkColor colbg_biela = { 0, 50000, 50000, 50000 }; GdkColor colfig_biela = { 0, 65000, 65000, 65000 }; GdkColor colbg_cierna = { 0, 25000, 25000, 25000 }; GdkColor colfig_cierna = { 0, 15000, 15000, 15000 }; GdkColor col_skok = { 0, 25000, 25000, 65000 }; GdkColor col_oznaceny = { 0, 65000, 25000, 25000 }; gint8 polohy[rozmer][rozmer]; gint8 *posledny_oznaceny; gint8 natahu; gint8 winner; gint delete_event (GtkWidget * widget, GdkEvent * event, gpointer data) { g_print ("Ukoncene krizikom.\n"); return (FALSE); } void destroy (GtkWidget * widget, gpointer data) { g_print ("Ukoncenie aplikacie.\n"); gtk_exit (1); } void draw_sachovnica (GtkWidget * widget) { int x, y; if (natahu == CIERNY) gdk_gc_set_foreground (gc, &colfig_cierna); else gdk_gc_set_foreground (gc, &colfig_biela); gdk_draw_rectangle (widget->window, gc, TRUE, 0, 0, widget->allocation.width, OKRAJ); gdk_draw_rectangle (widget->window, gc, TRUE, widget->allocation.width - OKRAJ, 0, OKRAJ, widget->allocation.height); gdk_draw_rectangle (widget->window, gc, TRUE, 0, widget->allocation.height - OKRAJ, widget->allocation.width, widget->allocation.height); gdk_draw_rectangle (widget->window, gc, TRUE, 0, 0, OKRAJ, widget->allocation.height); for (x = 0; x < rozmer; x++) for (y = 0; y < rozmer; y++) { if (((x + y) % 2) == 0) gdk_gc_set_foreground (gc, &colbg_cierna); else gdk_gc_set_foreground (gc, &colbg_biela); gdk_draw_rectangle (widget->window, gc, TRUE, x * pixlov + OKRAJ, y * pixlov + OKRAJ, pixlov, pixlov); if (polohy[x][y] & CIERNY) { gdk_gc_set_foreground (gc, &colfig_cierna); gdk_draw_arc (widget->window, gc, TRUE, x * pixlov + OKRAJ, y * pixlov + OKRAJ, pixlov, pixlov, 0, 64 * 360); } else if (polohy[x][y] & BIELY) { gdk_gc_set_foreground (gc, &colfig_biela); gdk_draw_arc (widget->window, gc, TRUE, x * pixlov + OKRAJ, y * pixlov + OKRAJ, pixlov, pixlov, 0, 64 * 360); } if (polohy[x][y] & OZNACENY) { gdk_gc_set_foreground (gc, &col_oznaceny); gdk_draw_rectangle (widget->window, gc, FALSE, x * pixlov + OKRAJ, y * pixlov + OKRAJ, pixlov - 1, pixlov - 1); } else if (polohy[x][y] & SKOK) { gdk_gc_set_foreground (gc, &col_skok); gdk_draw_rectangle (widget->window, gc, FALSE, x * pixlov + OKRAJ, y * pixlov + OKRAJ, pixlov - 1, pixlov - 1); } } } gint drawarea_expose (GtkWidget * widget, GdkEventExpose * event, gpointer callback_data) { g_print ("Prekreslenie grafickej plochy.\n"); g_print ("Oblast: od x=%d, y=%d rozmery sirka=%d, vyska=%d\n", event->area.x, event->area.y, event->area.width, event->area.height); draw_sachovnica (widget); return FALSE; } bool skontroluj_vytaza () { int x, y; bool win_cierny = true; bool win_biely = true; for (x = 0; x < 4; x++) for (y = 0; y < 4 - x; y++) { if (not (polohy[x][y] & BIELY)) win_biely = false; if (not (polohy[rozmer - x - 1][rozmer - y - 1] & CIERNY)) win_cierny = false; } if (win_biely) { winner = BIELY; g_print ("Vyhral BIELY hrac !!!.\n"); } if (win_cierny) { winner = CIERNY; g_print ("Vyhral CIERNY hrac !!!.\n"); } } void vypocitaj_skoky (int in_x, int in_y, int step) { int x, y, ix, iy; for (ix = -1; ix < 2; ix++) { for (iy = -1; iy < 2; iy++) { x = in_x + ix; y = in_y + iy; if ((x >= 0) and (x < rozmer) and (y >= 0) and (y < rozmer) and not ((ix == 0) and (iy == 0)) and not (polohy[x][y] & SKOK) // podmienka aby som sa mohol hybat iba dopredu // and ( (natahu-3)*(ix+iy) <= 0 )) nemohol hybat dozadu and ((natahu - 3) * (ix + iy) < 0)) { if ((step == 0) and not (polohy[x][y] & (CIERNY | BIELY))) polohy[x][y] = polohy[x][y] | SKOK; else if ((polohy[x][y] & (CIERNY | BIELY)) and (x + ix >= 0) and (x + ix < rozmer) and (y + iy >= 0) and (y + iy < rozmer) and (polohy[x + ix][y + iy] == PRAZDNE)) { polohy[x + ix][y + iy] = SKOK; vypocitaj_skoky (x + ix, y + iy, step + 1); } } } } } void odznac_skoky () { int x, y; for (x = 0; x < rozmer; x++) for (y = 0; y < rozmer; y++) { polohy[x][y] = polohy[x][y] & (255 - SKOK); } } void game_init () { int x, y; for (x = 0; x < rozmer; x++) for (y = 0; y < rozmer; y++) { polohy[x][y] = PRAZDNE; } for (x = 0; x < 4; x++) for (y = 0; y < 4 - x; y++) { polohy[x][y] = CIERNY; polohy[rozmer - x - 1][rozmer - y - 1] = BIELY; } posledny_oznaceny = NULL; natahu = BIELY; winner = PRAZDNE; odznac_skoky (); draw_sachovnica (drawarea); } gint button_clicked (GtkWidget * widget, GdkEventButton * event) { game_init (); /* hwindow = gtk_window_new (GTK_WINDOW_TOPLEVEL); g_signal_connect (G_OBJECT (hwindow), "delete_event", G_CALLBACK (delete_event), NULL); gtk_container_set_border_width (GTK_CONTAINER (hwindow), 0); gtk_window_set_default_size(GTK_WINDOW(hwindow), 300, 600); gtk_window_set_resizable (GTK_WINDOW (hwindow), FALSE); gtk_window_set_title (GTK_WINDOW (hwindow), "Pravidla"); gtk_window_set_icon (GTK_WINDOW (hwindow), gdk_pixbuf_new_from_file ("iconka.png", NULL)); view = gtk_text_view_new (); buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view)); gtk_text_buffer_set_text (buffer, "Pravidla hry :\nK tejto stolovej hre potrebujete sachovnicu 8x8 a dvadsat damovych kamenov (10 ciernych a 10 bielych). Rozostavite ich na sachovnici ako ukazuje obrazok cislo 1.\nZacina biely. Posunie jeden zo svojich kamenov do susedneho pola. Potom je na tahu cierny a dalej sa pravidelne striedaju. Kamene postupuju dopredu alebo dostrany, mozu prejst len na susedne policko, s ktorym sa ich policko dotyka bud celou stranou alebo aj rohom.\nKamene spolu nebojuju, maju sa co najrychlejsie presunut do opacneho kuta, odkial vychadza na zaciatku partie super. Postup kamenov sa da urychlit skokom cez jeden alebo viaceroi kamenov, cudzich i vlastnych (ako pri dame). Medzi preskakovanymi kamenmi vsak musi byt vzdy jedno pole volne. Pri viacnasobnom skoku je povolene po kazdom dopade zmenit smer.\nKto ma skorej svojich desat kamenov v povodnom rozostaveni v opacnom rohu sachovnice, vyhrava.\n" , -1); gtk_container_add (GTK_CONTAINER (hwindow), view); gtk_widget_show (view); gtk_widget_show (hwindow);*/ return TRUE; } gint button_press_event (GtkWidget * widget, GdkEventButton * event) { if (winner != PRAZDNE) return FALSE; guint x, y; x = (int) event->x - OKRAJ; y = (int) event->y - OKRAJ; x = x / pixlov; y = y / pixlov; g_print ("Klik: x=%d, y=%d \n", x, y); // klikol som na svoj kamen if (natahu & polohy[x][y]) { // oznacujem pole if (posledny_oznaceny != NULL) *posledny_oznaceny = *posledny_oznaceny & (255 - OZNACENY); polohy[x][y] = polohy[x][y] | OZNACENY; posledny_oznaceny = &polohy[x][y]; odznac_skoky (); vypocitaj_skoky (x, y, 0); } else if (SKOK & polohy[x][y]) { polohy[x][y] = natahu; odznac_skoky (); *posledny_oznaceny = *posledny_oznaceny & (255 - OZNACENY - CIERNY - BIELY); skontroluj_vytaza (); if (winner == PRAZDNE) natahu = abs (natahu - 6); } draw_sachovnica (widget); return FALSE; } int main (int argc, char **argv) { gtk_init (&argc, &argv); window = gtk_window_new (GTK_WINDOW_TOPLEVEL); g_signal_connect (G_OBJECT (window), "delete_event", G_CALLBACK (delete_event), NULL); g_signal_connect (G_OBJECT (window), "destroy", G_CALLBACK (destroy), NULL); gtk_container_set_border_width (GTK_CONTAINER (window), 0); gtk_window_set_resizable (GTK_WINDOW (window), FALSE); gtk_window_set_title (GTK_WINDOW (window), "Rohac, just another chessboard game"); gtk_window_set_icon (GTK_WINDOW (window), gdk_pixbuf_new_from_file ("iconka.png", NULL)); drawarea = gtk_drawing_area_new (); gtk_drawing_area_size (GTK_DRAWING_AREA (drawarea), pixlov * rozmer + 2 * OKRAJ, pixlov * rozmer + 2 * OKRAJ); vpane = gtk_vpaned_new (); button = gtk_button_new_with_label ("Nova hra"); g_signal_connect (G_OBJECT (button), "clicked", G_CALLBACK (button_clicked), NULL); gtk_container_add (GTK_CONTAINER (window), vpane); gtk_container_add (GTK_CONTAINER (vpane), drawarea); gtk_container_add (GTK_CONTAINER (vpane), button); gtk_widget_set_events (drawarea, GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK); gtk_widget_show (drawarea); gtk_widget_show (vpane); gtk_widget_show (button); gtk_widget_show (window); gc = gdk_gc_new (drawarea->window); gdk_colormap_alloc_color (gtk_widget_get_colormap (window), &colbg_biela, TRUE, TRUE); gdk_colormap_alloc_color (gtk_widget_get_colormap (window), &colbg_cierna, TRUE, TRUE); gdk_colormap_alloc_color (gtk_widget_get_colormap (window), &colfig_biela, TRUE, TRUE); gdk_colormap_alloc_color (gtk_widget_get_colormap (window), &colfig_cierna, TRUE, TRUE); gdk_colormap_alloc_color (gtk_widget_get_colormap (window), &col_skok, TRUE, TRUE); gdk_colormap_alloc_color (gtk_widget_get_colormap (window), &col_oznaceny, TRUE, TRUE); g_signal_connect (G_OBJECT (drawarea), "expose_event", G_CALLBACK (drawarea_expose), NULL); g_signal_connect (G_OBJECT (drawarea), "button_press_event", G_CALLBACK (button_press_event), NULL); game_init (); gtk_main (); return (0); }