15-puzzle/fi
From Free Pascal wiki
Jump to navigationJump to search
│
English (en) │
suomi (fi) │
français (fr) │
15-peli
15-peli on liukupalapeli joka koostuu kehyksestä jossa on numeroituja neliömäisiä laattoja satunnaisessa järjestyksessä missä yksi laatta puuttuu. Pelissä tavoitteena on sijoittaa laatat järjestykseen liu'uttamalla siirrettävä pala tyhjään tilaan.
Luodaan ohjelmakoodi
- Luo uusi tyhjä graafinen sovellus lomakkeella Form1
- Muuta lomakkeen Form1 ominaisuus caption arvoon 15Puzzle'.
- Lisää uusi käännösyksikkö unitGameBoard.pas
- Luodaan OnCreate tapahtumakäsittelijä lomakkeelle, käyttämällä komponenttimuokkaimen tapahtumat-välilehteä, valitsemalla OnCreate tapahtuma, klikkaamalla sen [...] painiketta tai kaksoisklikkaamalla painiketta lomakkeella.
- Lisää siihen seuraava koodi:
procedure TForm1.FormCreate(Sender: TObject);
var
i : Integer;
aButton: TButton;
point:TPoint;
begin
Randomize;
Puzzle15:= TGameBoard.Create;
i := 1;
while i < 16 do
begin //luodaan 15 painiketta
aButton:=TButton.Create(Self); //luodaan Button, Owner on Form1, kun painike myöhemmin julkaistaan
aButton.Parent:=Self; //määrittää, missä se on näytettävä
aButton.Caption:=IntToStr(i); //Painikkeessa näkyvä teksti
aButton.Width:=aButton.Height; //Painike on neliö
point := Puzzle15.ButtonPlace(aButton.Caption);
aButton.Left:= point.x* aButton.Width; //painikkeen vasemman reunan etäisyys
aButton.Top := point.y* aButton.Height;
aButton.OnClick:=@aButtonClick; //painikkeen tapahtumakäsittelijä
inc(i);
end;
Self.Height:=aButton.Height*6; //lomakkeen korkeuden määritys
Self.Width:=aButton.Width*6; //lomakkeen leveyden määritys
end;
- Luodaan komponenttimuokkaimella tapahtumakäsittelijä tapahtumalle FormDestroy, klikkaamalla sen painiketta [...].
- Täydennetään tapahtuman koodi seuraavaksi:
procedure TForm1.FormDestroy(Sender: TObject);
begin
FreeAndNil(Puzzle15);
end;
- Seuraavaksi luodaan tapahtumankäsittelijä painikkeiden klikkaukselle.
- Lähdekoodieditorissa siirrytään luokan TForm1 esittelyn private osaan.
- Lisää aliohjelma
procedure aButtonClick (Sender: TObject);
ja paina näppäimiä Ctrl+⇧ Shift+c (Koodin täydennys aktivoituu ja luo aliohjelman rungonprocedure TForm1.aButtonClick (Sender: TObject) ;
. - Täydennetään se tälläiseksi:
procedure TForm1.aButtonClick(Sender: TObject); //Painikkeen tapahtumankäsittelijä
var
i:integer;
point : TPoint;
begin
if (Sender is TButton) and //Tarkistetaan että tapahtuman tultiin näppäimen painalluksella
TryStrToInt(TButton(Sender).Caption, i) // ja onko sen teksti kokonaisluku
then
begin
if Puzzle15.CanMove(TButton(Sender).Caption) then
begin
point := Puzzle15.Change(TButton(Sender).Caption);
TButton(Sender).Left:= point.x* TButton(Sender).Width;
TButton(Sender).Top := point.y* TButton(Sender).Height;
end;
end;
end;
Lähdekoodi
unit1.pas
unit Unit1;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls,
unitGameBoard;
type
{ TForm1 }
TForm1 = class(TForm)
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
private
{ private declarations }
Puzzle15:TGameBoard;
procedure aButtonClick(Sender: TObject);
public
{ public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.lfm}
{ TForm1 }
procedure TForm1.FormCreate(Sender: TObject);
var
i : Integer;
aButton: TButton;
point:TPoint;
begin
Randomize;
Puzzle15:= TGameBoard.Create;
i := 1;
while i < 16 do
begin //luodaan 15 painiketta
aButton:=TButton.Create(Self); //luodaan Button, Owner on Form1, kun painike myöhemmin julkaistaan
aButton.Parent:=Self; //määrittää, missä se on näytettävä
aButton.Caption:=IntToStr(i); //Painikkeessa näkyvä teksti
aButton.Width:=aButton.Height; //Painike on neliö
point := Puzzle15.ButtonPlace(aButton.Caption);
aButton.Left:= point.x* aButton.Width; //painikkeen vasemman reunan etäisyys
aButton.Top := point.y* aButton.Height;
aButton.OnClick:=@aButtonClick; //painikkeen tapahtumakäsittelijä
inc(i);
end;
Self.Height:=aButton.Height*6; //lomakkeen korkeuden määritys
Self.Width:=aButton.Width*6; //lomakkeen leveyden määritys
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
FreeAndNil(Puzzle15);
end;
procedure TForm1.aButtonClick(Sender: TObject); //Painikkeen tapahtumankäsittelijä
var
i:integer;
point : TPoint;
begin
if (Sender is TButton) and //Tarkistetaan että tapahtuman tultiin näppäimen painalluksella
TryStrToInt(TButton(Sender).Caption, i) // ja onko sen teksti kokonaisluku
then
begin
if Puzzle15.CanMove(TButton(Sender).Caption) then
begin
point := Puzzle15.Change(TButton(Sender).Caption);
TButton(Sender).Left:= point.x* TButton(Sender).Width;
TButton(Sender).Top := point.y* TButton(Sender).Height;
end;
end;
end;
end.
Unit1.lfm
object Form1: TForm1
Left = 362
Height = 184
Top = 162
Width = 432
Caption = '15Puzzle'
OnCreate = FormCreate
OnDestroy = FormDestroy
LCLVersion = '1.6.0.4'
end
unitGameBoard.pas
unit unitGameBoard;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils;
const
GB_MAX_BUTTONS = 15;
GB_MAX_X = 4;
GB_MAX_Y = 4;
GB_EMPTY_PLACE ='-';
type
{ TGameBoard }
TGameBoard = class
private
GameArray:array[1..GB_MAX_X, 1..GB_MAX_Y] of string;
function ValidPoint(a_point:TPoint):boolean;
public
constructor Create;
function ButtonPlace(a_name:string):TPoint;
function CanMove(a_name:string):Boolean;
function Change(a_name: string): TPoint;
procedure RandomArray;
destructor Destroy; override;
end;
implementation
{ TGameBoard }
function TGameBoard.ValidPoint(a_point: TPoint): boolean;
begin
result := true;
if a_point.y > GB_MAX_Y then result := false;
if a_point.x > GB_MAX_X then result := false;
if a_point.y < 1 then result := false;
if a_point.x < 1 then result := false;
end;
constructor TGameBoard.Create;
var
i, x, y : integer;
begin
i := 1;
for y := 1 to GB_MAX_Y do
for x := 1 to GB_MAX_X do
begin
if i < GB_MAX_BUTTONS+1
then GameArray[x,y] := IntToStr(i)
else GameArray[x,y] := GB_EMPTY_PLACE;
inc(i);
end;
RandomArray;
end;
function TGameBoard.ButtonPlace(a_name: string): TPoint;
var
x,y:integer;
begin
result.x := 0;
result.y := 0;
for y := 1 to GB_MAX_Y do
for x := 1 to GB_MAX_X do
if GameArray[x,y] = a_name then
begin
result.x := x;
result.y := y;
end;
end;
function TGameBoard.CanMove(a_name: string): Boolean;
var
empty, point:TPoint;
begin
result := false;
empty := ButtonPlace( GB_EMPTY_PLACE );
point := ButtonPlace(a_name);
if (abs(empty.x-point.x)=1) and (empty.y=point.y) then result := true;
if (abs(empty.y-point.y)=1) and (empty.x=point.x) then result := true;
end;
function TGameBoard.Change(a_name: string): TPoint;
var
empty, point:TPoint;
begin
empty := ButtonPlace( GB_EMPTY_PLACE );
result := empty;
point := ButtonPlace(a_name);
GameArray[point.x, point.y] := GB_EMPTY_PLACE;
GameArray[empty.x, empty.y] := a_name;
end;
procedure TGameBoard.RandomArray;
var
j,i:integer;
name:string;
point,point2:TPoint;
begin
for i := 0 to 1000 do
begin
j := random(4);
point := ButtonPlace( GB_EMPTY_PLACE );
point2 := point;
case j of
0: point2.x := point.x-1;
1: point2.x := point.x+1;
2: point2.y := point.y-1;
3: point2.y := point.y+1;
end;
if ValidPoint( point2 ) then
begin
name := GameArray[point2.x, point2.y];
GameArray[point.x, point.y] := name;
GameArray[point2.x, point2.y] := GB_EMPTY_PLACE;
end;
end;
end;
destructor TGameBoard.Destroy;
begin
inherited Destroy;
end;
end.