#include <stdlib.h>
#include <time.h>
#include <gtk/gtk.h>
#define COLS 10
#define ROWS 20
const int size = 30;
const int colors_count = 3;
const double colors[][3] = {
{ 1, 1, 1 },
{ 1, 1, 0 },
{ 1, 0, 0 },
{ 0, 0, 1 },
{ 0.66, 0.66, 0.66 },
{ 0.33, 0.33, 0.33 } };
int board[COLS][ROWS];
void new_game() {
srand(time(NULL));
for(int x = 0; x < COLS; ++x)
for(int y = 0; y < ROWS; ++y)
board[x][y] = 1 + rand()%colors_count;
}
int get_block(int x, int y) {
if (x < 0 || y < 0 || x >= COLS || y >= ROWS)
return -1;
return board[x][y];
}
void check(int x, int y) {
int color = get_block(x, y);
if (color > 0) {
if (get_block(x-1, y) == color) {
board[x][y] = 0;
check(x-1, y);
board[x-1][y] = 0;
}
if (get_block(x+1, y) == color) {
board[x][y] = 0;
check(x+1, y);
board[x+1][y] = 0;
}
if (get_block(x, y-1) == color) {
board[x][y] = 0;
check(x, y-1);
board[x][y-1] = 0;
}
if (get_block(x, y+1) == color) {
board[x][y] = 0;
check(x, y+1);
board[x][y+1] = 0;
}
}
}
void fall() {
int dx = 0;
for(int x = 0; x < COLS; ++x) {
int dy = 0;
for(int y = 0; y < ROWS; ++y) {
if (board[x][y] != 0) {
if (dx > 0 || dy > 0) {
board[x-dx][y-dy] = board[x][y];
board[x][y] = 0;
}
} else {
++dy;
}
}
if (dy == ROWS) ++dx;
}
}
gboolean button_press(GtkWidget *widget, GdkEventButton *event, gpointer data) {
if (event->button == 1) {
check((int)(event->x)/size, ROWS - 1 - (int)(event->y)/size);
fall();
} else
if (event->button == 3) {
new_game();
}
gtk_widget_queue_draw(widget);
return TRUE;
}
gboolean draw(GtkWidget *widget, cairo_t *cr, gpointer data) {
for(int x = 0; x < COLS; ++x) {
for(int y = 0; y < ROWS; ++y) {
int c = board[x][ROWS - 1 - y];
cairo_rectangle(cr, x*size, y*size, size, size);
cairo_set_source_rgb(cr, colors[c][0], colors[c][1], colors[c][2]);
cairo_fill(cr);
}
}
return TRUE;
}
void activate(GtkApplication* app, gpointer data) {
GtkWidget *window = gtk_application_window_new (app);
g_signal_connect(window, "draw", G_CALLBACK(draw), NULL);
g_signal_connect(window, "button-press-event", G_CALLBACK(button_press), NULL);
gtk_window_set_default_size(GTK_WINDOW(window), size*COLS, size*ROWS);
gtk_widget_add_events(window, GDK_BUTTON_PRESS_MASK);
gtk_widget_show_all(window);
new_game();
}
int main(int argc, char **argv) {
GtkApplication *application = gtk_application_new(NULL, 0);
g_signal_connect(application, "activate", G_CALLBACK(activate), NULL);
int status = g_application_run(G_APPLICATION(application), argc, argv);
g_object_unref(application);
return status;
}