Windows Forms卡牌应用随机数生成引发死锁问题求助
卡牌随机分配程序问题修复
问题概述
需要实现一副牌(1-54)的随机分配:生成全部不重复随机数,7个分配给用户按钮、7个给电脑,剩余存入队列。当前程序启动后界面冻结60秒,随后抛出错误:
托管调试助手“ContextSwitchDeadlock”:“CLR 无法在60秒内从COM上下文0xa73c68切换到COM上下文0xa73bb0。”
核心错误原因
- 随机数生成逻辑死循环:
GenerateRandomNumber方法的去重逻辑完全错误,无法生成足够数量的不重复随机数,导致循环永远无法结束,占用UI线程引发死锁。 - 图片路径获取方式错误:通过
String.Join拼接栈元素为字符串后截取的方式,会错误获取数字的字符片段(而非完整卡牌编号),导致图片加载失败。 - 文件后缀不匹配:卡牌文件后缀为
.jpg,但代码中使用.png,会导致图片加载异常。
修复后的完整代码
1. 窗体构造与初始化
public FmClassic() { InitializeComponent(); // 初始化卡牌分配 InitializeCardDistribution(); }
2. 卡牌分配核心方法
private List<int> _shuffledCards; private Queue<int> _remainingCards; private List<int> _userCards; private List<int> _computerCards; private void InitializeCardDistribution() { // 生成1-54的完整卡牌列表 _shuffledCards = Enumerable.Range(1, 54).ToList(); // 洗牌(Fisher-Yates算法,高效无重复) ShuffleCards(_shuffledCards); // 分配用户7张牌 _userCards = _shuffledCards.Take(7).ToList(); // 分配电脑7张牌 _computerCards = _shuffledCards.Skip(7).Take(7).ToList(); // 剩余卡牌存入队列 _remainingCards = new Queue<int>(_shuffledCards.Skip(14)); // 设置用户按钮图片 SetUserButtonImages(); } // Fisher-Yates洗牌算法 private void ShuffleCards(List<int> cards) { Random random = new Random(); int n = cards.Count; while (n > 1) { n--; int k = random.Next(n + 1); (cards[k], cards[n]) = (cards[n], cards[k]); } }
3. 设置用户按钮图片
private void SetUserButtonImages() { string cardPath = @"C:\filepath\"; // 确保路径正确 button1.Image = Image.FromFile($"{cardPath}{_userCards[0]}.jpg"); button2.Image = Image.FromFile($"{cardPath}{_userCards[1]}.jpg"); button3.Image = Image.FromFile($"{cardPath}{_userCards[2]}.jpg"); button4.Image = Image.FromFile($"{cardPath}{_userCards[3]}.jpg"); button5.Image = Image.FromFile($"{cardPath}{_userCards[4]}.jpg"); button6.Image = Image.FromFile($"{cardPath}{_userCards[5]}.jpg"); button7.Image = Image.FromFile($"{cardPath}{_userCards[6]}.jpg"); }
关键改进点
- 使用Fisher-Yates洗牌算法生成无重复的随机卡牌序列,避免死循环,效率更高。
- 直接通过列表索引获取卡牌编号,避免字符串拼接截取的错误。
- 分离卡牌分配与UI设置逻辑,代码结构更清晰。
- 修正图片后缀为
.jpg,匹配实际文件格式。
内容的提问来源于stack exchange,提问作者contingiouscrayon
相关产品推荐
相关产品推荐

