Sign in Join
Wiki copytemporary

15-puzzle: what changed

Revision 1 to 2. Removed lines have a minus sign; added lines have a plus sign.

OldNewLine
11## 15-puzzle
22
3-<figure>
4-<img src="puzzle15.png" title="puzzle15.png" />
5-<figcaption>puzzle15.png</figcaption>
6-</figure>
3+![](/wiki-images/2/20/Puzzle15.png)
74
85The 15-puzzle is a sliding puzzle that consists of a frame of numbered square tiles in random order with one tile missing. The object of the puzzle is to place the tiles in order by making sliding moves that use the empty space.
96
107## Create code
118
129- Create a new blank GUI application with the form [[TForm|Form1]]
1310- Change caption Form1 to *15Puzzle*'.
1411- Add New [[Unit]] [[15-puzzle|unitGameBoard.pas]]
1512- Create the OnCreate event handler for the form, by clicking on your form, use the Object Inspector, the tab events, select the OnCreate event and click the button \[...\] or double click the button in the form.
1613- Add following code:
1714
1815``` pascal
1916procedure TForm1.FormCreate(Sender: TObject);
2017var
2118 i : Integer;
2219 aButton: TButton;
2320 point:TPoint;
2421begin
2522 Randomize;
2623 Puzzle15:= TGameBoard.Create;
2724 i := 1;
2825 while i < 16 do
2926 begin //create 15 Buttons
3027 aButton:=TButton.Create(Self); //create Button, Owner is Form1, where the button is released later
3128 aButton.Parent:=Self; //determine where it is to be displayed
3229 aButton.Caption:=IntToStr(i); //Captions of the buttons
3330 aButton.Width:=aButton.Height; //Width should correspond to the height of the buttons
3431 point := Puzzle15.ButtonPlace(aButton.Caption);
3532 aButton.Left:= point.x* aButton.Width; //Distance from left
3633 aButton.Top := point.y* aButton.Height;
3734
3835 aButton.OnClick:=@aButtonClick; //the event handler for the button -> will be created yet
3936 inc(i);
4037 end;
4138 Self.Height:=aButton.Height*6; //Height of the form should correspond to the height of the buttons
4239 Self.Width:=aButton.Width*6; //Width of the form to match the width of all buttons
4340end;
4441```
4542
4643- Create in the Object Inspector the event handler for the event FormDestroy, by clicking on the button \[...\].
4744- Add the following code to the handler:
4845
4946``` pascal
5047procedure TForm1.FormDestroy(Sender: TObject);
5148begin
5249 FreeAndNil(Puzzle15);
5350end;
5451```
5552
5653- Now you must create the event handler for the button clicks.
5754- In the source editor, entering your [[Class|class]] TForm1 in the section [[Private|private]].
58-- Add [[Procedure|procedure]] `procedure aButtonClick(Sender: TObject);` and then press the keys <span class="kbd">Ctrl</span>+<span class="kbd">Shift</span>+<span class="kbd">c</span> (the code completion becomes active and creates the `procedure TForm1.aButtonClick(Sender: TObject);`.
55+- Add [[Procedure|procedure]] `procedure aButtonClick(Sender: TObject);` and then press the keys `Ctrl`+`Shift`+`c` (the code completion becomes active and creates the `procedure TForm1.aButtonClick(Sender: TObject);`.
5956- Paste following code:
6057
6158``` pascal
6259procedure TForm1.aButtonClick(Sender: TObject); //the event handler for the button
6360var
6461 i:integer;
6562 point : TPoint;
6663begin
6764 if (Sender is TButton) and //called the event handler of a button out?
6865 TryStrToInt(TButton(Sender).Caption, i) //then try to convert the label in a integer
6966 then
7067 begin
7168 if Puzzle15.CanMove(TButton(Sender).Caption) then
7269 begin
7370 point := Puzzle15.Change(TButton(Sender).Caption);
7471 TButton(Sender).Left:= point.x* TButton(Sender).Width; //Distance from left
7572 TButton(Sender).Top := point.y* TButton(Sender).Height;
7673 end;
7774 end;
7875end;
7976```
8077
8178## Source code
8279
8380### unit1.pas
8481
8582``` pascal
8683unit Unit1;
8784
8885{$mode objfpc}{$H+}
8986
9087interface
9188
9289uses
9390 Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls,
9491 unitGameBoard;
9592
9693type
9794
9895 { TForm1 }
9996
10097 TForm1 = class(TForm)
10198 procedure FormCreate(Sender: TObject);
10299 procedure FormDestroy(Sender: TObject);
103100 private
104101 { private declarations }
105102 Puzzle15:TGameBoard;
106103 procedure aButtonClick(Sender: TObject);
107104
108105 public
109106 { public declarations }
110107 end;
111108
112109var
113110 Form1: TForm1;
114111
115112implementation
116113
117114{$R *.lfm}
118115
119116{ TForm1 }
120117
121118procedure TForm1.FormCreate(Sender: TObject);
122119var
123120 i : Integer;
124121 aButton: TButton;
125122 point:TPoint;
126123begin
127124 Randomize;
128125 Puzzle15:= TGameBoard.Create;
129126 i := 1;
130127 while i < 16 do
131128 begin //create 15 Buttons
132129 aButton:=TButton.Create(Self); //create Button, Owner is Form1, where the button is released later
133130 aButton.Parent:=Self; //determine where it is to be displayed
134131 aButton.Caption:=IntToStr(i); //Captions of the buttons
135132 aButton.Width:=aButton.Height; //Width should correspond to the height of the buttons
136133 point := Puzzle15.ButtonPlace(aButton.Caption);
137134 aButton.Left:= point.x* aButton.Width; //Distance from left
138135 aButton.Top := point.y* aButton.Height;
139136 aButton.OnClick:=@aButtonClick; //the event handler for the button -> will be created yet
140137 inc(i);
141138 end;
142139 Self.Height:=aButton.Height*6; //Height of the form should correspond to the height of the buttons
143140 Self.Width:=aButton.Width*6; //Width of the form to match the width of all buttons
144141end;
145142
146143procedure TForm1.FormDestroy(Sender: TObject);
147144begin
148145 FreeAndNil(Puzzle15);
149146end;
150147
151148procedure TForm1.aButtonClick(Sender: TObject); //the event handler for the button
152149var
153150 i:integer;
154151 point : TPoint;
155152begin
156153 if (Sender is TButton) and //called the event handler of a button out?
157154 TryStrToInt(TButton(Sender).Caption, i) //then try to convert the label in a integer
158155 then
159156 begin
160157 if Puzzle15.CanMove(TButton(Sender).Caption) then
161158 begin
162159 point := Puzzle15.Change(TButton(Sender).Caption);
163160 TButton(Sender).Left:= point.x* TButton(Sender).Width; //Distance from left
164161 TButton(Sender).Top := point.y* TButton(Sender).Height;
165162 end;
166163 end;
167164end;
168165
169166end.
170167```
171168
172169### Unit1.lfm
173170
174171``` pascal
175172object Form1: TForm1
176173 Left = 362
177174 Height = 184
178175 Top = 162
179176 Width = 432
180177 Caption = '15Puzzle'
181178 OnCreate = FormCreate
182179 OnDestroy = FormDestroy
183180 LCLVersion = '1.6.0.4'
184181end
185182```
186183
187184### unitGameBoard.pas
188185
189186``` pascal
190187unit unitGameBoard;
191188
192189{$mode objfpc}{$H+}
193190
194191interface
195192
196193uses
197194 Classes, SysUtils;
198195
199196const
200197 GB_MAX_BUTTONS = 15;
201198 GB_MAX_X = 4;
202199 GB_MAX_Y = 4;
203200 GB_EMPTY_PLACE ='-';
204201type
205202
206203 { TGameBoard }
207204
208205 TGameBoard = class
209206 private
210207 GameArray:array[1..GB_MAX_X, 1..GB_MAX_Y] of string;
211208 function ValidPoint(a_point:TPoint):boolean;
212209 public
213210 constructor Create;
214211 function ButtonPlace(a_name:string):TPoint;
215212 function CanMove(a_name:string):Boolean;
216213 function Change(a_name: string): TPoint;
217214 procedure RandomArray;
218215 destructor Destroy; override;
219216 end;
220217implementation
221218
222219{ TGameBoard }
223220
224221function TGameBoard.ValidPoint(a_point: TPoint): boolean;
225222begin
226223 result := true;
227224 if a_point.y > GB_MAX_Y then result := false;
228225 if a_point.x > GB_MAX_X then result := false;
229226 if a_point.y < 1 then result := false;
230227 if a_point.x < 1 then result := false;
231228end;
232229
233230constructor TGameBoard.Create;
234231var
235232 i, x, y : integer;
236233begin
237234 i := 1;
238235 for y := 1 to GB_MAX_Y do
239236 for x := 1 to GB_MAX_X do
240237 begin
241238 if i < GB_MAX_BUTTONS+1
242239 then GameArray[x,y] := IntToStr(i)
243240 else GameArray[x,y] := GB_EMPTY_PLACE;
244241 inc(i);
245242 end;
246243 RandomArray;
247244end;
248245
249246function TGameBoard.ButtonPlace(a_name: string): TPoint;
250247var
251248 x,y:integer;
252249begin
253250 result.x := 0;
254251 result.y := 0;
255252 for y := 1 to GB_MAX_Y do
256253 for x := 1 to GB_MAX_X do
257254 if GameArray[x,y] = a_name then
258255 begin
259256 result.x := x;
260257 result.y := y;
261258 end;
262259end;
263260
264261function TGameBoard.CanMove(a_name: string): Boolean;
265262var
266263 empty, point:TPoint;
267264begin
268265 result := false;
269266 empty := ButtonPlace( GB_EMPTY_PLACE );
270267 point := ButtonPlace(a_name);
271268 if (abs(empty.x-point.x)=1) and (empty.y=point.y) then result := true;
272269 if (abs(empty.y-point.y)=1) and (empty.x=point.x) then result := true;
273270end;
274271
275272function TGameBoard.Change(a_name: string): TPoint;
276273var
277274 empty, point:TPoint;
278275begin
279276 empty := ButtonPlace( GB_EMPTY_PLACE );
280277 result := empty;
281278 point := ButtonPlace(a_name);
282279 GameArray[point.x, point.y] := '-';
283280 GameArray[empty.x, empty.y] := a_name;
284281end;
285282
286283procedure TGameBoard.RandomArray;
287284var
288285 j,i:integer;
289286 name:string;
290287 point,point2:TPoint;
291288begin
292289 for i := 0 to 1000 do
293290 begin
294291 j := random(4);
295292 point := ButtonPlace( GB_EMPTY_PLACE );
296293 point2 := point;
297294 case j of
298295 0: point2.x := point.x-1;
299296 1: point2.x := point.x+1;
300297 2: point2.y := point.y-1;
301298 3: point2.y := point.y+1;
302299 end;
303300 if ValidPoint( point2 ) then
304301 begin
305302 name := GameArray[point2.x, point2.y];
306303 GameArray[point.x, point.y] := name;
307304 GameArray[point2.x, point2.y] := GB_EMPTY_PLACE;
308305 end;
309306 end;
310307end;
311308
312309destructor TGameBoard.Destroy;
313310begin
314311 inherited Destroy;
315312end;
316313
317314end.
318315```
319316
320317## See also
321318
322319- [[TButton]]
323320
324321---
325322*From the Free Pascal wiki, page "15-puzzle", as it stood on 2022-08-06 after a change by Kai Burghardt, out of the wiki's dump of 2024-05-26. Copyright stays with the author who wrote it, according to the old wiki's [[Licensing]] page. If you have concerns about this material, [message the admin](/wiki-contact).*

Back to history