Пазл

jpg.

Задача: создать игру Пазл;
Использованный API: GTK/GDK;
Среда разработки: Visual Studio 2008;

Игра пазл:
Имеется два окна: пример картинки и сам пазл. Нужно, переставляя части пазла на пустое место, собрать картинку.

Основная задача - убедиться, что пазл соберется. Для этого необходимо проверить на четность количество инверсий в перестановках. Если оно четное - пазл соберется верно, иначе мы перемешиваем части пазла еще раз.

/* Подключаемые модули */
#pragma comment(lib,"gthread-2.0.lib")
#pragma comment(lib,"gtk-win32-2.0.lib")
#pragma comment(lib,"glib-2.0.lib")
#pragma comment(lib,"gobject-2.0.lib")
#pragma comment(lib,"gdk-win32-2.0.lib")
#pragma comment(lib,"gdk_pixbuf-2.0.lib")
#pragma comment(lib,"pango-1.0.lib")
#pragma comment(lib,"pangowin32-1.0.lib")
#pragma comment(lib,"intl.lib")
 
/* Подключаемые библиотеки;
WIDTH - ширина создаваемого окна;
HEIGHT - высота создаваемого окна;
N - разрядность матрицы ||NxN||;
R - длина стороны квадратика;
shadow - сдвиг, чтобы из квадрата, радиуса R, получить квадрат радиуса чуть меньше;
*/
 
#include <gdk/gdkkeysyms.h>
#include <gtk/gtk.h>
#include <stdlib.h>
#include <time.h>
#define WIDTH N*R
#define HEIGHT N*R
#define N 4
#define R 100
#define shadow 5
 
int X1,Y1,Y2,X2,x1,x2,y1,y2,I,J,vector;
int a[N][N],lent;
GdkGC *gc,*gc1;//графические контексты
GtkWidget *window,*window1;//окна
GdkDrawable *w,*w1;//области рисования
double x_mouse, y_mouse;//координаты мышки
 
GtkWidget *mstart,*mst1,*mst2,*mst3,*mst4,*mst5,*mst6,*mst7,*mst8,*mst9,*mst10,*mst11,*mst12,*mst13,*mst14,*mst15,*mst16,*ms;
GdkPixbuf *start,*st1,*st2,*st3,*st4,*st5,*st6,*st7,*st8,*st9,*st10,*st11,*st12,*st13,*st14,*st15,*st16,*t,*s;
 
 
 
gboolean boolstart(GtkWidget *widget); // функция перерисовки состояния.
gboolean mousemove(GtkWidget *w, GdkEvent *e,gpointer data); // отслеживание перемещение мышки
gboolean on_click(GtkWidget *Window, GdkEventButton *event, gpointer data); // функция, обрабатывающая, событие: click
gboolean on_draw(GtkWidget *widget, GdkEventExpose *event, gpointer data); // задает исходное состояние.
gboolean apis(GtkWidget *widget, GdkEventExpose *event, gpointer data); // задает полную картинку.
gboolean destroy(GtkWidget *widget); // разрушение.
gboolean keypress(GtkWidget *widget, GdkEventKey *e,gpointer data); // обработка нажатия клавиш на клавиатуре.
gint delete_event(GtkWidget *widget); // удаление события.
gboolean time_wind(GtkWidget *widget); // перемещение кусочка пазла.
gboolean gdk_draw_picture(GdkPixbuf *picture,gint x,gint y); // прорисовка изображения.
 
/* отслеживание перемещений мышки */
 
gboolean mousemove(GtkWidget *w, GdkEvent *e,gpointer data)
{
	double a,b;
	gdk_event_get_coords(e,&a,&b);
	x_mouse=a;
	y_mouse=b;
	return FALSE;
 
}
 
gboolean gdk_draw_picture(GdkPixbuf *picture,gint x,gint y) // прорисовка изображения.
 
{
	gdk_draw_pixbuf(w,gc,picture,0,0,x,y,R,R,GDK_RGB_DITHER_NONE,0,0);
	return TRUE;
}
 
/* обработка нажатия клавиш на клавиатуре */
gboolean keypress(GtkWidget *widget, GdkEventKey *e,gpointer data)
{
	int st[N*N - 1],i,k,j,s,zero,t1,rdt,t2,tt1,tt2;
	switch(e->keyval)
 
	{
		case (GDK_r): // если нажали английскую 'r', проверяем состояние;
		{
			do	{
 
				rdt = rand()%100 + 20;
				for(i=0; i<rdt; i++)
				{
					t1 = rand()%N;
					t2 = rand()%N;
					tt1 = rand()%(N/2);
					tt2 = rand()%(N/2) + N/2;
					j = a[tt1][t1];
					a[tt1][t1] = a[tt2][t2];
					a[tt2][t2] = j;
				}
 
				for(i=0,k=0; i<N; i++) // переписываем элементы в строчку, исключая 0
				{
					for(j=0; j<N; j++)
					{
						if(a[i][j] != 0) {st[k] = a[i][j]; k++;	}
						else { zero = i + 1;}
					}
				}
				s = 1; 
				k = 0;
				while(s) // подсчет инверсий
				{
					i = 0;
               				s = 0;
					while(i < N*N - 2)
					{
						if(st[i] > st[i+1])
						{
							k++; // +1 инверсия
							s = 1;
							j = st[i];
							st[i] = st[i+1];
							st[i+1] = j;
						}
						i++;
					}
				}
				if((k+zero)%2 == 0) break;
			}while(k);
			boolstart(window);
			break;
	     }
	}
	return TRUE;
}
int main(int arge, char **argv)
{
	int i,j,k;
	gtk_init(&arge,&argv);
	srand(time(0));
	k = 0;
	for(i=0;i<N;i++) // создание начальной матрицы
	{
		for(j=0;j<N;j++)
		{
			k++;
			if(i == N-1 && j == N-1) a[i][j] = 0;
			else a[i][j] = k;
		}
	}
	mst1 = gtk_image_new_from_file("img//st1.jpg");//загружаем картинки
	st1 = gtk_image_get_pixbuf(GTK_IMAGE(mst1));
	mst2 = gtk_image_new_from_file("img//st2.jpg");
	st2 = gtk_image_get_pixbuf(GTK_IMAGE(mst2));
	mst3 = gtk_image_new_from_file("img//st3.jpg");
	st3 = gtk_image_get_pixbuf(GTK_IMAGE(mst3));
	mst4 = gtk_image_new_from_file("img//st4.jpg");
	st4 = gtk_image_get_pixbuf(GTK_IMAGE(mst4));
	mst5 = gtk_image_new_from_file("img//st5.jpg");
	st5 = gtk_image_get_pixbuf(GTK_IMAGE(mst5));
	mst6 = gtk_image_new_from_file("img//st6.jpg");
	st6 = gtk_image_get_pixbuf(GTK_IMAGE(mst6));
	mst7 = gtk_image_new_from_file("img//st7.jpg");
	st7 = gtk_image_get_pixbuf(GTK_IMAGE(mst7));
	mst8 = gtk_image_new_from_file("img//st8.jpg");
	st8 = gtk_image_get_pixbuf(GTK_IMAGE(mst8));
	mst9 = gtk_image_new_from_file("img//st9.jpg");
	st9 = gtk_image_get_pixbuf(GTK_IMAGE(mst9));
	mst10 = gtk_image_new_from_file("img//st10.jpg");
	st10 = gtk_image_get_pixbuf(GTK_IMAGE(mst10));
	mst11 = gtk_image_new_from_file("img//st11.jpg");
	st11 = gtk_image_get_pixbuf(GTK_IMAGE(mst11));
	mst12 = gtk_image_new_from_file("img//st12.jpg");
	st12 = gtk_image_get_pixbuf(GTK_IMAGE(mst12));
	mst13 = gtk_image_new_from_file("img//st13.jpg");
	st13 = gtk_image_get_pixbuf(GTK_IMAGE(mst13));
	mst14 = gtk_image_new_from_file("img//st14.jpg");
	st14 = gtk_image_get_pixbuf(GTK_IMAGE(mst14));
	mst15 = gtk_image_new_from_file("img//st15.jpg");
	st15 = gtk_image_get_pixbuf(GTK_IMAGE(mst15));
	mst16 = gtk_image_new_from_file("img//st16.jpg");
	st16 = gtk_image_get_pixbuf(GTK_IMAGE(mst16));
	ms = gtk_image_new_from_file("img//start.jpg");
	s = gtk_image_get_pixbuf(GTK_IMAGE(ms));
	window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
	window1 = gtk_window_new(GTK_WINDOW_TOPLEVEL);
	gtk_widget_set_size_request(window,WIDTH,HEIGHT);
	gtk_widget_set_size_request(window1,WIDTH,HEIGHT);
	gtk_widget_add_events(window,GDK_POINTER_MOTION_MASK);
	gtk_widget_add_events(window,GDK_BUTTON_PRESS_MASK);
	gtk_widget_add_events(window,GDK_POINTER_MOTION_MASK);
	g_signal_connect(G_OBJECT(window),"motion-notify-event",G_CALLBACK(mousemove),NULL);
	g_signal_connect(G_OBJECT(window),"destroy",G_CALLBACK(destroy),NULL);
	g_signal_connect(G_OBJECT(window),"delete_event",G_CALLBACK(delete_event),NULL);
	g_signal_connect(G_OBJECT(window),"button-press-event",G_CALLBACK(on_click),NULL);
	g_signal_connect(G_OBJECT(window),"key-press-event",G_CALLBACK(keypress),NULL);
	g_signal_connect(G_OBJECT(window),"expose_event",G_CALLBACK(on_draw),NULL);
	g_signal_connect(G_OBJECT(window1),"expose_event",G_CALLBACK(apis),NULL);
	gtk_widget_show_all(window);
	gtk_widget_show_all(window1);
	gtk_main();
	return 0;
}
gboolean destroy(GtkWidget *widget)
{
	return FALSE;
}
gint delete_event(GtkWidget *widget)
{
	gtk_main_quit();
	return 1;
}
/* при нажатии на левую кнопку мыши, проверяем, можем ли мы сдвинуться
в каком-либо направлении (т.е. есть ли в окрестности 0) 
vector:
1 - влево
2 - вверх
3 - вправо
4 - вниз */
gboolean on_click(GtkWidget *Window, GdkEventButton *event, gpointer data)
{
	int i,j;
	for(i=0; i<N; i++)
	{
		for(j=0; j<N; j++)
		{
			if(x_mouse > j*R && x_mouse < (j+1)*R && y_mouse > i*R && y_mouse < (i+1)*R)
			{
				x1 = j*R;
				y1 = i*R;
				I = i;
				J = j;
			}
		}
	}
	vector = 0;
	if(I == 0 || J == 0 || I == N-1 || J == N-1)//если часть пазла находится у границы окна(слева, сверху,справа,снизу)
	{
		if(I == 0 && J == 0)//левый верхний
		{
			if(a[I][J+1] == 0) vector = 3;//если правый пустой двигаемся вправо
			if(a[I+1][J] == 0) vector = 4;//если нижний пустой двигаемся вниз 
		}
		else if(I == 0 && J == N-1)
		{
			if(a[I][J-1] == 0) vector = 1;
			if(a[I+1][J] == 0) vector = 4;
		}
		else if(I == N-1 && J == 0)
		{
			if(a[I-1][J] == 0) vector = 2;
			if(a[I][J+1] == 0) vector = 3;
		}
		else if(I == N-1 && J == N-1)
		{
			if(a[I-1][J] == 0) vector = 2;
			if(a[I][J-1] == 0) vector = 1;
		}
		else if(I == 0)
		{
			if(a[I][J-1] == 0) vector = 1;
			if(a[I+1][J] == 0) vector = 4;
			if(a[I][J+1] == 0) vector = 3;
		}
		else if(I == N-1)
		{
			if(a[I-1][J] == 0) vector = 2;
			if(a[I][J-1] == 0) vector = 1;
			if(a[I][J+1] == 0) vector = 3;
		}
		else if(J == 0)
		{
			if(a[I+1][J] == 0) vector = 4;
			if(a[I-1][J] == 0) vector = 2;
			if(a[I][J+1] == 0) vector = 3;
		}
		else if(J == N-1)
		{
			if(a[I-1][J] == 0) vector = 2;
			if(a[I+1][J] == 0) vector = 4;
			if(a[I][J-1] == 0) vector = 1;
		}
	}
	else
	{
		if(a[I][J-1] == 0) vector = 1;
		if(a[I-1][J] == 0) vector = 2;
		if(a[I][J+1] == 0) vector = 3;
		if(a[I+1][J] == 0) vector = 4;
	}
	g_timeout_add(20,(GSourceFunc)time_wind,(gpointer)window);
	return TRUE;
}
/* После того, как мы сделали случайную перестановку элементов
(при нажатии клавишы 'r', нам нужно вывести на экран результат) */
gboolean boolstart(GtkWidget *widget)
{
	int i,j;
	for(i=0; i<N; i++)
	{
		for(j=0; j<N; j++)
		{
			if(a[i][j] == 1) gdk_draw_picture(st1,j*R,i*R);
			else if(a[i][j] == 2) gdk_draw_picture(st2,j*R,i*R);
			else if(a[i][j] == 3) gdk_draw_picture(st3,j*R,i*R);
			else if(a[i][j] == 4) gdk_draw_picture(st4,j*R,i*R);
			else if(a[i][j] == 5) gdk_draw_picture(st5,j*R,i*R);
			else if(a[i][j] == 6) gdk_draw_picture(st6,j*R,i*R);
			else if(a[i][j] == 7) gdk_draw_picture(st7,j*R,i*R);
			else if(a[i][j] == 8) gdk_draw_picture(st8,j*R,i*R);
			else if(a[i][j] == 9) gdk_draw_picture(st9,j*R,i*R);
			else if(a[i][j] == 10) gdk_draw_picture(st10,j*R,i*R);
			else if(a[i][j] == 11) gdk_draw_picture(st11,j*R,i*R);
			else if(a[i][j] == 12) gdk_draw_picture(st12,j*R,i*R);
			else if(a[i][j] == 13) gdk_draw_picture(st13,j*R,i*R);
			else if(a[i][j] == 14) gdk_draw_picture(st14,j*R,i*R);
			else if(a[i][j] == 15) gdk_draw_picture(st15,j*R,i*R);
			else if(a[i][j] == 0) gdk_draw_picture(st16,j*R,i*R);
		}
	}
	return TRUE;
}
gboolean apis(GtkWidget *widget, GdkEventExpose *event, gpointer data)//прорисовка полной картинки на втором окне
{
	gc1 = widget->style->fg_gc[GTK_WIDGET_STATE(widget)];
	w1 = widget->window;
	gdk_draw_pixbuf(w1,gc1,s,0,0,0,0,WIDTH,HEIGHT,GDK_RGB_DITHER_NONE,0,0);
	return TRUE;
}
/* Создаем изображение начального состояния и задаем начальные элементы (цвета, надписи и т.п.) */
gboolean on_draw(GtkWidget *widget,GdkEventExpose *event, gpointer data)
{
	int i, j, XX1, YY1, XX2, YY2,k;
	XX1 = YY1 = 0; XX2 = WIDTH; YY2 = HEIGHT;
	gc = widget->style->fg_gc[GTK_WIDGET_STATE(widget)];
	w = widget->window;
	for(i=0,k=1; i<N; i++)
	{
		for(j=0; j<N; j++)
		{
			if(k == 1) gdk_draw_picture(st1,j*R,i*R);
			else if(k == 2) gdk_draw_picture(st2,j*R,i*R);
			else if(k == 3) gdk_draw_picture(st3,j*R,i*R);
			else if(k == 4) gdk_draw_picture(st4,j*R,i*R);
			else if(k == 5) gdk_draw_picture(st5,j*R,i*R);
			else if(k == 6) gdk_draw_picture(st6,j*R,i*R);
			else if(k == 7) gdk_draw_picture(st7,j*R,i*R);
			else if(k == 8) gdk_draw_picture(st8,j*R,i*R);
			else if(k == 9) gdk_draw_picture(st9,j*R,i*R);
			else if(k == 10) gdk_draw_picture(st10,j*R,i*R);
			else if(k == 11) gdk_draw_picture(st11,j*R,i*R);
			else if(k == 12) gdk_draw_picture(st12,j*R,i*R);
			else if(k == 13) gdk_draw_picture(st13,j*R,i*R);
			else if(k == 14) gdk_draw_picture(st14,j*R,i*R);
			else if(k == 15) gdk_draw_picture(st15,j*R,i*R);
			else if(k == 0) gdk_draw_picture(st16,j*R,i*R);
			k++;
		}
	}
	return TRUE;
}
/* Перемещение квадратика в направлении найденного вектора (после обработки события: click) */
gboolean time_wind(GtkWidget *widget)
{
	int xx1,yy1;
	if(vector == 1)//влево
	{
		xx1 = x1 - R;
		yy1 = y1;
		if(a[I][J] == 1) t = st1;
		else if(a[I][J] == 2) t = st2;
		else if(a[I][J] == 3) t = st3;
		else if(a[I][J] == 4) t = st4;
		else if(a[I][J] == 5) t = st5;
		else if(a[I][J] == 6) t = st6;
		else if(a[I][J] == 7) t = st7;
		else if(a[I][J] == 8) t = st8;
		else if(a[I][J] == 9) t = st9;
		else if(a[I][J] == 10) t = st10;
		else if(a[I][J] == 11) t = st11;
		else if(a[I][J] == 12) t = st12;
		else if(a[I][J] == 13) t = st13;
		else if(a[I][J] == 14) t = st14;
		else if(a[I][J] == 15) t = st15;
		gdk_draw_picture(st16,x1,y1);
		gdk_draw_picture(t,xx1,yy1);
		a[I][J-1] = a[I][J];
		a[I][J] = 0;
	}
	else if(vector == 2)//вверх
	{
		xx1 = x1;
		yy1 = y1 - R;
		if(a[I][J] == 1) t = st1;
		else if(a[I][J] == 2) t = st2;
		else if(a[I][J] == 3) t = st3;
		else if(a[I][J] == 4) t = st4;
		else if(a[I][J] == 5) t = st5;
		else if(a[I][J] == 6) t = st6;
		else if(a[I][J] == 7) t = st7;
		else if(a[I][J] == 8) t = st8;
		else if(a[I][J] == 9) t = st9;
		else if(a[I][J] == 10) t = st10;
		else if(a[I][J] == 11) t = st11;
		else if(a[I][J] == 12) t = st12;
		else if(a[I][J] == 13) t = st13;
		else if(a[I][J] == 14) t = st14;
		else if(a[I][J] == 15) t = st15;
		gdk_draw_picture(st16,x1,y1);
		gdk_draw_picture(t,xx1,yy1);
		a[I-1][J] = a[I][J];
		a[I][J] = 0;
	}
	else if(vector == 3)//вправо
	{
		xx1 = x1 + R;
		yy1 = y1;
		if(a[I][J] == 1) t = st1;
		else if(a[I][J] == 2) t = st2;
		else if(a[I][J] == 3) t = st3;
		else if(a[I][J] == 4) t = st4;
		else if(a[I][J] == 5) t = st5;
		else if(a[I][J] == 6) t = st6;
		else if(a[I][J] == 7) t = st7;
		else if(a[I][J] == 8) t = st8;
		else if(a[I][J] == 9) t = st9;
		else if(a[I][J] == 10) t = st10;
		else if(a[I][J] == 11) t = st11;
		else if(a[I][J] == 12) t = st12;
		else if(a[I][J] == 13) t = st13;
		else if(a[I][J] == 14) t = st14;
		else if(a[I][J] == 15) t = st15;
		gdk_draw_picture(t,xx1,yy1);
		gdk_draw_picture(st16,x1,y1);
		a[I][J+1] = a[I][J];
		a[I][J] = 0;
	}
	else if(vector == 4)//вниз
	{
		xx1 = x1;
		yy1 = y1 + R;
		if(a[I][J] == 1) t = st1;
		else if(a[I][J] == 2) t = st2;
		else if(a[I][J] == 3) t = st3;
		else if(a[I][J] == 4) t = st4;
		else if(a[I][J] == 5) t = st5;
		else if(a[I][J] == 6) t = st6;
		else if(a[I][J] == 7) t = st7;
		else if(a[I][J] == 8) t = st8;
		else if(a[I][J] == 9) t = st9;
		else if(a[I][J] == 10) t = st10;
		else if(a[I][J] == 11) t = st11;
		else if(a[I][J] == 12) t = st12;
		else if(a[I][J] == 13) t = st13;
		else if(a[I][J] == 14) t = st14;
		else if(a[I][J] == 15) t = st15;
		gdk_draw_picture(t,xx1,yy1);
		gdk_draw_picture(st16,x1,y1);
		a[I+1][J] = a[I][J];
		a[I][J] = 0;
	}
	return FALSE;
}

Ключевые слова: 
игра, пазл
ВложениеРазмер
pasl.rar1.35 Мб