Search code examples
arraysdelphiminesweeper

How can I check if any button of a two dimensional array was clicked?


I am trying to build a minesweeper program. So far, I made a two-dimensional array of buttons with the variable Buttons[rows][cols], so you can target every button on the field. The buttons are created on the form at runtime. Now I need to know how I can determine whether a button was clicked.

I know you can check if Sender = Button but how does it work with two-dimensional arrays? And since I created the Buttons at runtime (FormCreate), how do I create the procedure in which the code can be executed, because it certainly shouldn't check if a button was clicked at runtime.

Would anyone be so kind and show me how I can disable a button after it was clicked? For this, obviously, I need to know how to determine which button was clicked.


Solution

  • When you create the buttons, set their Tag property to an ID:

    Button.Tag := Col + Row*ColCount;
    

    Give each button the same OnClick event handler.

    Button.OnClick := ButtonClick;
    

    These two lines of code will be inside a loop like this:

    for Row := 0 to RowCount-1 do
      for Col := 0 to ColCount-1 do
      begin
        Button := TButton.Create(Self);
        Button.Parent := Self;
        Button.Left := ...;
        Button.Top := ...;
        Button.Tag := ...;
        Button.OnClick := ...;
        Buttons[Row,Col] := Button;
      end;
    

    I expect you already have code like this.

    Implement the event handler to decode the ID like this:

    procedure TMyForm.ButtonClick(Sender: TObject);
    var
      Button: TButton;
      Row, Col: Integer;
    begin
      Button := Sender as TButton;
      Row := Button.Tag div ColCount;
      Col := Button.Tag mod ColCount;
      // respond to click
    end;
    

    Disable a control by setting its Enabled property to False.

    Here I've assumed zero based indexing, and that your buttons are TButton. If these assumptions are wrong, you'll clearly need to adapt to your scenario.

    I think this answers the question you asked. However, using a button for each grid square is probably the wrong way to implement Minesweeper. You would be better off with a TPaintBox, a non-visual structure to hold the state, and a single OnClick handler for the paint box.