Отправляет email-рассылки с помощью сервиса Sendsay

Программирование в Delphi

  Все выпуски  

Делаем игрушку "Пятнашки"


Здравствуйте!

Как вы думаете, какие самые игры: WarCraft, Quake? Нет! Минёр, тетрис, «шарики» – вот игры всех времён и народов. В «серьёзные» игры играют не все, а в тетрис на компьютере играл каждый!

Сегодня мы напишем одну из таких “ZBest Game” – “Пятнашки”.Смысл игры: выбранная пользователем картинка разбивается на 16 кусочков, перемешивается и её ,естессно, надо собрать.

Сначала займёмся интерфейсом. Поместите на форму компонент ToolBar1, и в нём разместите 5 кнопок Toolbutton.

Вот какие функции они будут выполнять:

ToolButton1-Новая игра

ToolButton2-Показать/Спрятать оригинал

ToolButton3-Заново перемешать картинку

ToolButton4-О программе

ToolButton5-Выход

Задайте кнопкам соответствующие картинки. Для этого создайте компонент ImageList, добавьте в него иконки, и пропишите его в свойстве Images компонента ToolBar. Ещё нам понадобится компонент OpenPictureDialog и 3 компонента Image.В их свойства Width и Height поставьте 200.  Один из них назовите Map и поместите на форме слева – здесь появится разрезанная картинка. Второй Image назовите Original и поместите правее первого. В нём будет оригинал картинки. Третий Image назовите StrechImage и сделайте его невидимым – это служебный Image и пользователю его видеть не положено :)).

 

Теперь приступим к кодерству. Объявите глобальные переменные:

  pic: array[1..16] of TBitMap;

  mass: array [1..4, 1..4] of smallint;

  orig:boolean;

В массиве pic у на будут храниться кусочки мозайки, а в mass – индексы картинок..

Создайте процедуру Picture.

procedure TMain.Picture;

var i, j, count:smallint;

SRS: TRect;

begin

OpenPictureDialog1.execute;

If OpenPictureDialog1.filename<> '' then

begin

Original.Picture.LoadFromFile(OpenPictureDialog1.filename);

StrechImage.canvas.StretchDraw(StrechImage.clientrect, Original.picture.graphic);

count:=0;

SRS.Left:=0;

srs.Top:=0;

srs.Right:=50;

srs.Bottom:=50;

For J:= 1 to 4 do

begin

 For i:= 1 to 4 do

 begin

  count:=count+1;

 Pic[count].Canvas.CopyRect(pic[count].Canvas.ClipRect, StrechImage.canvas, SRS);

 srs.left:=srs.Left+50;

 srs.Right:=srs.Right+50;

 end;

srs.Left:=0;

srs.Right:=50;

srs.Top:=srs.Top+50;

srs.Bottom:=srs.bottom+50;

end;

pic[16].Canvas.fillrect(clientrect);

end;

Map.Enabled:=true;

end;

Эта процедура загружает выбранную пользователем картинку в Original, а затем с помощью метода StrechDraw копирует в StrechImage уже в том разрешении,  которое нам и нужно: 200x200. Дальше сжатая картинка разбивается на 16 кусков, которые последовательно записываются в массив pic. Pic[16] затирается – это будет пустая ячейка, благодаря которой можно перемещать остальные кусочки.

Теперь сделаем процедуру, которая в случайном порядке введёт индексы кусочков мозайки в массив mass.

procedure TMain.Restart;

var i, j: smallint;

f: boolean;

bool: array [1..16] of boolean;

begin

For i:= 1 to 16 do bool[i]:=false;

 For j:= 1 to 4 do

 begin

  For i:= 1 to 4 do

  begin

  f:=true;

   while f=true do

   begin

   mass[i, j]:=random(16)+1;

   If bool[mass[i, j]]=false then

   begin

   bool[mass[i, j]]:=true;

   f:=false;

   end;

   end;

  end;

 end;

Draw;

end;

По сути дела мы перемешали кусочки мозайки. Теперь их нужно нарисовать, для этого создадим процедуру Draw.

procedure TMain.Draw;

var i, j, x, y: smallint;

begin

x:=0;

y:=0;

 For j:= 1 to 4 do

 begin

  For i:= 1 to 4 do

  begin

  Map.canvas.draw(x, y, pic[mass[i, j]]);

  x:=x+50;

  end;

  x:=0;

  y:=y+50;

 end;

end;

Всё, с «самопальными» процедурами закончено, начнём прописывать события, связанные с интерфейсом.

procedure TMain.FormCreate(Sender: TObject);

var i:smallint;

begin

orig:=true;

for i:= 1 to 16 do

begin

pic[i]:=TBitMap.create; //Выделяем в памяти место под наши картинки

pic[i].Height:=50;

pic[i].Width:=50;

end;

end;

 

//Кнопка «Новая игра»

procedure TMain.ToolButton1Click(Sender: TObject);

begin

Picture;

Restart;

end;

 

 

// Кнопка «Рестарт»

procedure TMain.ToolButton3Click(Sender: TObject);

begin

Restart;

end;

 

//Кнопка «Показать/Спрятать оригинал»

procedure TMain.ToolButton2Click(Sender: TObject);

begin

If orig=true then

begin

N10.Checked:=false;

orig:=false;

Main.Width:=223;

ToolButton2.Hint:=’Показать оригинал’;

end

else

begin

n10.checked:=true;

orig:=true;

Main.Width:=436;

ToolButton2.Hint:='Спрятать оригинал';

end;

end;

Здесь остановимся подробнее. При запуске программы оригинал картинки виден. При этом длина моей формы – 436. При нажатии кнопки «Спрятать оригинал» форма должна уменьшить свою длину, спрятав оригинал. Когда моя форма укорочена, её длина равна 223. У вас скорее всего будут другие результаты! Поэтому «померьте» свою форму в «суженном» и «расширенном» состояниях, пропишите в процедуре ToolButton2Click СВОИ ЗНАЧЕНИЯ!

Теперь самое интересное – процедура обработки кликлв мышки на компоненте map.

Процедура довольно громоздкая, но ничего страшного в ней нет!

В переменных posX и posY мы вычисляем на каком по номеру кусочке мозаики щёлкнул пользователь,  и если справа, слева, сверху или снизу есть пустой квадратик – меняет их местами.

procedure TMain.MapMouseDown(Sender: TObject; Button: TMouseButton;

  Shift: TShiftState; X, Y: Integer);

var p, i, j, posX, posY: smallint;

begin

posX:=x div 50 +1;

posY:= y div 50 +1;

 

If mass[posX-1, posY]=16 then

begin

mass[posX, posY]:= Mass[posX-1, posY]+mass[posX, posY];

mass[posx-1, posY]:=mass[posX, posY]- mass[posX-1, posY];

mass[posX, posY]:= mass[posX, posY]-mass[posX-1, posY];

end

else

If mass[posX+1, posY]=16 then

begin

mass[posX, posY]:= Mass[posX+1, posY]+mass[posX, posY];

mass[posx+1, posY]:=mass[posX, posY]- mass[posX+1, posY];

mass[posX, posY]:= mass[posX, posY]-mass[posX+1, posY];

end

else

If mass[posX, posY-1]=16 then

begin

mass[posX, posY]:= Mass[posX, posY-1]+mass[posX, posY];

mass[posx, posY-1]:=mass[posX, posY]- mass[posX, posY-1];

mass[posX, posY]:= mass[posX, posY]-mass[posX, posY-1];

end

else

If mass[posX, posY+1]=16 then

begin

mass[posX, posY]:= Mass[posX, posY+1]+mass[posX, posY];

mass[posx, posY+1]:=mass[posX, posY]- mass[posX, posY+1];

mass[posX, posY]:= mass[posX, posY]-mass[posX, posY+1];

end;

Draw;

p:=0;

For j:= 1 to 4 do

begin

 For i:= 1 to 4 do

 begin

 If mass[i, j]= (j*4) - (4-i) then p:=p+1;

 end;

end;

If p=16 then Application.MessageBox('Вы выиграли!', 'Поздравляю!');

end;

procedure TMain.ToolButton5Click(Sender: TObject);

begin

close;

end;

 

Напоследок давайте сделаем небольшой чит-код(Разработчики называют их «Easter eggs» - “Пасхальные яйца”). При нажатии клавиши «w» с зажатым Shift’ом, картинка будет складываться сама ;))

procedure TMain.FormKeyPress(Sender: TObject; var Key: Char);

var i, j: smallint;

begin

If (key='W') and (Map.Enabled=true) then

begin

For j:= 1 to 4 do

begin

 For i:= 1 to 4 do mass[i, j]:=(4*j) - (4-i);

end;

Draw;

end;

end;

//Включаем генератор случайных чисел

initialization

randomize;

По своему усмотрению прикрутите к проге секундомер, подсчёт сделанных «телодвижений» и вуаля – вполне работоспособная игрушка готова!

Исходники программы здесь, а здесь – -exe.

C уважением, Valar.


В избранное