结构体与指针场景下用temp变量洗牌52张卡牌数组出现重复缺失问题
问题原因分析
- 最核心的错误:你声明的
Card* temp = deck.Cards;只是创建了一个指向原扑克牌数组的指针,并没有拷贝原数组的内容。temp和deck.Cards指向完全相同的内存地址,修改deck.Cards中任意位置的值,temp对应下标的值也会同步变化。 - 交换逻辑完全失效:你写的两行代码
deck.Cards[i] = deck.Cards[randomIndex]; deck.Cards[randomIndex] = temp[i];
因为temp[i]本质就是deck.Cards[i],等价于你先把i位置的值覆盖为randomIndex位置的值,再把randomIndex位置的值赋值为已经覆盖后的i位置的值。两次操作后i和randomIndex位置的值都等于原randomIndex位置的值,原i位置的值直接丢失,循环多次后自然会出现大量值重复、缺失的问题。
修复方案
- 最简修复:交换两个值只需要临时存储单个元素即可,不需要额外备份整个数组,修改后逻辑如下:
for (int i = 0; i < 52; i++) { int randomIndex = rand() % 52; // 临时存储当前i位置的原始值 Card tempCard = deck.Cards[i]; deck.Cards[i] = deck.Cards[randomIndex]; deck.Cards[randomIndex] = tempCard; }
- 优化建议:上述写法的排列概率并不均匀,如果需要更公平的洗牌结果,推荐使用标准Fisher-Yates洗牌算法:
// 从后往前遍历,随机下标范围控制在0~i,保证所有排列出现概率相等 for (int i = 51; i > 0; i--) { int randomIndex = rand() % (i + 1); Card tempCard = deck.Cards[i]; deck.Cards[i] = deck.Cards[randomIndex]; deck.Cards[randomIndex] = tempCard; }
内容的提问来源于stack exchange,提问作者tg8
相关产品推荐
相关产品推荐

