13.2 洗牌
大多数扑克牌游戏需要提供洗牌功能,即将牌随机地排列。8.7 节介绍了如何生成随机数,但如何用随机数来洗牌并不那么简单。
一种选择是模拟人工洗牌的方式:通常将整副牌分成两半,再交替地从这两半中取牌。因为人工洗牌通常不能洗得很乱,所以需要重复大约 7 次才能让整副牌的排列顺序相当随机。
但计算机程序有个令人讨厌的特征,就是每次洗牌都能洗得很乱,但不是完全随机的。实际上,程序连续洗 8 次后,牌就会恢复到原来的顺序!有关这方面的更详细信息,请参阅 https://en.wikipedia.org/wiki/Faro_shuffle。
一种更佳的洗牌算法是遍历整副牌——每次一张,并在每次迭代中交换两张牌的位置。这种算法的工作原理大致如下。为了大致地描绘程序,我们结合使用了 Java 语句和自然语言,这种组合被称为伪代码(pseudocode):
for each index i {// 在i和length - 1之间随机地选择一个数字// 将第i张牌和随机选择的那张牌的位置互换}
伪代码的优点在于,让你能够清楚地知道需要哪些方法。从上述伪代码可知,你需要两个方法:一个方法要在 low 和 high 之间随机地选择一个数字,另一个方法要接受两个索引并交换这两个索引处的扑克牌。这样的方法被称为辅助方法(helper method),因为它们用于帮助实现更复杂的算法。
这种先编写伪代码,再编写所需方法的过程被称为自上而下的开发(top-down development),更详细的信息请参阅 https://en.wikipedia.org/wiki/Top-down_and_bottom-up_design。
本章末尾有一个练习,要求你编写辅助方法 randomInt 和 swapCards,并用它们实现 shuffle。
