GtkTris

Gtk+ 2.0

Description

Tic Tac Toe game written with Gtk+ 2.0 library


Source

/* Semplicissimo gioco del tris per 2 persone
 * realizzato da HdS619 con le Gtk+.
 *
 * Per compilare: gcc hgt.c -o hgt `pkg-config --libs --cflags gtk+-2.0`
*/

#include <gtk/gtk.h>

#define gh(x,y) ((griglia[x][0] == y) && (griglia[x][1] == y) && (griglia[x][2] == y))
#define ght     gh(0,0) || gh(1,0) || gh(2,0) || gh(0,1) || gh(1,1) || gh(2,1)
#define gv(x,y) ((griglia[0][x] == y) && (griglia[1][x] == y) && (griglia[2][x] == y))
#define gvt     gv(0,0) || gv(1,0) || gv(2,0) || gv(0,1) || gv(1,1) || gv(2,1)
#define gd(n)   ((griglia[0][0] == n) && (griglia[1][1] == n) && (griglia[2][2] == n)) || \
                ((griglia[0][2] == n) && (griglia[1][1] == n) && (griglia[2][0] == n))
#define gdt     gd(0) || gd(1)

gint corrente = 0, turni = 0;
gint griglia[3][3] = {{3,3,3},{3,3,3},{3,3,3}};
GtkWidget *button[9];

void _info(gchar* message, int x)
{
 GtkWidget *dialog;
 gint a, b, i = 0;
 dialog = gtk_message_dialog_new (NULL, 0,
                   GTK_MESSAGE_INFO,
              GTK_BUTTONS_CLOSE,
              message);
 gtk_window_set_title(GTK_WINDOW(dialog), "HGT - Errore");

 gtk_dialog_run (GTK_DIALOG (dialog));
 gtk_widget_destroy (dialog);

 if ( x == 1 ) {
      for ( a = 0; a < 3; ++a ) {
            for ( b = 0; b < 3; ++b ) {
                  griglia[a][b] = 3;
                  gtk_button_set_label(GTK_BUTTON(button[i]), " ");
                  i++;
            }
      }
      turni = 0;
 }
}

gboolean posto_occupato(int n)
{
      if ( n > -1 && n < 3 && griglia[0][n] == 3 ) return FALSE;
 else if ( n > 2 && n < 6 && griglia[1][n-3] == 3 ) return FALSE;
 else if ( n > 5 && n < 9 && griglia[2][n-6] == 3 ) return FALSE;
 else return TRUE;
}

void occupa_posto(int n)
{
 if ( n < 3 ) griglia[0][n] = corrente;
 if ( n < 6 ) griglia[1][n-3] = corrente;
 if ( n < 9 ) griglia[2][n-6] = corrente;
}

void tris(gint x)
{
 gchar *str = (gchar *) g_malloc0(50);
 sprintf(str, "Il giocatore \"%s\" ha vinto!\n", (!x) ? "0" : "X");
 _info(str, 1);
}

void tris_control(void)
{
  if ( ght || gvt || gdt ) tris(corrente);
  else if ( turni == 9 ) _info("Pareggio", 1);
}


void segna(GtkWidget *bw, gpointer *n)
{
 int i = (int)n;

 if (posto_occupato(i) == TRUE) {
      _info("Il posto scelto è già occupato.\n\nRiprova!", 0);
 }
 else {
        gtk_button_set_label(GTK_BUTTON(button[i]), (corrente == 0) ? "O" : "X");
        occupa_posto(i);
        turni++;
        tris_control();
        corrente = !corrente;
 }
}

int main(int argc, char **argv)
{
 GtkWidget *window, *table;
 gint i;

 gtk_init(&argc, &argv);

 window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
 gtk_window_set_title(GTK_WINDOW(window), "HGT");

 table = gtk_table_new(3, 3, FALSE);
 gtk_container_add(GTK_CONTAINER(window), table);

 for ( i = 0; i < 9; ++i ) {
       button[i] = gtk_button_new();
       gtk_widget_set_size_request(button[i], 50, 50);

       if ( i < 3 )
       gtk_table_attach(GTK_TABLE(table), button[i], i, i+1, 0, 1,
                        GTK_FILL | GTK_EXPAND, GTK_FILL | GTK_EXPAND, 0, 0);
       else if ( i < 6 )
       gtk_table_attach(GTK_TABLE(table), button[i], i-3, i-2, 1, 2,
                        GTK_FILL | GTK_EXPAND, GTK_FILL | GTK_EXPAND, 0, 0);
       else
       gtk_table_attach(GTK_TABLE(table), button[i], i-6, i-5, 2, 3,
                        GTK_FILL | GTK_EXPAND, GTK_FILL | GTK_EXPAND, 0, 0);

       g_signal_connect(G_OBJECT(button[i]), "clicked", G_CALLBACK(segna), (gpointer*)i);
 }

 gtk_widget_show_all(window);

 g_signal_connect(G_OBJECT(window), "delete_event", G_CALLBACK(gtk_main_quit), NULL);
 gtk_main();
 return 0;
}