Ожидайте, чтобы пользователь щелкнул один элемент управления в нескольких элементах управления. - PullRequest
0 голосов
/ 31 марта 2020

Этот вопрос начинается с тех же слов, что и кучка других ... "Я пытаюсь сделать карточную игру в c#", я видел много похожих вопросов, но на самом деле никто не решает моя проблема.

Я представлю свою проблему с небольшим сценарием:

Игрок A разыгрывает карту X с целью B

Игроку B необходимо выбрать контркарту Y или pass

Вид игрока B содержит его карты, и каждая карта представлена ​​графическим блоком.

Чтобы продолжить игру, мне нужно, чтобы контроллер игрока B ждал, пока он не нажмет на карту типа Y, или чтобы пройти терн.

Для меня самый простой способ сделать что-то вроде этого - это подделка с использованием логических значений. Легко записать, какая карта была последней сыгранной (например, X), а затем подождать, пока событие не будет активировано. Нажатие на карточку типа Y или нажатие кнопки «Пасс».

Проблема в том, что что он требует использования большого количества логических переменных и если / еще для обработки этих «событий».

Что было бы лучше для реализации чего-то подобного?

Edit.

GameController.cs

public void XCardPlayed(string target)
{
    if (this.players[0].Username.Equals(target))
    {
        // I'm the target
        lastCardPlayed = "X";
        PlayYCard();
    } 
    else
    {
        // display the card on the table
    }
}

public void PlayYCard()
{
    gameView.NotifyPlayYCard();
}

GameForm.cs

public void PlayCardFromHand(int index)
{
    if (playY)
    {
       // Check if card at index is instance of Y
    }
}

public void NotifyPlayYCard()
{
    playY = true;
}

public void CardClick(object sender, EventArgs e)
{
    PictureBox current = (PictureBox)sender;
    PlayCardFromHand(pnl_cards.Controls.IndexOf(current));
}

1 Ответ

3 голосов
/ 31 марта 2020

Как правило, такие проблемы решаются путем создания машины состояний, то есть того, что знает, в каком состоянии находится игра, и в зависимости от этого состояния обрабатывает следующий ввод. Существует несколько способов программирования конечных автоматов, но один из них - использовать async / await, чтобы компилятор мог это сделать.

Вы можете заключить кнопку в классе, который выполняет задачу при каждом нажатии кнопки:

public class ButtonAwaiter
{
    private readonly Button button;
    private TaskCompletionSource<bool> tcs = new TaskCompletionSource<bool>();
    public ButtonAwaiter(Button button)
    {
        this.button = button;
        this.button.Click += OnClick;
    }

    private void OnClick(object sender, EventArgs e)
    {
        tcs.SetResult(true);
        tcs  = new TaskCompletionSource<bool>();
    }

    public Task GetTask() => tcs.Task;
}

Замените 'bool' на то, что представляет кнопка.

И ждите, когда первая из кнопок нажата, как:

    public async Task DoGameLoop()
    {
        var b1 = new ButtonAwaiter(button1);
        var b2 = new ButtonAwaiter(button2);
        while (GameIsInProgress)
        {
            var pressed = await Task.WhenAny(new[] {b1.GetTask(), b2.GetTask()});
        }
    }

Этот метод особенно приятно, когда пользователю нужно выполнить некоторую последовательность действий, поскольку он позволяет писать код достаточно простым способом.

...