Логичка игра Слагалица

извори Википедија, бесплатна енциклопедија ( Puzzle , Енигматика , Слагалица)


Слагалице су врло популарне логичке игре. Постоје разне врсте и варијанте слагалица. Прочитајте о томе неки од текстова који се налазе на горе наведеним линковима. У оквиру овог текста обрађена је само једна врста слагалица која је и најпознатија. Ради се о уклапању више дводимензионалних елемената који на себи имају нацртан мањи део слике с циљем да се добије оригинална сликa.

Елементи су настали тако што је на ортогоналној табли нацртана оригинална слика, а затим је исечена на много мањих правоугаоних делова такозваних плочица, истих димензија. Плочице се насумично поређају на табли, а особа која решава слагалицу треба да заменом места одабраним плочицама дође до оригиналне слике. Слагалица која се решава на овај начин је добила име 'Преметаљка' .

Распоред насумично поређаних плочица на табли може да се промени сакривањем једне плочице када се добије слободно поље на табли. Слагалица се тада решава померањем плочица по табли, коришћењем слободног поља, и довођењем плочица на жељене позиције на табли. Овакав начин решавања слагалице јe тежи, а због тога што елементи клизају по површини табле, слагалица је добила назив 'Клизаљка'.

Компјутерски програм који симулира описану слагалицу с оба начина решавања може да се преузме кликом на било коју слику програма или са линка на дну ове странице ' Слагалица.zip'. Комплетна контрола у програму се одвија преко менија који се отвара десним кликом. За исправан рад неопходно је да имате инсталиран најновији '.Net framework 4.0' ( ^ ) . Испод се налази главни део програма, а уколико желите можете да преузмете пројекат с комплетним програмом такође на линку на дну стране 'Слагалица отворени код.zip' . Оно што је интересантно за програмере који праве овакав вид слагалице јесте да 'Клизаљка' може да буде и нерешива уколико је почетни распоред плочица на табли неодговарајући. Да би се избегла таква ситуација треба пронаћи такав почетни распоред плочица за који је слагалица решива. Ово се одрађује врло једноставним математичким решењем, које је имплементирано у оквиру програмског кода у делу 'Пронађи све могуће пермутације индекса плочица'.

/*****************************************************************************************************

* Назив програма : Слагалица *

* Верзија програма : 2.0 *

* Креиран помоћу : SharpDevelop *

* Аутор програма : Перић Жељко *

* Програмски језик : C# *

* Датум : 25.04.2012 *

* Време : 13:32 *

* *

* Опис програма : Програм 'Слагалица' је проста логичка игра уклапања дводимензионалних елемената. *

* На квадратној табли је нацртана слика, а затим је табла исечена на девет једнаких *

* плочица које су насумично поређане у квадратној мрежи димензија 3х3 поља. *

* Циљ је да се слагалица реши и оригинална слика поново склопи премештањем плочица. *

* Oво може да се уради на два начина. *

* *

* Заменом места плочицама одабиром парова плочица које замењују места. *

* Слагалица с овим начином решавања се зове 'Преметаљка' *

* *

* Померањем плочица тзв. клизањем лево, десно, горе или доле употребом *

* слободног поља на табли.Слагалица с овим начином решавања се зове 'Клизаљка'. *

* За овај начин решавања јако је битан почетни распоред плочица, јер Слагалица *

* није решива за сваки почетни распоред. Објашњење погледајте у оквиру програма *

* у делу 'Пронађи све могуће пермутације индекса плочица'. *

* *

* *

* Све најбоље, *

* Аутор *

* *

*****************************************************************************************************/

using System;

using System.ComponentModel;

using System.Diagnostics;

using System.Drawing;

using System.Drawing.Imaging;

using System.Windows.Forms;


namespace Слагалица

{

public partial class MainForm : Form

{

#region- Глобалне променљиве -

//

// Променљива за приступ сликама смештеним у локалној датотеци унутар програма

//

ComponentResourceManager Слике = new ComponentResourceManager(typeof(MainForm));

//

// Бројач слика у локалној датотеци унутар програма

//

int Следећа_Слика_Бројач = 65;

// Табела 'Плочице' садржи

// сличице исечене из оригиналне слике

PictureBox [] Плочице;

// Табела 'Табла' садржи индексе плочица

// и представља тренутни распоред плочица на табли

//

// 1 2 3

//

// 1 2 3 4

// 2 8 7 6

// 3 5 1 9

//

//

int [,] Табла;

// Табела 'Почетни_Распореди_Плочица' садржи

// све могуће пермутације индекса плочица

string [] Почетни_Распореди_Плочица;

// Једна од многобројних могућих пермутација

//

// Почетни распоред плочица на табли

//

const string Почетни_Распоред_Плочица = "123456789";

// Једна од многобројних могућих пермутација

//

// Крајњи распоред плочица на табли

//

const string Крајњи_Распоред_Плочица = "123456789";

// Индекс плочице која ће на табли бити замењена празном плочицом

// и представљати празно поље на табли

//

// Ово је битно само у случају када играч решава Слагалицу - Клизаљку

//

int Индекс_Празног_Поља = 9;

// Променљиве за смештање потребних

// вредности приликом премештања плочица

// с једне на другу позицију на табли

//

int Индекс_Плочице = 0;

int Позиција_Плочице_X = 0;

int Позиција_Плочице_Y = 0;

bool Премести = false;

#endregion

public MainForm()

{

InitializeComponent();

Иницијализуј_Табеле();

Иницијализуј_Плочице();

Иницијализуј_Мени();

Пронађи_Све_Распореде_Плочица();

}

#region- Иницијализација -

void Подеси_Видљивост_Поља(bool Видљиво, int Милисекунди)

{

Поље1.Visible = Видљиво;

Refresh();

Пауза(Милисекунди);

Поље2.Visible = Видљиво;

Refresh();

Пауза(Милисекунди);

Поље3.Visible = Видљиво;

Refresh();

Пауза(Милисекунди);

Поље4.Visible = Видљиво;

Refresh();

Пауза(Милисекунди);

Поље5.Visible = Видљиво;

Refresh();

Пауза(Милисекунди);

Поље6.Visible = Видљиво;

Refresh();

Пауза(Милисекунди);

Поље7.Visible = Видљиво;

Refresh();

Пауза(Милисекунди);

Поље8.Visible = Видљиво;

Refresh();

Пауза(Милисекунди);

Поље9.Visible = Видљиво;

Refresh();

Пауза(Милисекунди);

}

void Подеси_Видљивост_Индекса_Плочица(bool Видљиво, int Милисекунди)

{

Индекс1.Visible = Видљиво;

Индекс1.BringToFront();

Refresh();

Пауза(Милисекунди);

Индекс2.Visible = Видљиво;

Индекс2.BringToFront();

Refresh();

Пауза(Милисекунди);

Индекс3.Visible = Видљиво;

Индекс3.BringToFront();

Refresh();

Пауза(Милисекунди);

Индекс4.Visible = Видљиво;

Индекс4.BringToFront();

Refresh();

Пауза(Милисекунди);

Индекс5.Visible = Видљиво;

Индекс5.BringToFront();

Refresh();

Пауза(Милисекунди);

Индекс6.Visible = Видљиво;

Индекс6.BringToFront();

Refresh();

Пауза(Милисекунди);

Индекс7.Visible = Видљиво;

Индекс7.BringToFront();

Refresh();

Пауза(Милисекунди);

Индекс8.Visible = Видљиво;

Индекс8.BringToFront();

Refresh();

Пауза(Милисекунди);

Индекс9.Visible = Видљиво;

Индекс9.BringToFront();

Refresh();

Пауза(Милисекунди);

Refresh();

}

void Иницијализуј_Табеле()

{

int и;

int ј;


int позиција;

// Табела 'Плочице' садржи

// сличице исечене из оригиналне слике

Плочице = new PictureBox[10];

Плочице.Initialize();

// Додели иницијалне вредности елементима у табели

позиција = 0;

for(позиција=0;позиција<10;позиција++)

{

Плочице[позиција] = new PictureBox();

Плочице[позиција].Image = null;

}

// Табела 'Табла' садржи индексе плочица

// и представља тренутни распоред плочица на табли

Табла = new int [5,5];

Табла.Initialize();

// Додели иницијалне вредности елементима у табели

и = 0;

ј = 0;

for(и=0;и<5;и++)

{

for(ј=0;ј<5;ј++)

{

Табла[и,ј] = -1;

}

}

// Табела 'Почетни_Распореди_Плочица' садржи

// све могуће пермутације индекса плочица

Почетни_Распореди_Плочица = new string[362880];

Почетни_Распореди_Плочица.Initialize();

// Додели иницијалне вредности елементима у табели

и = 0;

for(и=0;и<362880;и++)

{

Почетни_Распореди_Плочица[и] = null;

}

}

void Иницијализуј_Плочице()

{

//

// Исеци оригиналну слику на девет једнаких правоугаоних сличица,

// које имају идентичне димензије и додели их елементима у табели 'Плочице'

// Елементи табеле са својом вредношћу ће представљати Плочице

//

// Поређани елементи табеле на основу индекса,

// у доле приказаном распореду, сачињавају оригиналну слику

//

// 1 2 3

// 4 5 6

// 7 8 9

//

// променљива за смештање оригиналне слике

Bitmap Оригинална_Слика;

// формат пиксела оригиналне слике

PixelFormat Формат;

// правоугаоник дефинисан висином, ширином и координатама једног угла

RectangleF Плочица;

int Висина_Плочице;// висина плочице у пикселима

int Ширина_Плочице;// ширина плочице у пикселима

//

Оригинална_Слика = new Bitmap(BackgroundImage);

Формат = Оригинална_Слика.PixelFormat;

Висина_Плочице = Оригинална_Слика.Height/3;

Ширина_Плочице = Оригинална_Слика.Width/3;


Плочица = new RectangleF();

Плочица.Width = Ширина_Плочице;

Плочица.Height = Висина_Плочице;

// 0. плочица, празна плочица

Плочице[0].Image = null;

// 1. плочица

Плочица.X = 0;

Плочица.Y = 0;

Плочице[1].Image = Оригинална_Слика.Clone(Плочица,Формат);

// 2. плочица

Плочица.X = Ширина_Плочице;

Плочица.Y = 0;

Плочице[2].Image = Оригинална_Слика.Clone(Плочица,Формат);

// 3. плочица

Плочица.X = 2*Ширина_Плочице;

Плочица.Y = 0;

Плочице[3].Image = Оригинална_Слика.Clone(Плочица,Формат);

// 4. плочица

Плочица.X = 0;

Плочица.Y = Висина_Плочице;

Плочице[4].Image = Оригинална_Слика.Clone(Плочица,Формат);

// 5. плочица

Плочица.X = Ширина_Плочице;

Плочица.Y = Висина_Плочице;

Плочице[5].Image = Оригинална_Слика.Clone(Плочица,Формат);

// 6. плочица

Плочица.X = 2*Ширина_Плочице;

Плочица.Y = Висина_Плочице;

Плочице[6].Image = Оригинална_Слика.Clone(Плочица,Формат);

// 7. плочица

Плочица.X = 0;

Плочица.Y = 2*Висина_Плочице;

Плочице[7].Image = Оригинална_Слика.Clone(Плочица,Формат);

// 8. плочица

Плочица.X = Ширина_Плочице;

Плочица.Y = 2*Висина_Плочице;

Плочице[8].Image = Оригинална_Слика.Clone(Плочица,Формат);

// 9. плочица

Плочица.X = 2*Ширина_Плочице;

Плочица.Y = 2*Висина_Плочице;

Плочице[9].Image = Оригинална_Слика.Clone(Плочица,Формат);

}

void Иницијализуј_Мени()

{

//

// Постави доступност опција Менија на почетну вредност

//

Сепаратор1.Visible = true;

СлагалицаКлизаљка.Visible = true;

СлагалицаПреметаљка.Visible = true;

Сепаратор2.Visible = true;

СледећаСлика.Visible = true;

УчитајСлику.Visible = true;

Сепаратор3.Visible = true;

НоваСлагалица.Text = "Нова слагалица";

НоваСлагалица.Visible = true;

Сепаратор4.Visible = false;

РешењеСлагалице.Visible = false;

Сепаратор5.Visible = false;

ПомоћСлагалице.Checked = false;

ПомоћСлагалице.Visible = false;

if(СлагалицаКлизаљка.Checked)

{

СлучајнаПозицијаПразногПоља.Visible = true;

Сепаратор6.Visible = true;

}

else

{

СлучајнаПозицијаПразногПоља.Visible = false;

Сепаратор6.Visible = false;

}

ОпцијеСлагалице.Refresh();

}

#endregion

#region- Пронађи све могуће пермутације индекса плочица -

#region- Правила за утврђивање решивости слагалице -

//

// !!! ВАЖНО !!!

//

// Слагалица - Клизаљка због начина решавања,

// није решива за сваки почетни распоред плочица

// Број инверзија унутар распореда индекса плочица омогућава да се утврди да

// ли је слагалица овог типа решива за тај распоред или није

//

// Објашњење :

// Предпоставимо да је жељени коначни распоред плочица

//

// 1 2 3

// 4 5 6

// 7 8 0

//

// где 0 представља празно поље које омогућава премештање плочица

//

// Сада, посматрамо следећи почетни распоред плочица

//

// 1 2 3

// 4 5 7

// 6 8 0

//

// Распоред плочица у првом реду је онако како би требало да буде

// Други ред је добар све до броја 7 који треба да буде после броја 6

// Ово се зове 'ИНВЕРЗИЈА' унутар распореда

//

// Ако је број инверзија унутар распореда плочица ПАРАН,

// слагалица је решива за посматрани почетни распоред плочица

//

// Ако је број инверзија унутар распореда плочица НЕПАРАН,

// слагалица није решива за посматрани почетни распоред плочица

//

// Следећи пример:

// Посматрајмо следећи почетни распоред плочица

//

// 2 4 3

// 1 0 6

// 7 5 8

//

// Уочавамо следеће инверзије

//

// 2 долази пре 1

// 4 долази пре 3 и 1

// 3 долази пре 1

// 6 долази пре 5

// 7 долази пре 5

//

// Укупно 6 инверзија.Слагалица је решива за овакав почетни распоред плочица

// приликом бројања инверзија не узима се у обзир празно поље које има број 0

//

//

#endregion

void Пронађи_Све_Распореде_Плочица()

{

//

// Промени сличицу показивача на 'Чекај'

//

Cursor = Cursors.WaitCursor;

//

// Пронађи све пермутације индекса плочица

// за девет плочица укупно 362880 пермутација

// елементи прве пермутације

const string прва_пермутација = "123456789";

// елементи последње пермутације

const string последња_пермутација = "987654321";

char [] елементи;// табела за памћење нових пермутација

int број_елемената;// број елемената унутар пермутације

string пермутација = string.Empty;// нова пермутација

int н = 0;// бројач пермутација унутар табеле

int к = 0;// бројач унутар петље


елементи = прва_пермутација.ToCharArray();

број_елемената = прва_пермутација.Length;

Почетни_Распореди_Плочица[н] = прва_пермутација; // прва пермутација

do

{

//

// Пронађи следећу пермутацију индекса

//

н++;

к = 0;

while (к==0)

{

к = Следећа_Пермутација(ref елементи,број_елемената);

}

пермутација = new string(елементи);

Почетни_Распореди_Плочица[н] = пермутација;

}

while(пермутација!=последња_пермутација);

//

// Промени сличицу показивача на 'Рука'

//

Cursor = Cursors.Hand;

}


int Следећа_Пермутација(ref char [] елементи, int број_елемената)

{

//

// Оригинални алгоритам и програм за проналажење пермутација

// Jeffrey A. Johnson, Brigham Young University-Hawaii Campus

// http://www.freewebs.com/permute/soda_submit.html

//

int н = број_елемената - 1;

int м = број_елемената - 1;

char с = ' ';

while( (н > 0) & (елементи[н] <= елементи[н-1]) )

{

н--;

}

н--;

if( н < 0 )

{

return 0;

}

м = број_елемената - 1;

while( (м > н) & (елементи[м] <= елементи[н]) )

{

м--;

}

с = елементи[н];

елементи[н] = елементи[м];

елементи[м] = с;

број_елемената--;

н++;

while(број_елемената>н)

{

с = елементи[број_елемената];

елементи[број_елемената] = елементи[н];

елементи[н] = с;


н++;

број_елемената--;

}

return 1;

}

string Следећи_Решив_Распоред_Плочица(int индекс_празног_поља)

{

//

// Пронађи следећу пермутацију индекса плочица,

// односно почетни распоред плочица

//

// Почетни распоред индекса плочица:

//

// Распоред индекса Пермутација

// плочица на табли

//

// 1 2 3 123456789

// 4 5 6

// 7 8 9

//

int и = 0;// бројач унутар петље

int ј = 0;// бројач унутар петље

int н = 0;// бројач унутар петље

int број_инверзија = 0;// бројач инверзија !!!

string следећи_распоред_плочица = string.Empty;

bool слагалица_није_решива = true;

н = Одабери_Индекс_Почетног_Распореда_Плочица();

while(слагалица_није_решива)

{

н++;

if(н==362880){н=1;}

следећи_распоред_плочица = Почетни_Распореди_Плочица[н];

//

// Провери да ли је Слагалица - Клизаљка решива

// за следећи_распоред_плочица

// Преброј инверзије унутар распореда

//

број_инверзија = 0;

for(и=0;и<8;и++)

{

if(следећи_распоред_плочица[и].ToString()!=индекс_празног_поља.ToString())

{

for(ј=и+1;ј<9;ј++)

{

if(следећи_распоред_плочица[ј].ToString()!=индекс_празног_поља.ToString())

{

if(следећи_распоред_плочица[и]>следећи_распоред_плочица[ј])

{

број_инверзија++;

}

}

}

}

}

// Паран број инверзија значи да је Слагалица решива

if(број_инверзија%2==0)

{

слагалица_није_решива = false;

}

}

//

//

//

return следећи_распоред_плочица;

}

#endregion

#region- Главне методе -

void Промешај_Плочице()

{

//

// Измешај плочице на табли 33 пута

//

int Бројач = 0;

int Милисекунде = 0;

int Индекс_Почетног_Распореда = 0;

string Одабрани_Распоред = string.Empty;

for(Бројач=0;Бројач<33;Бројач++)

{

Индекс_Почетног_Распореда = Одабери_Индекс_Почетног_Распореда_Плочица();

Одабрани_Распоред = Почетни_Распореди_Плочица[Индекс_Почетног_Распореда];

Додели_Индекс_Плочице_Тренутној_Позицији_На_Табли(Одабрани_Распоред);

Постави_Плочице_На_Таблу();

Додели_Индекс_Плочице_Пољима_За_Помоћ();

Милисекунде = 100;

Пауза(Милисекунде);

}

}

int Одабери_Индекс_Празног_Поља()

{

//

// Насумично, изабери индекс плочице која ће бити невидљива

// То ће бити празно поље у оквиру Слагалице - Клизаљке

//

Random Генератор_Случајних_Бројева = new Random();

int Индекс_Празног_Поља = 0;

int Случајан_Број = 0;

Случајан_Број = Генератор_Случајних_Бројева.Next(1,10);

Индекс_Празног_Поља = Случајан_Број;

return Индекс_Празног_Поља;

}

int Одабери_Индекс_Почетног_Распореда_Плочица()

{

//

// Насумично, изабери један од могућих почетних распореда плочица

//

Random Генератор_Случајних_Бројева = new Random();

int Индекс_Почетног_Распореда = 0;

int Случајан_Број = 0;

Случајан_Број = Генератор_Случајних_Бројева.Next(1,362880);

Индекс_Почетног_Распореда = Случајан_Број;

return Индекс_Почетног_Распореда;

}

void Додели_Индекс_Плочице_Тренутној_Позицији_На_Табли(string Пермутација)

{

Табла[1,1] = int.Parse(Пермутација.Substring(0,1));

Табла[1,2] = int.Parse(Пермутација.Substring(1,1));

Табла[1,3] = int.Parse(Пермутација.Substring(2,1));

Табла[2,1] = int.Parse(Пермутација.Substring(3,1));

Табла[2,2] = int.Parse(Пермутација.Substring(4,1));

Табла[2,3] = int.Parse(Пермутација.Substring(5,1));

Табла[3,1] = int.Parse(Пермутација.Substring(6,1));

Табла[3,2] = int.Parse(Пермутација.Substring(7,1));

Табла[3,3] = int.Parse(Пермутација.Substring(8,1));

}

void Додели_Индекс_Плочице_Пољима_За_Помоћ()

{

//

// Одреди тренутни распоред индекса плочица

//

string Тренутни_Распоред_Индекса = string.Empty;

Тренутни_Распоред_Индекса =

Табла[1,1].ToString() +

Табла[1,2].ToString() +

Табла[1,3].ToString() +

Табла[2,1].ToString() +

Табла[2,2].ToString() +

Табла[2,3].ToString() +

Табла[3,1].ToString() +

Табла[3,2].ToString() +

Табла[3,3].ToString();

//

// Промени индекс празне плочице с одабраним индексом празног поља

//

if(СлагалицаКлизаљка.Checked)

{

Тренутни_Распоред_Индекса =

Тренутни_Распоред_Индекса.Replace("0",Индекс_Празног_Поља.ToString());

}

//

// Додели тренутни индекс плочица пољима за помоћ

//

Индекс1.Text = Тренутни_Распоред_Индекса.Substring(0,1);

Индекс2.Text = Тренутни_Распоред_Индекса.Substring(1,1);

Индекс3.Text = Тренутни_Распоред_Индекса.Substring(2,1);

Индекс4.Text = Тренутни_Распоред_Индекса.Substring(3,1);

Индекс5.Text = Тренутни_Распоред_Индекса.Substring(4,1);

Индекс6.Text = Тренутни_Распоред_Индекса.Substring(5,1);

Индекс7.Text = Тренутни_Распоред_Индекса.Substring(6,1);

Индекс8.Text = Тренутни_Распоред_Индекса.Substring(7,1);

Индекс9.Text = Тренутни_Распоред_Индекса.Substring(8,1);

Refresh();

}


void Постави_Плочице_На_Таблу()

{

//

// На основу индекса плочице, додељеног позицији на табли

// додели адекватну сличицу плочице

//

Поље1.Image = Плочице[Табла[1,1]].Image;

Поље2.Image = Плочице[Табла[1,2]].Image;

Поље3.Image = Плочице[Табла[1,3]].Image;

Поље4.Image = Плочице[Табла[2,1]].Image;

Поље5.Image = Плочице[Табла[2,2]].Image;

Поље6.Image = Плочице[Табла[2,3]].Image;

Поље7.Image = Плочице[Табла[3,1]].Image;

Поље8.Image = Плочице[Табла[3,2]].Image;

Поље9.Image = Плочице[Табла[3,3]].Image;

Refresh();

}


void Провери_Решење()

{

//

// Провери да ли је играч решио слагалицу.

//

string Тренутни_Распоред = string.Empty;

Тренутни_Распоред =

Табла[1,1].ToString() +

Табла[1,2].ToString() +

Табла[1,3].ToString() +

Табла[2,1].ToString() +

Табла[2,2].ToString() +

Табла[2,3].ToString() +

Табла[3,1].ToString() +

Табла[3,2].ToString() +

Табла[3,3].ToString();

//

// Промени индекс празне плочице с одабраним индексом празног поља

//

if(СлагалицаКлизаљка.Checked)

{

Тренутни_Распоред =

Тренутни_Распоред.Replace("0",Индекс_Празног_Поља.ToString());

}

if(Тренутни_Распоред==Крајњи_Распоред_Плочица)

{

Додели_Индекс_Плочице_Тренутној_Позицији_На_Табли(Тренутни_Распоред);

Постави_Плочице_На_Таблу();

Refresh();

MessageBox.Show(" Решили сте СЛАГАЛИЦУ. ", " Браво !!!",

MessageBoxButtons.OK,

MessageBoxIcon.Information);

Refresh();

Слагалица_Је_Решена();

}

}

void Слагалица_Је_Решена()

{

Cursor = Cursors.WaitCursor;

Refresh();

int Милисекунде = 0;

Милисекунде = 10;

Подеси_Видљивост_Индекса_Плочица(false, Милисекунде);

Милисекунде = 150;

Подеси_Видљивост_Поља(false, Милисекунде);

Иницијализуј_Мени();

Cursor = Cursors.Hand;

Refresh();

}

void Пауза(int Милисекунде)

{

// Програм прави паузу за жељени број милисекунду

Stopwatch Штоперица = new Stopwatch();

Штоперица.Start();

while(Штоперица.ElapsedMilliseconds<Милисекунде)

{

// Празна петља

}

Штоперица.Stop();

Штоперица.Reset();

}

#endregion

#region- Прикажи могући смер померања плочице -

void ПољеMouseLeave(object sender, EventArgs e)

{

if(СлагалицаКлизаљка.Checked)

{

Cursor = Cursors.Hand;

}

}

void Поље1MouseEnter(object sender, EventArgs e)

{

Прикажи_Смер(1,1);

}


void Поље2MouseEnter(object sender, EventArgs e)

{

Прикажи_Смер(1,2);

}


void Поље3MouseEnter(object sender, EventArgs e)

{

Прикажи_Смер(1,3);

}


void Поље4MouseEnter(object sender, EventArgs e)

{

Прикажи_Смер(2,1);

}


void Поље5MouseEnter(object sender, EventArgs e)

{

Прикажи_Смер(2,2);

}


void Поље6MouseEnter(object sender, EventArgs e)

{

Прикажи_Смер(2,3);

}


void Поље7MouseEnter(object sender, EventArgs e)

{

Прикажи_Смер(3,1);

}


void Поље8MouseEnter(object sender, EventArgs e)

{

Прикажи_Смер(3,2);

}


void Поље9MouseEnter(object sender, EventArgs e)

{

Прикажи_Смер(3,3);

}

void Прикажи_Смер(int Табла_X, int Табла_Y)

{

if(Табла[Табла_X,Табла_Y]!=0 && СлагалицаКлизаљка.Checked)

{

if(Табла[Табла_X,Табла_Y-1]==0)

{

Cursor = Cursors.PanWest;

Refresh();

}

else if(Табла[Табла_X-1,Табла_Y]==0)

{

Cursor = Cursors.PanNorth;

Refresh();

}

else if(Табла[Табла_X+1,Табла_Y]==0)

{

Cursor = Cursors.PanSouth;

Refresh();

}

else if(Табла[Табла_X,Табла_Y+1]==0)

{

Cursor = Cursors.PanEast;

Refresh();

}

}

else if(Табла[Табла_X,Табла_Y]==0 && СлагалицаКлизаљка.Checked)

{

Cursor = Cursors.Hand;

Refresh();

}

}

#endregion


#region- Замени места плочицама -

void Поље1Click(object sender, EventArgs e)

{

Премести_Плочицу(1,1);

}


void Поље2Click(object sender, EventArgs e)

{

Премести_Плочицу(1,2);

}


void Поље3Click(object sender, EventArgs e)

{

Премести_Плочицу(1,3);

}


void Поље4Click(object sender, EventArgs e)

{

Премести_Плочицу(2,1);

}


void Поље5Click(object sender, EventArgs e)

{

Премести_Плочицу(2,2);

}


void Поље6Click(object sender, EventArgs e)

{

Премести_Плочицу(2,3);

}


void Поље7Click(object sender, EventArgs e)

{

Премести_Плочицу(3,1);

}


void Поље8Click(object sender, EventArgs e)

{

Премести_Плочицу(3,2);

}


void Поље9Click(object sender, EventArgs e)

{

Премести_Плочицу(3,3);

}

void Премести_Плочицу(int Табла_X, int Табла_Y)

{

if(Табла[Табла_X,Табла_Y]!=0 && СлагалицаКлизаљка.Checked)

{

if(Табла[Табла_X,Табла_Y-1]==0)

{

Табла[Табла_X,Табла_Y-1] = Табла[Табла_X,Табла_Y];

Табла[Табла_X,Табла_Y] = 0;

Постави_Плочице_На_Таблу();

Додели_Индекс_Плочице_Пољима_За_Помоћ();

Прикажи_Смер(Табла_X,Табла_Y);

}

else if(Табла[Табла_X-1,Табла_Y]==0)

{

Табла[Табла_X-1,Табла_Y] = Табла[Табла_X,Табла_Y];

Табла[Табла_X,Табла_Y] = 0;

Постави_Плочице_На_Таблу();

Додели_Индекс_Плочице_Пољима_За_Помоћ();

Прикажи_Смер(Табла_X,Табла_Y);

}

else if(Табла[Табла_X+1,Табла_Y]==0)

{

Табла[Табла_X+1,Табла_Y] = Табла[Табла_X,Табла_Y];

Табла[Табла_X,Табла_Y] = 0;

Постави_Плочице_На_Таблу();

Додели_Индекс_Плочице_Пољима_За_Помоћ();

Прикажи_Смер(Табла_X,Табла_Y);

}

else if(Табла[Табла_X,Табла_Y+1]==0)

{

Табла[Табла_X,Табла_Y+1] = Табла[Табла_X,Табла_Y];

Табла[Табла_X,Табла_Y] = 0;

Постави_Плочице_На_Таблу();

Додели_Индекс_Плочице_Пољима_За_Помоћ();

Прикажи_Смер(Табла_X,Табла_Y);

}

Провери_Решење();

}

else if(СлагалицаПреметаљка.Checked)

{

if(Премести)

{

Cursor = Cursors.Hand;

Refresh();

Табла[Позиција_Плочице_X, Позиција_Плочице_Y] = Табла[Табла_X, Табла_Y];

Табла[Табла_X, Табла_Y] = Индекс_Плочице;

Премести = false;

Постави_Плочице_На_Таблу();

Додели_Индекс_Плочице_Пољима_За_Помоћ();

Провери_Решење();

}

else

{

Cursor = Cursors.NoMoveHoriz;

Refresh();

Премести = true;

Позиција_Плочице_X = Табла_X;

Позиција_Плочице_Y = Табла_Y;

Индекс_Плочице = Табла[Табла_X, Табла_Y];

}

}

}

#endregion


#region- Опције менија слагалице -

void Нова_Слагалица(object sender, EventArgs e)

{

int Милисекунде = 0;

int Индекс_Почетног_Распореда = 0;

string Одабрани_Распоред = string.Empty;

Cursor = Cursors.WaitCursor;

Refresh();


//

// Промени доступност опција Менија

//

Сепаратор1.Visible = false;

СлагалицаКлизаљка.Visible = false;

СлагалицаПреметаљка.Visible = false;

Сепаратор2.Visible = false;

СледећаСлика.Visible = false;

УчитајСлику.Visible = false;

Сепаратор4.Visible = true;

РешењеСлагалице.Visible = true;

Сепаратор5.Visible = true;

ПомоћСлагалице.Visible = true;

Сепаратор6.Visible = false;

СлучајнаПозицијаПразногПоља.Visible = false;

ОпцијеСлагалице.Refresh();

if(НоваСлагалица.Text == "Нова слагалица")

{

НоваСлагалица.Text = "Поново промешај плочице";

Одабрани_Распоред = Почетни_Распоред_Плочица;

Додели_Индекс_Плочице_Тренутној_Позицији_На_Табли(Одабрани_Распоред);

Постави_Плочице_На_Таблу();

Милисекунде = 300;

Подеси_Видљивост_Поља(true, Милисекунде);

Refresh();

}

Промешај_Плочице();

if(СлучајнаПозицијаПразногПоља.Checked && СлагалицаКлизаљка.Checked)

{

Индекс_Празног_Поља = Одабери_Индекс_Празног_Поља();

}

else

{

Индекс_Празног_Поља = 9;

}

// Ако је Слагалица - Клизаљка

if(СлагалицаКлизаљка.Checked)

{

Индекс_Почетног_Распореда = Одабери_Индекс_Почетног_Распореда_Плочица();

Одабрани_Распоред = Следећи_Решив_Распоред_Плочица(Индекс_Празног_Поља);

Одабрани_Распоред = Одабрани_Распоред.Replace(Индекс_Празног_Поља.ToString(),"0");

Додели_Индекс_Плочице_Тренутној_Позицији_На_Табли(Одабрани_Распоред);

Постави_Плочице_На_Таблу();

Додели_Индекс_Плочице_Пољима_За_Помоћ();

}

// Ако је Слагалица - Преметаљка

else

{

Индекс_Почетног_Распореда = Одабери_Индекс_Почетног_Распореда_Плочица();

Одабрани_Распоред = Почетни_Распореди_Плочица[Индекс_Почетног_Распореда];

Додели_Индекс_Плочице_Тренутној_Позицији_На_Табли(Одабрани_Распоред);

Постави_Плочице_На_Таблу();

Додели_Индекс_Плочице_Пољима_За_Помоћ();

}

Cursor = Cursors.Hand;

Refresh();

}

void Учитај_Слику(object sender, EventArgs e)

{

DialogResult Избор;

Избор = ДијалогУчитајСлику.ShowDialog();

if( Избор == DialogResult.OK )

{

BackgroundImage = new Bitmap(ДијалогУчитајСлику.FileName);


Иницијализуј_Плочице();

}

Cursor = Cursors.Hand;

Refresh();

}

void Решење_Слагалице(object sender, EventArgs e)

{

Cursor = Cursors.Hand;

Refresh();

Слагалица_Је_Решена();

}

void Помоћ_Слагалице(object sender, EventArgs e)

{

int Милисекунде = 0;

Cursor = Cursors.Hand;

Refresh();

//

// Ако је ова опција одабрана,

// приказани су индекси плочица као помоћ играчу

//

if(ПомоћСлагалице.Checked)

{

Милисекунде = 150;

Подеси_Видљивост_Индекса_Плочица(true, Милисекунде);

}

else

{

Милисекунде = 10;

Подеси_Видљивост_Индекса_Плочица(false, Милисекунде);

}

}

void Следећа_Слика(object sender, EventArgs e)

{

Cursor = Cursors.Hand;

Refresh();

Следећа_Слика_Бројач++;

if(Следећа_Слика_Бројач>85)

{

Следећа_Слика_Бројач = 1;

}

BackgroundImage = (System.Drawing.Image)

(Слике.GetObject(Следећа_Слика_Бројач.ToString()));

Иницијализуј_Плочице();

Refresh();

}

void Слагалица_Клизаљка(object sender, EventArgs e)

{

Cursor = Cursors.Hand;

Refresh();

if(СлагалицаКлизаљка.Checked)

{

СлагалицаПреметаљка.Checked = false;

MainForm.ActiveForm.Text = " Слагалица - Клизаљка";

Сепаратор6.Visible = true;

СлучајнаПозицијаПразногПоља.Visible = true;

}

else

{

СлагалицаПреметаљка.Checked = true;

MainForm.ActiveForm.Text = " Слагалица - Преметаљка";

Сепаратор6.Visible = false;

СлучајнаПозицијаПразногПоља.Visible = false;

}

}

void Слагалица_Преметаљка(object sender, EventArgs e)

{

Cursor = Cursors.Hand;

Refresh();

if(СлагалицаПреметаљка.Checked)

{

СлагалицаКлизаљка.Checked = false;

MainForm.ActiveForm.Text = " Слагалица - Преметаљка";

Сепаратор6.Visible = false;

СлучајнаПозицијаПразногПоља.Visible = false;

}

else

{

СлагалицаКлизаљка.Checked = true;

MainForm.ActiveForm.Text = " Слагалица - Клизаљка";

Сепаратор6.Visible = true;

СлучајнаПозицијаПразногПоља.Visible = true;

}

}

#endregion

#region- Прикажи оригиналну сличицу по клику на индекс -

void Индекс1MouseDown(object sender, MouseEventArgs e)

{

Поље1.Hide();

}

void Индекс1MouseUp(object sender, MouseEventArgs e)

{

Поље1.Show();

}

void Индекс2MouseDown(object sender, MouseEventArgs e)

{

Поље2.Hide();

}

void Индекс2MouseUp(object sender, MouseEventArgs e)

{

Поље2.Show();

}

void Индекс3MouseDown(object sender, MouseEventArgs e)

{

Поље3.Hide();

}

void Индекс3MouseUp(object sender, MouseEventArgs e)

{

Поље3.Show();

}

void Индекс4MouseDown(object sender, MouseEventArgs e)

{

Поље4.Hide();

}

void Индекс4MouseUp(object sender, MouseEventArgs e)

{

Поље4.Show();

}

void Индекс5MouseDown(object sender, MouseEventArgs e)

{

Поље5.Hide();

}

void Индекс5MouseUp(object sender, MouseEventArgs e)

{

Поље5.Show();

}

void Индекс6MouseDown(object sender, MouseEventArgs e)

{

Поље6.Hide();

}

void Индекс6MouseUp(object sender, MouseEventArgs e)

{

Поље6.Show();

}

void Индекс7MouseDown(object sender, MouseEventArgs e)

{

Поље7.Hide();

}

void Индекс7MouseUp(object sender, MouseEventArgs e)

{

Поље7.Show();

}

void Индекс8MouseDown(object sender, MouseEventArgs e)

{

Поље8.Hide();

}

void Индекс8MouseUp(object sender, MouseEventArgs e)

{

Поље8.Show();

}

void Индекс9MouseDown(object sender, MouseEventArgs e)

{

Поље9.Hide();

}

void Индекс9MouseUp(object sender, MouseEventArgs e)

{

Поље9.Show();

}

#endregion

}

}

/************************************************************************

* Program Licence : *

* *

* Copyright 2012 , Perić Željko *

* (periczeljkosmederevo@yahoo.com) *

* *

* According to it's main purpose , this program is licensed *

* under the therms of 'Free Software' licence agreement. *

* *

* If You do not know what those therms applies to *

* please read explanation at the following link : *

* (http://www.gnu.org/philosophy/free-sw.html.en) *

* *

* Since it is Free Software this program has no warranty of any kind. *

************************************************************************

* Ethical Notice : *

* *

* It is not ethical to change program code signed by it's author *

* and then to redistribute it under the same author name , *

* especially if it is incorrect. *

* *

* It is recommended that if You make improvement in program code , *

* to make remarks of it and then to sign it with Your own name , *

* for further redistribution as new major version of program. *

* *

* Author name and references of old program code version should be *

* kept , for tracking history of program development. *

* *

* For any further information please contact code author at his email. *

************************************************************************/


/************************************

* List Of Revisions *

************************************

* Mајоr revision of version 1.0 *

* Author 21.03.2014 *

* New algorithm for finding *

* selecting and memorizing, *

* all solvable solutions of puzzle *

* Visibility of Menu options are *

* changed, depending on selection *

* Help on index click developed *

* new comments added *

* New version number 2.0 *

************************************/