吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 3622|回复: 58
收起左侧

[Python 转载] 【转载】Python实现春晚刘谦魔术

  [复制链接]
十万菠萝拍黄瓜 发表于 2024-2-11 09:58
以下内容为转载,感觉挺好玩的,分享一下~

一、导入库
[Python] 纯文本查看 复制代码
import random
from collections import deque


二、跟着刘谦步骤写程序


1、打乱13张牌
用一个 cards 列表存放 13 张不一样的牌 ["2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K", "A"]
使用random.shuffle() 函数,将列表中的元素随机打乱。这个函数会直接修改原始列表,而不是创建一个新的打乱顺序的列表。
[Python] 纯文本查看 复制代码
cards = ["2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K", "A"]
print(f"最初的的13张牌:{cards}")
random.shuffle(cards)
print(f"打乱顺序的13张牌:{cards}")


控制台中输出如下:
1.png

2、随机抽取4张牌
使用random.sample()函数,从列表中随机抽取指定数量的元素。这个函数不会修改原始序列,而是返回一个新的包含抽取元素的列表。
[Python] 纯文本查看 复制代码
# 随机选择4张牌
random_4_cards = random.sample(cards, 4)
print(f"随机抽出的4张牌:{random_4_cards}")


控制台输出如下:
2.png

3、将牌对折后撕开
创建了一个名为 random_8_cards 的双端队列,其中包含 random_4_cards 的 2 倍元素。

[Python] 纯文本查看 复制代码
# 对折后撕开得到8张牌
random_8_cards = deque(random_4_cards * 2)
print(f"对折后撕开得到8张牌:{random_8_cards}")


控制台输出如下:
3.png

4、根据名字字数得到新顺序牌
使用 collections.deque 类中的rotate() 方法,将双端队列中的元素向左或向右旋转指定的位置。这个方法接受一个参数,表示要旋转的位置数。正数表示向右旋转,负数表示向左旋转。
[Python] 纯文本查看 复制代码
# 1. 根据名字有几个字,将前几张牌移到最后
name = int(input("请输入名字字数:"))
# 将双端队列中的元素向左旋转几个位置
random_8_cards.rotate(-name)
print(f"根据名字字数调整后的牌:{random_8_cards}")


控制台输出如下:
4.png

5、最上面3张插入剩下牌中间
[Python] 纯文本查看 复制代码
# 2. 取出前三张牌并随机插入剩余牌中,不能插在第一张和最后一张
first_three = [random_8_cards.popleft() for i in range(3)]
print(f"上面3张牌是:{first_three}")
print(f"下面5张牌是:{random_8_cards}")

for card in first_three:
    insert_position = random.randint(1, len(random_8_cards) - 2)
    random_8_cards.insert(insert_position, card)
    print(f"插入牌是:{card},随机插入位置是:{insert_position+1},新牌顺序是{random_8_cards}")
print(f"上面3张牌随机插入剩下牌中间,此时新牌顺序:{random_8_cards}")


控制台输出如下:
5.png

6、最上面1张牌藏起来
[Python] 纯文本查看 复制代码
# 3. 把最上面的牌藏起来
remembered_card = random_8_cards.popleft()
print(f"藏起来的1张牌是:{remembered_card}")
print(f"剩下7张牌是:{random_8_cards}")


控制台输出如下:
6.png

7、根据南北方得到新顺序牌
[Python] 纯文本查看 复制代码
# 4. 南方人取1张,北方人取2张,无法确定取3张,将这些牌随机插入剩下的牌中
location = int(input("请输入地区,南方人输入1,北方人输入2,无法确定输入3:"))
first_location = [random_8_cards.popleft() for i in range(location)]
print(f"上面地区牌是:{first_location}")
print(f"剩下牌是:{random_8_cards}")

for card in first_location:
    insert_position = random.randint(1, len(random_8_cards) - 2)
    random_8_cards.insert(insert_position, card)
    print(f"插入牌是:{card},随机插入位置是:{insert_position + 1},新牌顺序是{random_8_cards}")
print(f"根据南北方,随机插入剩下牌中间,此时新牌顺序:{random_8_cards}")


控制台输出如下:
7.png

8、根据性别得到新顺序牌
[Python] 纯文本查看 复制代码
# 5. 男生取1张,女生取2张,将这些牌扔掉
gender = int(input("请输入性别,男性输入1,女性输入2:"))
for i in range(gender):
    random_8_cards.popleft()
print(f"根据性别扔牌,此时新牌顺序:{random_8_cards}")


控制台输出如下:
8.png

9、见证奇迹的时刻
"见证奇迹的时刻"是 7 个字,翻译成代码就是将双端队列中的元素向左旋转 7 个位置。
[Python] 纯文本查看 复制代码
# 6. 见证奇迹的时刻
# 将双端队列中的元素向左旋转7个位置
random_8_cards.rotate(-7)
print(f"见证奇迹的时刻(向左旋转7次牌),此时新牌顺序:{random_8_cards}")


控制台输出如下:
9.png

10、好运留下来,烦恼丢出去
[Python] 纯文本查看 复制代码
# 7. 好运留下来,烦恼丢出去!
while len(random_8_cards) > 1:
    random_8_cards.append(random_8_cards.popleft())  # 第一张牌移到最后
    random_8_cards.popleft()  # 删除现在的第一张牌
    print(f"好运留下来,烦恼丢出去!(第一张牌移到最后,删除现在的第一张牌)此时剩余牌顺序:{random_8_cards}")
print(f"剩余最后1张牌是:{random_8_cards}")


控制台输出如下:
10.png

三、完整代码
完整的代码程序如下:
[Python] 纯文本查看 复制代码
import random
from collections import deque

cards = ["2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K", "A"]
print(f"最初的的13张牌:{cards}")
random.shuffle(cards)
print(f"打乱顺序的13张牌:{cards}")

# 随机选择4张牌
random_4_cards = random.sample(cards, 4)
print(f"随机抽出的4张牌:{random_4_cards}")
# 对折后撕开得到8张牌
random_8_cards = deque(random_4_cards * 2)
print(f"对折后撕开得到8张牌:{random_8_cards}")

# 1. 根据名字有几个字,将前几张牌移到最后
name = int(input("请输入名字字数:"))
# 将双端队列中的元素向左旋转几个位置
random_8_cards.rotate(-name)
print(f"根据名字字数调整后的牌:{random_8_cards}")

# 2. 取出前三张牌并随机插入剩余牌中,不能插在第一张和最后一张
first_three = [random_8_cards.popleft() for _ in range(3)]
print(f"上面3张牌是:{first_three}")
print(f"下面5张牌是:{random_8_cards}")

for card in first_three:
    insert_position = random.randint(1, len(random_8_cards) - 2)
    random_8_cards.insert(insert_position, card)
    print(f"插入牌是:{card},随机插入位置是:{insert_position + 1},新牌顺序是{random_8_cards}")
print(f"上面3张牌随机插入剩下牌中间,此时新牌顺序:{random_8_cards}")

# 3. 把最上面的牌藏起来
remembered_card = random_8_cards.popleft()
print(f"藏起来的1张牌是:{remembered_card}")
print(f"剩下7张牌是:{random_8_cards}")

# 4. 南方人取1张,北方人取2张,无法确定取3张,将这些牌随机插入剩下的牌中
location = int(input("请输入地区,南方人输入1,北方人输入2,无法确定输入3:"))
first_location = [random_8_cards.popleft() for i in range(location)]
print(f"上面地区牌是:{first_location}")
print(f"剩下牌是:{random_8_cards}")

for card in first_location:
    insert_position = random.randint(1, len(random_8_cards) - 2)
    random_8_cards.insert(insert_position, card)
    print(f"插入牌是:{card},随机插入位置是:{insert_position + 1},新牌顺序是{random_8_cards}")
print(f"根据南北方,随机插入剩下牌中间,此时新牌顺序:{random_8_cards}")

# 5. 男生取1张,女生取2张,将这些牌扔掉
gender = int(input("请输入性别,男性输入1,女性输入2:"))
for i in range(gender):
    random_8_cards.popleft()
print(f"根据性别扔牌,此时新牌顺序:{random_8_cards}")

# 6. 见证奇迹的时刻
# 将双端队列中的元素向左旋转7个位置
random_8_cards.rotate(-7)
print(f"见证奇迹的时刻(向左旋转7次牌),此时新牌顺序:{random_8_cards}")

# 7. 好运留下来,烦恼丢出去!
while len(random_8_cards) > 1:
    random_8_cards.append(random_8_cards.popleft())  # 第一张牌移到最后
    random_8_cards.popleft()  # 删除现在的第一张牌
    print(f"好运留下来,烦恼丢出去!(第一张牌移到最后,删除现在的第一张牌)此时剩余牌顺序:{random_8_cards}")
print(f"剩余最后1张牌是:{random_8_cards}")

# 8. 查看藏起来的1张牌
print(f"藏起来的1张牌是:{remembered_card}")


控制台输出如下:
11.png

四、封装函数
我们将上面的代码进行封装,定义一个 magic() 函数,把名字字数定义为随机 1-10 的数字,南北方人为随机 1-3 的数字,性别为随机 1-2 的数字。
在 main 主函数内调用 10 万次 magic()函数,看一下运行结果正确率。
[Python] 纯文本查看 复制代码
import random
from collections import deque


def magic():
    cards = ["2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K", "A"]
    # print(f"最初的的13张牌:{cards}")
    random.shuffle(cards)
    # print(f"打乱顺序的13张牌:{cards}")

    # 随机选择4张牌
    random_4_cards = random.sample(cards, 4)
    # print(f"随机抽出的4张牌:{random_4_cards}")
    # 对折后撕开得到8张牌
    random_8_cards = deque(random_4_cards * 2)
    # print(f"对折后撕开得到8张牌:{random_8_cards}")

    # 1. 根据名字有几个字,将前几张牌移到最后
    name = int(random.randint(1, 10))
    # 将双端队列中的元素向左旋转几个位置
    random_8_cards.rotate(-name)
    # print(f"根据名字字数调整后的牌:{random_8_cards}")

    # 2. 取出前三张牌并随机插入剩余牌中,不能插在第一张和最后一张
    first_three = [random_8_cards.popleft() for _ in range(3)]
    # print(f"上面3张牌是:{first_three}")
    # print(f"下面5张牌是:{random_8_cards}")

    for card in first_three:
        insert_position = random.randint(1, len(random_8_cards) - 2)
        random_8_cards.insert(insert_position, card)
    #     print(f"插入牌是:{card},随机插入位置是:{insert_position + 1},新牌顺序是{random_8_cards}")
    # print(f"上面3张牌随机插入剩下牌中间,此时新牌顺序:{random_8_cards}")

    # 3. 把最上面的牌藏起来
    remembered_card = random_8_cards.popleft()
    # print(f"藏起来的1张牌是:{remembered_card}")
    # print(f"剩下7张牌是:{random_8_cards}")

    # 4. 南方人取1张,北方人取2张,无法确定取3张,将这些牌随机插入剩下的牌中
    location = int(random.randint(1, 4))
    first_location = [random_8_cards.popleft() for i in range(location)]
    # print(f"上面地区牌是:{first_location}")
    # print(f"剩下牌是:{random_8_cards}")

    for card in first_location:
        insert_position = random.randint(1, len(random_8_cards) - 2)
        random_8_cards.insert(insert_position, card)
    #     print(f"插入牌是:{card},随机插入位置是:{insert_position + 1},新牌顺序是{random_8_cards}")
    # print(f"根据南北方,随机插入剩下牌中间,此时新牌顺序:{random_8_cards}")

    # 5. 男生取1张,女生取2张,将这些牌扔掉
    gender = int(random.randint(1, 2))
    for i in range(gender):
        random_8_cards.popleft()
    # print(f"根据性别扔牌,此时新牌顺序:{random_8_cards}")

    # 6. 见证奇迹的时刻
    # 将双端队列中的元素向左旋转7个位置
    random_8_cards.rotate(-7)
    # print(f"见证奇迹的时刻(向左旋转7次牌),此时新牌顺序:{random_8_cards}")

    # 7. 好运留下来,烦恼丢出去!
    while len(random_8_cards) > 1:
        random_8_cards.append(random_8_cards.popleft())  # 第一张牌移到最后
        random_8_cards.popleft()  # 删除现在的第一张牌
    #     print(f"好运留下来,烦恼丢出去!(第一张牌移到最后,删除现在的第一张牌)此时剩余牌顺序:{random_8_cards}")
    # print(f"剩余最后1张牌是:{random_8_cards[0]}")

    # 8. 查看藏起来的1张牌
    # print(f"藏起来的1张牌是:{remembered_card[0]}")
    return [random_8_cards[0], remembered_card]


if __name__ == '__main__':
    # 进行多次模拟,计算正确率
    times = 100000
    correct_match_times = 0
    for i in range(times):
        result = magic()
        if result[0] == result[1]:
            correct_match_times += 1
    match_rate = f"{(correct_match_times / times * 100)} % "
    print(f"运行{times}次,正确率是{match_rate}")


Pycharm 控制台输出如下:
运行 10 万次程序,正确率 100%。
12.png

通过我们的代码实验,可以看出刘谦的这个魔术纯粹是数学原理,只要按照固定的顺序执行,就一定能拼成完成的牌。
所以小尼的牌能对不上也真是有点东西







免费评分

参与人数 27吾爱币 +26 热心值 +25 收起 理由
bobo0121 + 1 + 1 用心讨论,共获提升!
mynamejaw + 1 用心讨论,共获提升!
Rogers5 + 1 + 1 学习了,感谢大佬
starry888 + 1 用心讨论,共获提升!
yzhl + 1 + 1 用心讨论,共获提升!
flyingPoint + 1 我很赞同!
lai_xiaoji + 1 + 1 我很赞同!
shenguan7 + 1 + 1 我很赞同!
q6790296 + 1 + 1 6啊
soughing + 1 + 1 我很赞同!
huayugongju + 1 + 1 热心回复!
wp11007920653 + 1 + 1 我很赞同!
shiqiangge + 1 + 1 我很是赞同!
Naive2021 + 1 + 1 谢谢@Thanks!
NonsenseMe + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
rex_the_failure + 1 + 1 我很赞同!
为了青春 + 1 + 1 热心回复!
iNIC + 1 + 1 谢谢@Thanks!
fengoto + 2 + 1 热心回复!
xiaobinwang + 1 + 1 我很赞同!
lccccccc + 1 + 1 用心讨论,共获提升!
BonnieRan + 1 + 1 谢谢@Thanks!
Lishi8 + 1 + 1 用心讨论,共获提升!
lxwen + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
a1235465a + 1 + 1 我很赞同!
wincao + 1 + 1 我很赞同!
肉蛋葱鸡 + 1 + 1 用心讨论,共获提升!

查看全部评分

本帖被以下淘专辑推荐:

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

BonnieRan 发表于 2024-2-11 12:02
这个程序好有趣,魔术好像是数学上的约瑟夫环
TADYCB 发表于 2024-2-11 11:06
肉蛋葱鸡 发表于 2024-2-11 10:14
sai609 发表于 2024-2-11 09:59
why小尼的牌能对不上?
牧尘主宰 发表于 2024-2-11 10:14
sai609 发表于 2024-2-11 09:59
why小尼的牌能对不上?

尼格买提有一步没放在中间位置
AronnaxM 发表于 2024-2-11 10:14
sai609 发表于 2024-2-11 09:59
why小尼的牌能对不上?

其中一次刘谦让大家把牌插到中间,小尼插到最底下去了
harry2022 发表于 2024-2-11 10:57
这个也能用pythob解释,涨见识了,嘿嘿
随缘随意 发表于 2024-2-11 11:04
还是大佬牛X,支持下
tangjl12345 发表于 2024-2-11 11:28
TADYCB 发表于 2024-2-11 11:06
不会是故意的吧?增加节目效果

100%是故意的,制造话题,你看社交平台都在炒,如果不是故意的,难道为了说明小尼智商低?
bluecloud2016 发表于 2024-2-11 11:45
这种魔术 大卫科波菲尔小时候玩的
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-21 23:24

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表