You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C# WinForm定时器翻牌问题:MessageBox重复弹出求助

解决WinForm翻牌游戏MessageBox重复弹出的问题

首先咱们来定位问题根源:你的Timer在游戏结束后没有停止,而且模态MessageBox会阻塞UI线程,导致Timer的Tick事件在后台排队。当用户关闭MessageBox后,这些排队的Tick事件会一次性执行,每次都会检测到所有卡牌已翻面,进而重复弹出对话框。

修复步骤

核心思路是:当检测到所有卡牌翻面时,先停止Timer,避免后续Tick事件触发;等用户确认并重置卡牌后,再重新启动Timer。

修改后的代码如下:

private void cardsChangingTimer_Tick(object sender, EventArgs e)
{
    int chosenImage = rnd.Next(1, 17);
    int chosenCard = rnd.Next(0, 4);

    if (bucketArr[chosenCard] == 0)
    {
        bucketArr[chosenCard]++;
        switch (chosenCard)
        {
            case 0:
                card1Pic.Image = Image.FromFile("cards\\" + chosenImage + ".png");
                break;
            case 1:
                card2Pic.Image = Image.FromFile("cards\\" + chosenImage + ".png");
                break;
            case 2:
                card3Pic.Image = Image.FromFile("cards\\" + chosenImage + ".png");
                break;
            case 3:
                card4Pic.Image = Image.FromFile("cards\\" + chosenImage + ".png");
                break;
        }
    }

    // 检查是否所有卡牌已翻面
    bool allCardsTurned = true;
    for (int i = 0; i < bucketArr.Length; i++)
    {
        if (bucketArr[i] == 0)
        {
            allCardsTurned = false;
            break;
        }
    }

    if (allCardsTurned)
    {
        // 先停止计时器,防止后续Tick事件触发
        cardsChangingTimer.Stop();

        DialogResult dialog = MessageBox.Show("All 4 cards were turned over...");
        if (dialog == DialogResult.OK)
        {
            // 重置所有卡牌为背面
            card1Pic.Image = Image.FromFile("..\\..\\17.png");
            card2Pic.Image = Image.FromFile("..\\..\\17.png");
            card3Pic.Image = Image.FromFile("..\\..\\17.png");
            card4Pic.Image = Image.FromFile("..\\..\\17.png");

            // 重置标记数组
            Array.Clear(bucketArr, 0, bucketArr.Length);
        }

        // 重新启动计时器,继续游戏
        cardsChangingTimer.Start();
    }
}

关键改进点

  1. 替换全局状态变量为局部判断:用局部变量allCardsTurned代替全局的gameEnded,避免全局变量状态混乱导致的逻辑错误。
  2. 停止Timer再弹出对话框:在弹出MessageBox前调用cardsChangingTimer.Stop(),彻底阻止后续Tick事件触发和排队,从根源上避免重复弹窗。
  3. 重置后重启Timer:用户确认并重置卡牌后,调用cardsChangingTimer.Start()恢复游戏流程。
  4. 简化数组重置:用Array.Clear()代替手动循环赋值,代码更简洁易维护。

这样修改后,就不会再出现MessageBox重复弹出的问题了——在用户处理对话框的过程中,Timer已经停止,不会有新的Tick事件干扰流程。

内容的提问来源于stack exchange,提问作者MasterSplinter

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 06:36:14