15-puzzle/fi

From Free Pascal wiki
Jump to navigationJump to search

English (en) suomi (fi) français (fr)

15-peli

puzzle15.png

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 rungon procedure 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.

Katso myös