//+------------------------------------------------------------------+
//|                                             Большие пятнашки.mq4 |
//|                        Copyright 2016, MetaQuotes Software Corp. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "vorese"
#property link      "https://www.mql5.com/ru/users/vorese"
#property version   "1.00"
#property strict
#property indicator_chart_window
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
enum  level
  {
   low=1,
   high=2,
  };
input level Level_difficulty=2;//уровень сложности
input color clr_text_butt=clrMidnightBlue;
input color clr_stop_butt=clrRed;
input color clr_button=clrDarkGreen;
input color clr_frame=clrMaroon;
input color clr_background=clrBlack;
input color clr_text=clrPaleTurquoise;
input int xdist=5;
input int ydist=20;

int
x_empty=0,
y_empty=0,
count_0=0,
xx=0,
yy=0,
array_rand[7];

bool tr_step1=true,
tr_event=false;

string
stop_butt=NULL,
str_name=NULL,
array_letter[7]={"","P","R","O","F","I","T"},
array_name[29];

#define ms 50
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
   EventSetMillisecondTimer(ms);

   f_GetRand(1,30,7,array_rand);
   ArraySort(array_rand);

   RectLabelCreate(clr_frame,clr_background,4+xdist,4+ydist);

   f_Step_0();

   return(INIT_SUCCEEDED);
  }
//===================================================================
void OnDeinit(const int reason)
  {
   f_Delete_object();
   ObjectDelete("RectLabel");
//--- destroy timer
   EventKillTimer();
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[])
  {
   return(rates_total);
  }
//+------------------------------------------------------------------+
//| Timer function                                                   |
//+------------------------------------------------------------------+
void OnTimer()
  {
   count_0++;
   int num_1=0,num_2=0;
   if(tr_step1 && f_Pause(2000,ms,count_0))
     {
      f_Delete_object();
      f_Step_1();
      tr_step1=false;
     }
   if(tr_event)
     {
      if(Level_difficulty==1)
        {
         num_1=2;num_2=5;
        }
      else
        {
         num_1=3;num_2=4;
        }
      if(f_Direction(xx,yy,x_empty,y_empty) && f_Stop_button(array_letter,stop_butt,str_name,xx,yy,num_1,num_2))
        {
         if(f_Offset(str_name,xx,yy,x_empty,y_empty))tr_event=false;
        }
     }
   ChartRedraw();
  }
//+------------------------------------------------------------------+
//| ChartEvent function                                              |
//+------------------------------------------------------------------+
//====================================================================
void OnChartEvent(const int id,
                  const long &lparam,
                  const double &dparam,
                  const string &sparam)
  {
   for(int a=0;a<29;a++)
     {
      if(sparam=="but"+IntegerToString(a,1))
        {
         xx=(int)ObjectGetInteger(0,array_name[a],OBJPROP_XDISTANCE);
         yy=(int)ObjectGetInteger(0,array_name[a],OBJPROP_YDISTANCE);
         stop_butt=ObjectGetString(0,array_name[a],OBJPROP_TEXT);
         ObjectSetInteger(0,str_name,OBJPROP_STATE,false);
         str_name=array_name[a];
         tr_event=true;
        }
     }
   return;
  }
//+------------------------------------------------------------------+
bool f_Stop_button(string &array[],string st_butt,string name_butt,int x,int y,int index1,int index2)
  {
   if(st_butt==array[index1] && x==10+xdist+31*(index1-1) && y==10+ydist+31*2)
     {
      ObjectSetInteger(0,name_butt,OBJPROP_BGCOLOR,clr_stop_butt);
      return(false);
     }
   else
   if(st_butt==array[index2] && x==10+xdist+31*(index2-1) && y==10+ydist+31*2)
     {
      ObjectSetInteger(0,name_butt,OBJPROP_BGCOLOR,clr_stop_butt);
      return(false);
     }
   else
      return(true);
  }
//====================================================================
bool f_Offset(string name_butt,int x,int y,int &xempty,int &yempty)
  {
   ObjectSetInteger(0,name_butt,OBJPROP_YDISTANCE,yempty);
   ObjectSetInteger(0,name_butt,OBJPROP_XDISTANCE,xempty);
   ObjectSetInteger(0,name_butt,OBJPROP_STATE,false);
   xempty=x;
   yempty=y;
   return(false);
  }
//====================================================================
bool f_Direction(int a,int b,int c,int d)
  {
   if(a-c==31 && d==b)return(true);
   else
      if(c-a==31 && d==b)return(true);
   else
      if(b-d==31 && c==a)return(true);
   else
      if(d-b==31 && c==a)return(true);
   else
      return(false);
  }
//====================================================================
void f_Step_1()
  {
   int c=0,d=1,e=0,r=0;
   color clr_butt=clrNONE;
   string letter=NULL;

   for(int a=0;a<5;a++)
     {
      for(int b=0;b<6;b++)
        {
         c++;

         if(array_rand[0]==c)
           {
            x_empty=10+xdist+31*b;
            y_empty=10+ydist+31*a;
            continue;
           }

         if(d<7 && c==array_rand[d])
           {
            letter=array_letter[d];clr_butt=clr_text_butt;d++; 
           }
         else
           {
            r++;
            clr_butt=clr_button;
            if(Level_difficulty==1)
              {
               letter="#";
              }
            else
              {
               letter=(string)r;
              }
           }
         array_name[e]="but"+IntegerToString(e,1);
         ButtonCreate("but"+IntegerToString(e,1),10+xdist+31*b,10+ydist+31*a,letter,clr_butt,clr_text);
         e++;
        }
     }
  }
//====================================================================
void f_Step_0()
  {
   int e=0,r=0,size=11;
   color clr_butt=clrNONE;
   string letter=NULL;

   for(int a=0;a<5;a++)
     {
      for(int b=0;b<6;b++)
        {
         if(a==2)
           {
            letter=array_letter[b+1];clr_butt=clr_text_butt;
            if(Level_difficulty==2)
              {
               if(b==2 || b==3)clr_butt=clr_stop_butt;
              }
            else
              {
               if(b==1 || b==4)clr_butt=clr_stop_butt;
              }
           }
         else
           {
            r++;
            if(Level_difficulty==2)
              {
               letter=IntegerToString(r,1);clr_butt=clr_button;
              }
            else
              {
               letter="#";clr_butt=clr_button;
              }
           }
         if(a!=4 || b!=5)
           {
            array_name[e]="but"+IntegerToString(e,1);

            ButtonCreate("but"+IntegerToString(e,1),10+xdist+31*b,10+ydist+31*a,letter,clr_butt,clr_text);
            e++;
           }
        }
     }
  }
//+-------------------------------------------------------------------+ 
//|Генератор случайных чисел. Помещает в массив, переданный по ссылке,|            
//|серию не совпадающих чисел.                                        |  
//+-------------------------------------------------------------------+
void f_GetRand(int min,int max,int num,int &array[])
  {
   int v=0,t=0,b=0;
   MathSrand(GetTickCount());
   while(true)
     {
      bool tr_cycle=false;
      v=MathRand();
      if(v>=min && v<=max)
        {
         if(t==0)
           {
            array[0]=v; t++; continue;
           }
         else
           {
            for(b=0;b<t;b++)
              {
               if(array[b]==v)
                 {
                  t--; tr_cycle=true;
                 }
              }
            if(!tr_cycle)
              {
               array[t]=v; t++;
              }
           }
        }
      if(t==num)break;
     }
  }
//====================================================================
bool f_Pause(int pause,int m,int count)
  {
   if(pause/m>count)
      return(false);
   else
      return(true);
  }
//====================================================================
void f_Delete_object()
  {
   for(int a=0;a<29;a++)
     {
      ObjectDelete("but"+(string)a);
     }
  }
//+------------------------------------------------------------------+
//| Создает прямоугольную метку                                      |
//+------------------------------------------------------------------+
void RectLabelCreate(const color            clr=clrBlue,               // цвет плоской границы (Flat)
                     const color            back_clr=C'236,233,216',   // цвет фона
                     const int              x=30,                      // координата по оси X
                     const int              y=30,                      // координата по оси Y
                     const long             chart_ID=0,                // ID графика
                     const string           name="RectLabel",          // имя метки
                     const int              sub_window=0,              // номер подокна                     
                     const int              width=197,                 // ширина
                     const int              height=166,                // высота
                     const ENUM_BORDER_TYPE border=BORDER_FLAT,        // тип границы
                     const ENUM_BASE_CORNER corner=CORNER_LEFT_UPPER,  // угол графика для привязки
                     const ENUM_LINE_STYLE  style=STYLE_SOLID,         // стиль плоской границы
                     const int              line_width=5,              // толщина плоской границы
                     const bool             back=false,                // на заднем плане
                     const bool             selection=false,           // выделить для перемещений
                     const bool             hidden=false,              // скрыт в списке объектов
                     const long             z_order=0)                 // приоритет на нажатие мышью
  {
//--- сбросим значение ошибки
   ResetLastError();

   if(ObjectFind(name)==-1)
     {
      //--- создадим прямоугольную метку     
      ObjectCreate(chart_ID,name,OBJ_RECTANGLE_LABEL,sub_window,0,0);
      //--- установим координаты метки
      ObjectSetInteger(chart_ID,name,OBJPROP_XDISTANCE,x);
      ObjectSetInteger(chart_ID,name,OBJPROP_YDISTANCE,y);
      //--- установим размеры метки
      ObjectSetInteger(chart_ID,name,OBJPROP_XSIZE,width);
      ObjectSetInteger(chart_ID,name,OBJPROP_YSIZE,height);
      //--- установим цвет фона
      ObjectSetInteger(chart_ID,name,OBJPROP_BGCOLOR,back_clr);
      //--- установим тип границы
      ObjectSetInteger(chart_ID,name,OBJPROP_BORDER_TYPE,border);
      //--- установим угол графика, относительно которого будут определяться координаты точки
      ObjectSetInteger(chart_ID,name,OBJPROP_CORNER,corner);
      //--- установим цвет плоской рамки (в режиме Flat)
      ObjectSetInteger(chart_ID,name,OBJPROP_COLOR,clr);
      //--- установим стиль линии плоской рамки
      ObjectSetInteger(chart_ID,name,OBJPROP_STYLE,style);
      //--- установим толщину плоской границы
      ObjectSetInteger(chart_ID,name,OBJPROP_WIDTH,line_width);
      //--- отобразим на переднем (false) или заднем (true) плане
      ObjectSetInteger(chart_ID,name,OBJPROP_BACK,back);
      //--- включим (true) или отключим (false) режим перемещения метки мышью
      ObjectSetInteger(chart_ID,name,OBJPROP_SELECTABLE,selection);
      ObjectSetInteger(chart_ID,name,OBJPROP_SELECTED,selection);
      //--- скроем (true) или отобразим (false) имя графического объекта в списке объектов
      ObjectSetInteger(chart_ID,name,OBJPROP_HIDDEN,hidden);
      //--- установим приоритет на получение события нажатия мыши на графике
      ObjectSetInteger(chart_ID,name,OBJPROP_ZORDER,z_order);
     }
  }
//===============кнопки===============================================
bool ButtonCreate(const string  name="button",      // имя кнопки
                  const int x=0,                    // координата по оси X
                  const int y=0,                    // координата по оси Y
                  const string text="error",        // текст
                  const color  back_clr=clrNONE,    // цвет фона  
                  const color clr=clrWhite,// цвет текста
                  const int font_size=13,// размер шрифта
                  //===================                                                        
                  const bool back=false,            // на заднем плане
                  const bool selection=false,       // выделить для перемещений
                  const bool hidden=false,          // скрыт в списке объектов
                  const bool state=false,           // нажата/отжата  
                  const int width=30,               // ширина кнопки
                  const int height=30,              // высота кнопки
                  const color border_clr=clrNONE,   // цвет границы  
                  const string  font="Verdana",       // шрифт 
                  const long z_order=0)             // приоритет на нажатие мышью  
  {
   ResetLastError();
   if(ObjectFind(name)==-1)
     {
      ObjectCreate(0,name,OBJ_BUTTON,0,0,0);
      ObjectSetInteger(0,name,OBJPROP_XSIZE,width);
      ObjectSetInteger(0,name,OBJPROP_YSIZE,height);
      ObjectSetInteger(0,name,OBJPROP_CORNER,CORNER_LEFT_UPPER);
      ObjectSetString(0,name,OBJPROP_FONT,font);
      ObjectSetInteger(0,name,OBJPROP_FONTSIZE,font_size);
      ObjectSetInteger(0,name,OBJPROP_COLOR,clr);
      ObjectSetInteger(0,name,OBJPROP_BORDER_COLOR,border_clr);
      ObjectSetInteger(0,name,OBJPROP_BACK,back);
      ObjectSetInteger(0,name,OBJPROP_SELECTABLE,selection);
      ObjectSetInteger(0,name,OBJPROP_SELECTED,selection);
      ObjectSetInteger(0,name,OBJPROP_HIDDEN,hidden);
      ObjectSetInteger(0,name,OBJPROP_ZORDER,z_order);
     }
   ObjectSetInteger(0,name,OBJPROP_STATE,state);
   ObjectSetString(0,name,OBJPROP_TEXT,text);
   ObjectSetInteger(0,name,OBJPROP_BGCOLOR,back_clr);
   ObjectSetInteger(0,name,OBJPROP_YDISTANCE,y);
   ObjectSetInteger(0,name,OBJPROP_XDISTANCE,x);
   return(true);
  }
//+------------------------------------------------------------------+
