C# 等待用户在多个控件中单击一个控件
这个问题是从一堆其他人的同样的话开始的。。。我试着用c做一个纸牌游戏,我见过很多类似的问题,但是没有人真正解决我的问题 我将用一个小场景介绍我的问题: 玩家A与目标B玩牌X 玩家B需要选择一张牌Y或传球 玩家B视图包含他的牌,每张牌由a表示 图片盒 要继续游戏,我需要玩家B的控制器等待,直到他点击卡 属于Y型,或通过转弯 对我来说,最简单的方法就是用布尔值假装等待。很容易记录最后一张牌,例如X,然后等待该牌。在Y类型的牌上触发Click事件或按下pass按钮时,单击事件 问题是它需要使用大量布尔变量和if/else来处理这些事件 有什么更好的方法来实现这样的事情呢 编辑C# 等待用户在多个控件中单击一个控件,c#,winforms,async-await,C#,Winforms,Async Await,这个问题是从一堆其他人的同样的话开始的。。。我试着用c做一个纸牌游戏,我见过很多类似的问题,但是没有人真正解决我的问题 我将用一个小场景介绍我的问题: 玩家A与目标B玩牌X 玩家B需要选择一张牌Y或传球 玩家B视图包含他的牌,每张牌由a表示 图片盒 要继续游戏,我需要玩家B的控制器等待,直到他点击卡 属于Y型,或通过转弯 对我来说,最简单的方法就是用布尔值假装等待。很容易记录最后一张牌,例如X,然后等待该牌。在Y类型的牌上触发Click事件或按下pass按钮时,单击事件 问题是它需要使用大量布尔
一般来说,这些问题都是通过创建一个状态机来解决的,即知道游戏处于什么状态的东西,以及根据这个状态如何处理下一个输入。有几种方法可以对状态机进行编程,但其中一种方法是使用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;
}
当用户需要遵循某个操作序列时,此方法特别好,因为它可以让您以相当简单的方式编写代码。也许您可以向CardClass添加一个存储枚举值的变量。如果已单击某张卡,则可以使用switchcase禁用与单击类型不匹配的卡。。。这只是一个想法。。。也许你可以在文章中添加一些代码或GUI的屏幕截图,这将非常有用async/await关键字用于异步编程。在这里,您没有尝试异步运行IO或CPU绑定的代码。您正在尝试确定玩家何时执行了某个动作、玩了一张牌或通过了某个动作。玩家B打牌/传球的动作应该调用一个方法或调用一个事件,将控制权传递回玩家a。根据您提供的信息,不需要等待任何事情。这实际上很好,我必须稍微更改代码以强制使用Task,否则我无法获得结果。我仍然需要相当多的控件来执行,但代码要简单得多。谢谢
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));
}
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;
}
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()});
}
}