Python案例怎么实现随机洗牌?

wen python案例 52

本文目录导读:

Python案例怎么实现随机洗牌?

  1. 方法一:使用 random.shuffle(最简单)
  2. 方法二:实现 Fisher-Yates 洗牌算法
  3. 方法三:使用 random.sample
  4. 方法四:完整的扑克牌游戏案例
  5. 方法五:带验证的洗牌测试
  6. 方法六:加密安全的随机洗牌
  7. 推荐用法

我来介绍几种实现随机洗牌(Shuffle)的 Python 方法:

使用 random.shuffle(最简单)

import random
def shuffle_with_random(deck):
    """使用random.shuffle直接洗牌"""
    deck = deck.copy()  # 创建副本,避免修改原列表
    random.shuffle(deck)
    return deck
# 示例
cards = ['A', '2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K']
suits = ['♠', '♥', '♣', '♦']
# 创建一副完整的扑克牌
deck = [f'{card}{suit}' for suit in suits for card in cards]
print("原始牌序:", deck[:5])
shuffled_deck = shuffle_with_random(deck)
print("洗牌后:", shuffled_deck[:5])

实现 Fisher-Yates 洗牌算法

import random
def fisher_yates_shuffle(deck):
    """手动实现 Fisher-Yates 洗牌算法"""
    deck = deck.copy()
    n = len(deck)
    for i in range(n-1, 0, -1):
        # 从 0 到 i 中随机选择一个位置
        j = random.randint(0, i)
        # 交换位置 i 和 j 的元素
        deck[i], deck[j] = deck[j], deck[i]
    return deck
# 示例
deck = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
print("原始牌序:", deck)
print("Fisher-Yates洗牌:", fisher_yates_shuffle(deck))

使用 random.sample

import random
def shuffle_with_sample(deck):
    """使用random.sample实现洗牌"""
    return random.sample(deck, len(deck))
# 示例
deck = list(range(1, 53))  # 52张牌
shuffled = shuffle_with_sample(deck)
print("洗牌结果(前10张):", shuffled[:10])

完整的扑克牌游戏案例

import random
class PokerDeck:
    """扑克牌类"""
    def __init__(self):
        self.suits = ['♠', '♥', '♣', '♦']
        self.ranks = ['2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K', 'A']
        self.deck = []
        self.create_deck()
    def create_deck(self):
        """创建新牌堆"""
        self.deck = [f'{rank}{suit}' for suit in self.suits for rank in self.ranks]
    def shuffle(self):
        """洗牌"""
        random.shuffle(self.deck)
        print("牌已洗好!")
    def fisher_yates_shuffle(self):
        """使用Fisher-Yates算法洗牌"""
        n = len(self.deck)
        for i in range(n-1, 0, -1):
            j = random.randint(0, i)
            self.deck[i], self.deck[j] = self.deck[j], self.deck[i]
    def deal_card(self):
        """发一张牌"""
        if self.deck:
            return self.deck.pop()
        else:
            return None
    def deal_hand(self, num_cards):
        """发一手牌"""
        hand = []
        for _ in range(num_cards):
            card = self.deal_card()
            if card:
                hand.append(card)
        return hand
    def show_deck(self):
        """显示牌堆"""
        print(f"当前牌堆 ({len(self.deck)}张):")
        for i, card in enumerate(self.deck, 1):
            print(f"{card:4}", end=' ')
            if i % 13 == 0:
                print()
        print()
# 使用示例
print("=== 扑克牌洗牌演示 ===")
deck = PokerDeck()
print("创建新牌堆:")
deck.show_deck()
print("洗牌后:")
deck.shuffle()
deck.show_deck()
print("发5张牌:")
hand = deck.deal_hand(5)
print("手牌:", hand)
print(f"剩余牌数: {len(deck.deck)}")

带验证的洗牌测试

import random
from collections import Counter
def test_shuffle_quality():
    """测试洗牌质量"""
    original_deck = list(range(1, 53))
    def shuffle_test(shuffle_func, iterations=1000):
        """多次洗牌测试"""
        position_counts = Counter()
        for _ in range(iterations):
            deck = shuffle_func(original_deck.copy())
            # 记录每张牌第一次出现的位置
            for pos, card in enumerate(deck):
                if card == 1:  # 以第一张牌为例
                    position_counts[pos] += 1
                    break
        return position_counts
    # 使用random.shuffle测试
    pos_counts = shuffle_test(random.shuffle)
    print("洗牌1000次后,第一张牌出现在各位置的概率:")
    for pos in range(0, 52, 5):  # 每5个位置显示一次
        probability = pos_counts.get(pos, 0) / 1000
        print(f"位置 {pos:2d}: {probability:.2%}")
# 执行测试
test_shuffle_quality()

加密安全的随机洗牌

import secrets
import random
def cryptographically_secure_shuffle(deck):
    """使用secrets模块实现加密安全的洗牌"""
    deck = deck.copy()
    n = len(deck)
    for i in range(n-1, 0, -1):
        # secrets.randbelow 提供加密安全的随机数
        j = secrets.randbelow(i + 1)
        deck[i], deck[j] = deck[j], deck[i]
    return deck
# 适用于需要高安全性的场景
deck = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
secure_shuffled = cryptographically_secure_shuffle(deck)
print("加密安全洗牌:", secure_shuffled)

推荐用法

# 最常用、最简单的洗牌方法
import random
my_list = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
random.shuffle(my_list)  # 直接修改原列表
print(my_list)
# 或者创建新列表
my_list = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
new_list = random.sample(my_list, len(my_list))  # 返回新列表
print(new_list)

选择建议:

  • 日常使用random.shuffle() 最简单
  • 需要原列表不变random.sample()
  • 了解原理:Fisher-Yates 算法
  • 高安全性:使用 secrets 模块

抱歉,评论功能暂时关闭!