Динамическое размещение кнопок в C Builder 6? - PullRequest
0 голосов
/ 06 января 2010

Я хочу сделать игру в TicTacToe. Когда я изменяю размер окна, я хочу, чтобы на интерфейсе появилось больше кнопок. От матрицы 3х3 до 4х4 и т. Д. До 9х9, в зависимости от того, насколько я изменяю размер окна. Как мне это сделать?

Я сделаю бесплатный дизайн сайта для тех, кто дает мне рабочий ответ (и что-то дополнительное для полной программы игры в tictactoe).

Спасибо!

1 Ответ

2 голосов
/ 07 января 2010

Что вы можете сделать, это установить максимальный размер, который должна иметь кнопка, а затем просто разделить размер контейнера, чтобы найти необходимое количество кнопок. С этой частью все просто, добавление кнопок на самом деле не проблема. Вы можете использовать свойство Tag для отслеживания положения кнопок в массиве крестики-нолики.

Я думаю, что, поскольку у вас есть максимальное количество кнопок, которое вы хотите, вы можете создать кнопки 9x9 с самого начала, просто установив для их свойства Visible значение false, отображая их по мере необходимости. Тогда процедура изменения размера должна изменить размер кнопок.

Я привел простой пример того, как создать кнопки в конструкторе формы, хотя учтите, что это чрезвычайно просто, но просто служит для иллюстрации моего вышеизложенного. Обратите внимание, что я использую одномерный массив вместо двухмерного, чтобы потом было легче найти победителя.

// Declare constants used for our tic tac toe example
const int minButtons = 3; // The minimum number of buttons in either direction
const int maxButtons = 9; // The maximum number of buttons in either direction
const int buttonDistance = 5; // The distance between the buttons
const int buttonSize = 50; // The targeted button size.

//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
 : TForm(Owner)
{
    // Create our buttons and set some tag value to identify them later.
    for (int i = 0; i < maxButtons; i++)
    {
        for (int j = 0; j < maxButtons; j++)
        {
            int idx = i * maxButtons + j;

            buttons[idx] = new TButton(this);
            buttons[idx]->Parent = this;

            // Assign the on click event (we define this later)
            buttons[idx]->OnClick = ButtonPressed;
        }
    }

    // Let the X player start
    currentPlayer = "X";
}

После создания кнопок вы можете контролировать их количество и размер в формах OnResize событие:

void __fastcall TForm1::FormResize(TObject *Sender)
{
    // Calculate the number of buttons to display.
    int btd = std::min(ClientWidth, ClientHeight) / buttonSize;

    // Make sure we have atleast minButtons and at most maxButtons buttons.
    btd = (btd < minButtons) ? minButtons : (btd > maxButtons) ? maxButtons : btd;

    // Write the tic tac toe board size in the form caption
    Caption = IntToStr(btd) + " x " + IntToStr(btd);

    // Calculate the new button size.
    int buttonWidth = (ClientWidth - (btd - 1) * buttonDistance) / btd;
    int buttonHeight = (ClientHeight - (btd - 1) * buttonDistance) / btd;

    // Show and position buttons
    for (int i = 0; i < maxButtons; i++)
    {
        for (int j = 0; j < maxButtons; j++)
        {
            int idx = i * maxButtons + j;

            if (i < btd && j < btd)
            {
                buttons[idx]->Visible = true;
                buttons[idx]->Width = buttonWidth;
                buttons[idx]->Height = buttonHeight;
                buttons[idx]->Left = i * buttonWidth + i * buttonDistance;
                buttons[idx]->Top = j * buttonHeight + j * buttonDistance;
            }
            else
            {
                buttons[idx]->Visible = false;
            }
        }
    }
}

Теперь нам нужен код для обработки ввода пользователя, то есть всякий раз, когда пользователь нажимает одну из наших кнопок, мы приводим параметр Sender к TButton, таким образом мы можем выполнить обработку щелчка в одной функции.

void __fastcall TForm1::ButtonPressed(TObject *Sender)
{
    TButton *btn = dynamic_cast<TButton*>(Sender);
    if (btn)
    {
        // Check if this button is free to be pressed
        if (btn->Enabled)
        {
            btn->Caption = currentPlayer;
            btn->Enabled = false;


            if (IsWinner())
                ShowMessage(currentPlayer + " is the winner :)");

            if (currentPlayer == "X") currentPlayer = "O";
            else currentPlayer = "X";
        }
    }
}

Наконец, мы добавляем простую функцию, чтобы проверить, является ли текущий игрок победителем, это, очевидно, можно сделать более умным и намного более оптимизированным, но это всего лишь простой пример, служащий источником вдохновения:

bool __fastcall TForm1::IsWinner()
{
    bool foundWinner;

    // Calculate the number of buttons to display.
    int btd = std::min(ClientWidth, ClientHeight) / buttonSize;

    // Make sure we have atleast minButtons and at most maxButtons buttons.
    btd = (btd < minButtons) ? minButtons : (btd > maxButtons) ? maxButtons : btd;

    // Check for a winner in the direction top to bottom
    for (int i = 0; i < btd; i++)
    {
        foundWinner = true;

        for (int j = 0; j < btd; j++)
        {
            if (buttons[i * maxButtons + j]->Caption != currentPlayer)
                foundWinner = false;
        }

        if (foundWinner) return true;
    }

    // Check for a winner in the direction left to right
    for (int j = 0; j < btd; j++)
    {
        foundWinner = true;

        for (int i = 0; i < btd; i++)
        {
            if (buttons[i * maxButtons + j]->Caption != currentPlayer)
                foundWinner = false;
        }

        if (foundWinner) return true;
    }

    // Check for a winner in the diagonal directions
    foundWinner = true;
    for (int i = 0; i < btd; i++)
    {
        if (buttons[i * maxButtons + i]->Caption != currentPlayer)
            foundWinner = false;
    }

    if (foundWinner) return true;

    foundWinner = true;
    for (int i = btd - 1; i >= 0; i--)
    {
        if (buttons[i * maxButtons + i]->Caption != currentPlayer)
            foundWinner = false;
    }

   return foundWinner;
}

Очевидно, что многое еще предстоит сделать, вся обработка выигравшего ( обновление просто добавила простую проверку ), создание интерфейса для запуска новой игры и т. Д. Кроме того, игра не Полностью защищенный от ошибок, в текущей версии игра добавляет дополнительные кнопки, когда вы изменяете размер даже после запуска игры, это, скорее всего, не то, что вам нужно, но исправить это просто вопрос добавления проверки в функцию изменения размера. В любом случае, я не собираюсь создавать для вас всю игру, я уверен, что вы захотите сделать это сами.

Если вы находите это полезным, вы можете использовать его, если нет, то, возможно, (и, скорее всего), вы можете быть вдохновлены моим подходом (который на самом деле является двухминутным решением). Надеюсь, это работает для вас. Бесплатный веб-дизайн не будет необходим, я думаю, вы можете сохранить это для дальнейшего вопроса;)

...