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(); } }
关键改进点
- 替换全局状态变量为局部判断:用局部变量
allCardsTurned代替全局的gameEnded,避免全局变量状态混乱导致的逻辑错误。 - 停止Timer再弹出对话框:在弹出MessageBox前调用
cardsChangingTimer.Stop(),彻底阻止后续Tick事件触发和排队,从根源上避免重复弹窗。 - 重置后重启Timer:用户确认并重置卡牌后,调用
cardsChangingTimer.Start()恢复游戏流程。 - 简化数组重置:用
Array.Clear()代替手动循环赋值,代码更简洁易维护。
这样修改后,就不会再出现MessageBox重复弹出的问题了——在用户处理对话框的过程中,Timer已经停止,不会有新的Tick事件干扰流程。
内容的提问来源于stack exchange,提问作者MasterSplinter
相关产品推荐
相关产品推荐

