-1

This question starts with the same words of a bunch of others... "I'm trying to do a card game in c#", i've seen a lot of similar questions, but no one is actually solving my problem.

I'll introduce my problem with a little scenario:

Player A plays card X with target B

Player B needs to choose a countercard Y or pass

Player B view contains his cards and each card is represented by a picturebox.

To continue the game i need the controller of player B to await until he clicks on card of type Y, or to pass the turn.

To me, the easiest way to do something like this is faking await using booleans. It's easy to record which was the last card played (E.g X) and then wait until the card.Click event is triggered on a card of type Y or if the pass button is pressed.

The problem with that is that it requires the use of a large number of boolean variables and if/else to handle those "events".

What would be a better implementation of something like this?

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));
}
  • Maybe you could add a variable storing an enum value to your CardClass. Ones a card has been clicked, you can use switchcase to disable the cards that don't match with the clicked type... Is just an idea... Maybe you could add some code to your post or a screenshot of your GUI, that would be really helpful – Adrian Efford Mar 31 '20 at 13:06
  • 1
    The `async`/`await` keywords are for asynchronous programming. You're not trying to run IO or CPU-bound code asynchronously here. You're trying to determine when the player has performed a certain action (played a card or passed). Player B's action (playing a card/passing) should invoke a method or call an event that passes control back to Player A. There is no need to `await` anything given the information you provided. – Patrick Tucci Mar 31 '20 at 13:30

1 Answers1

3

In general these kinds of problems are solved by creating a statemachine, I.e. something that know what state the game is in, and depending on this state, how to handle the next input. There are several ways to program state machines, but one way is to use async/await to let the compiler do it.

You can wrap a button in a class that completes a task each time the button is pressed:

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;
}

Substitute 'bool' for whatever the button represents.

And await when the first of the buttons is pressed like:

    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()});
        }
    }

This method is especially nice when the user needs to follow some sequence of actions since it lets you write the code in a reasonably straightforward manner.

JonasH
  • 28,608
  • 2
  • 10
  • 23
  • This is actually pretty nice, i had to slightly change the code to force the use of Task otherwise i wasn't able to get results. I still need quite plenty of controls to do, but the code is way more straightforward. Thanks! – scorpion2k40 Mar 31 '20 at 14:57