Link to home
Start Free TrialLog in
Avatar of Mark Brady
Mark BradyFlag for United States of America

asked on

Image click to return the name and position of that image ?

I have a panel with 16 small images 50 * 50.  They are 4 wide and 4 deep.
The last image has no picture (blank).  Images are named Image1 through to Image15 and the last one is named 'Imblank'.

I want to create a puzzel that when you click on an image next to the blanl one, the image and blank slide places.  Just like the number squares game (only I'm using a picture all diced up).

The GUI is all set up but the coding for this one I'm having difficulty with.

If you can't help with an idea, then can you tell me how to get the Image name returned to a variable once an image is clicked and to work out if the blank image is next to it and able to be moved there ?

Thanks

Mark
Avatar of Igor UL7AAjr
Igor UL7AAjr
Flag of Kazakhstan image

Hi Elvin,

I know the game you mean. Just an idea.
You have to create an array[0..3, 0..3] of integers and keep you data here.
Also you have create some visualization for array. I recommend you to use TDrawGrid.

It would be easy to implement.

____
Igor
here is a whole code of puzzle.

DG - TDrawGrid 4 x 4
Image1 - source image for puzzle, it will be splitted by 16 parts


Do not forget to assign an events :)

-----
Igor


unit u78;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, Grids, ExtCtrls;

type
  TData16 = array[0..3, 0.. 3] of Integer;
  TImg16 = array[0..15] of TBitmap;

  TForm1 = class(TForm)
    DG: TDrawGrid;
    Image1: TImage;
    procedure FormCreate(Sender: TObject);
    procedure DGDrawCell(Sender: TObject; ACol, ARow: Integer; Rect: TRect;
      State: TGridDrawState);
    procedure DGClick(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
  private
    { Private declarations }
  public
    Data: TData16;
    Imgs: TImg16;
    procedure PrepareImgs;
    procedure DoneImgs;
    procedure SetNewData;
    procedure ShowData;
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}


procedure TForm1.SetNewData;
var
  I, J, N: Integer;
  L: TList;
begin
  Randomize;
  L := TList.Create;
  for I := 0 to 15 do
    L.Add(Pointer(I));

  for I := 0 to 3 do
    for J := 0 to 3 do
    begin
      N := Random(L.Count);
      Data[I, J] := Integer(L[N]);
      L.Delete(N);
    end;

  L.Free;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  PrepareImgs;
  SetNewData;
  DG.Invalidate;
end;

procedure TForm1.ShowData;
begin
end;

procedure TForm1.DGDrawCell(Sender: TObject; ACol, ARow: Integer;
  Rect: TRect; State: TGridDrawState);
begin
  if Data[ACol, ARow] = 0 then
    DG.Canvas.FillRect(Rect)
  else
    DG.Canvas.StretchDraw(Rect, Imgs[Data[ACol, ARow]]);
end;

procedure TForm1.DGClick(Sender: TObject);
var
  X, Y: Integer;

  procedure Move(AX, AY: Integer);
  begin
    Data[AX, AY] := Data[X, Y];
    Data[X, Y] := 0;
  end;

begin
  X := DG.Col;
  Y := DG.Row;

  if (X > 0) and (Data[X - 1, Y] = 0) then Move(X - 1, Y) else
  if (X < 3) and (Data[X + 1, Y] = 0) then Move(X + 1, Y) else
  if (Y > 0) and (Data[X, Y - 1] = 0) then Move(X, Y - 1) else
  if (Y < 3) and (Data[X, Y + 1] = 0) then Move(X, Y + 1) else
    Beep;
  DG.Invalidate;
end;

procedure TForm1.PrepareImgs;
var
  X, Y: Integer;
  W, H: Integer;
  I: Integer;
  B: TBitmap;
  RS, RD: TRect;
begin
  B := Image1.Picture.Bitmap;
  W := B.Width div 4;
  H := B.Height div 4;
  SetRect(RD, 0, 0, W, H);
  for X := 0 to 3 do
    for Y := 0 to 3 do
    begin
      SetRect(RS, W * X, H * Y, W * X + W, H * Y + H);
      I := 15 - (X + Y * 4);
      Imgs[I] := TBitmap.Create;
      Imgs[I].Width := W;
      Imgs[I].Height := H;
      Imgs[I].Canvas.CopyRect(RD, B.Canvas, RS);
    end;
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  DoneImgs;
end;

procedure TForm1.DoneImgs;
var
  I: Integer;
begin
  for I := 0 to 15 do
    Imgs[I].Free;
end;

end.
Avatar of Mark Brady

ASKER

Hi ugay

Hey that looks real interesting.  It's a little over my head but I'd love to give it a try.  Can you tell me what I'd need on my form to make this work ?  Do I start with a blank project and paste this code into it ??  Buttons ?
Sorry, but I just don't know where to start.  Any more help would be very good.

thanks
Mark
Yes, you can start from empty form

1. drop TDrawGrid and set it's property:
  Name = DG
  ColCount = 4
  RowCount = 4
  FixedRows = 0
  FixedCols = 0
  DefaultColWidth = your choice
  DefaultRowHeight = your choice

2.  Drop TImage and load any bitmap you want
 

3. Insert type definition

 TData16 = array[0..3, 0.. 3] of Integer;
 TImg16 = array[0..15] of TBitmap;

4. write procedures and implementations for TForm (you can copy and paste my code)

  public
    Data: TData16;
    Imgs: TImg16;
    procedure PrepareImgs;
    procedure DoneImgs;
    procedure SetNewData;
    procedure ShowData;
  end;


5. Create an events and place the same code as in sample here

    procedure FormCreate(Sender: TObject);
    procedure DGDrawCell(Sender: TObject; ACol, ARow: Integer; Rect: TRect;
      State: TGridDrawState);
    procedure DGClick(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
 

Thats all.
Let me know if you still have a troubles.

____
Igor

I tried all that but I have a few problems.  It can't find
'Variants.dcu'.  Then I get a bunch of 'undeclared identifier' errors even though those things are on my form.

Any chance you could compile a quick example and send me the exe and the project files for me to study ?

If so, please send to elvin66@xtra.co.nz

Many thanks for your time.

Mark
hi Mark,

did you try to remove Variants from uses clause?

-----
Igor
yes I did.  That solved that problem but still I get a lot of other errors.  It might be easier for me to study and customise If I could see a complete project file(s) and see how it runs.  If you don't want to send it, then can you be more clear on how to set it up ?  Like, with image1, do I place that next to the drawgrid or over top of it or what ?  
Mark
Also, thius creates an error.

type
 TData16 = array[0..3, 0.. 3] of Integer;
error = ': expected but = found'  however I modify that line it doesn't work. Hmmm

Mark
Hi elvin66
I can post whole project to you,
but seems we are using different Delphi versions,
I have D6 source only. Not sure in backward compatibility.
Ok, I will try to send you only .DFM and .PAS files.
------
Igor
ASKER CERTIFIED SOLUTION
Avatar of Igor UL7AAjr
Igor UL7AAjr
Flag of Kazakhstan image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
that would be great.  I'll check my email.  I'm using delphi 5
That works perfectly !  Never mind the email, I got it working and changed the bitmap to the picture I want to use.  Now I will go and put a button on the form that lets user load different images.  Thank you so much !

Mark