Python实战:用Python程序实现春晚刘谦魔术

刘谦春晚魔术是一个让人叹为观止的魔术表演,其中涉及到了数学、编程和创意的结合。看了春晚魔术的朋友们,是不是好奇春晚刘谦的魔术是怎么变的。

在这篇文章中,我们将通过 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() 函数,将列表中的元素随机打乱。这个函数会直接修改原始列表,而不是创建一个新的打乱顺序的列表。

import random
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}")

Pycharm 控制台输出如下:

2、随机抽取4张牌

使用random.sample() 是 函数,从列表中随机抽取指定数量的元素。这个函数不会修改原始序列,而是返回一个新的包含抽取元素的列表。

from collections import deque# 随机选择4张牌
random_4_cards = random.sample(cards, 4)
print(f"随机抽出的4张牌:{random_4_cards}")

Pycharm 控制台输出如下:

3、将牌对折撕开

创建了一个名为 random_8_cards 的双端队列,其中包含 random_4_cards 的 2 倍元素。

# 对折后撕开得到8张牌
random_8_cards = deque(random_4_cards * 2)
print(f"对折后撕开得到8张牌:{random_8_cards}")

Pycharm 控制台输出如下:

4、根据名字字数得到新顺序牌

使用 collections.deque 类中的rotate() 方法,将双端队列中的元素向左或向右旋转指定的位置。这个方法接受一个参数,表示要旋转的位置数。正数表示向右旋转,负数表示向左旋转。

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

Pycharm 控制台输出如下:

5、最上面3张插入剩下牌中间

# 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}")

Pycharm 控制台输出如下:

6、最上面1张牌藏起来

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

Pycharm 控制台输出如下:

7、根据南北方得到新顺序牌

# 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}")

Pycharm 控制台输出如下:

8、根据性别得到新顺序牌

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

Pycharm 控制台输出如下:

9、见证奇迹的时刻

"见证奇迹的时刻"是 7 个字,翻译成代码就是将双端队列中的元素向左旋转 7 个位置。

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

Pycharm 控制台输出如下:

10、好运留下来,烦恼丢出去

# 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}")

Pycharm 控制台输出如下:

三、完整代码

完整的代码程序如下:

import random
from collections import dequecards = ["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}")

Pycharm 控制台输出如下:

四、封装函数

我们将上面的代码进行封装,定义一个 magic() 函数,把名字字数定义为随机 1-10 的数字,南北方人为随机 1-3 的数字,性别为随机 1-2 的数字。

在 main 主函数内调用 10 万次 magic()函数,看一下运行结果正确率。

import random
from collections import dequedef 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 = 100000correct_match_times = 0for i in range(times):result = magic()if result[0] == result[1]:correct_match_times += 1match_rate = f"{(correct_match_times / times * 100)} % "print(f"运行{times}次,正确率是{match_rate}")

Pycharm 控制台输出如下:

运行 10 万次程序,正确率 100%。

五、总结

通过我们的代码实验,可以看出刘谦的这个魔术纯粹是数学原理,只要按照固定的顺序执行,就一定能拼成完成的牌。

如果您觉得这篇文章对您有所启发或帮助,请不吝点赞、转发,与您的朋友和家人分享。

本文首发在“程序员coding”公众号,欢迎关注与我一起交流学习。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/463130.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2024年N1叉车司机证模拟考试题库及N1叉车司机理论考试试题

题库来源:安全生产模拟考试一点通公众号小程序 2024年N1叉车司机证模拟考试题库及N1叉车司机理论考试试题是由安全生产模拟考试一点通提供,N1叉车司机证模拟考试题库是根据N1叉车司机最新版教材,N1叉车司机大纲整理而成(含2024年…

MIPS指令集处理器设计(支持64条汇编指令)

一、题目背景和意义 二、国内外研究现状 (略) 三、MIPS指令集处理器设计与实现 (一).MIPS指令集功能性梳理 1.MIPS指令集架构 (1).mips基础指令集格式总结 MIPS是(Microcomputer without interlocked pipeline stages)[10]的缩写,含义是…

《动手学深度学习(PyTorch版)》笔记7.7

注:书中对代码的讲解并不详细,本文对很多细节做了详细注释。另外,书上的源代码是在Jupyter Notebook上运行的,较为分散,本文将代码集中起来,并加以完善,全部用vscode在python 3.9.18下测试通过&…

Flutter开发iOS问题记录

一、版本适配问题 warning: The iOS deployment target ‘IPHONEOS_DEPLOYMENT_TARGET’ is set to 10.0, but the range of supported deployment target versions is 12.0 to 17.2.99. (in target ‘Protobuf’ from project ‘Pods’) 可以通过在podfile中配置解决。 pos…

数字孪生:构建未来智慧社区的关键技术

随着科技的快速发展,数字孪生技术作为构建未来智慧社区的关键技术,正逐渐受到广泛关注。数字孪生技术能够实现物理世界与数字世界的交互映射,为智慧社区的建设提供强有力的支持。本文将探讨数字孪生技术在构建未来智慧社区中的作用和意义&…

Android14音频进阶:MediaPlayerService如何启动AudioTrack 上篇(五十五)

简介: CSDN博客专家,专注Android/Linux系统,分享多mic语音方案、音视频、编解码等技术,与大家一起成长! 优质专栏:Audio工程师进阶系列【原创干货持续更新中……】🚀 优质专栏:多媒体系统工程师系列【原创干货持续更新中……】🚀 人生格言: 人生从来没有捷径,只…

如何在Sprint中管理UI测试?

作为iOS团队,我们编写3种类型的UI测试。如果你问这些是什么;快照、冒烟和回归测试。那么这些测试到底是什么?让我们稍微谈谈这些。 快照测试快照测试是检查UI中的某些内容是否损坏的测试。 首先,它将所需的视图图像保存在某处&am…

U3D记录之FBX纹理丢失问题

今天费老大劲从blender建了个模型,然后导出进去unity 发现贴图丢失 上网查了一下 首先blender导出要改设置 这个path mode要copy 然后unity加载纹理也要改设置 这里这个模型的纹理load要改成external那个模式 然后就有了,另外这个导出还有好多选项可…

【linux温故】CFS调度

写在前面 网上关于CFS 调度器的文章多如牛毛,没必要自己写。很多文章写的都非常好。 很多文章里,关键的技术点,都是一样的,只是各个文章说法不一样。 掌握了核心的,关键的,其他的,如果工作中…

SpringBoot3整合Mybatis-Plus,自定义动态数据源starter

文章目录 前言正文一、项目总览二、核心代码展示2.1 自定义AbstractRoutingDataSource2.2 动态数据源DynamicDataSource2.3 动态数据源自动配置2.4 动态数据源上下文DynamicDataSourceContextHolder2.5 动态数据源修改注解定义2.6 修改切面DynamicDataSourceAspect2.7 动态数据…

轻薄型工业平板亿道EM-T195,续航持久高达10小时

时尚而坚固的 10.1英寸EM-T195触摸屏平板电脑融合了高耐力和无与伦比的适应性,可抵御极端天气条件和多重冲击,借助强大的联发科8核处理器,它可以从容面对任何工作挑战。 其读取能力(2D 成像器)结合其坚固性&#xff0…

hexo部署到gitee(码云)

引言 Hexo 是一个基于Node.js的静态博客框架,而 Gitee(也被称为码云)是一个国内的代码托管平台,支持 Git 版本控制系统,与 GitHub 类似。将 Hexo 部署到 Gitee Pages 可以让你的博客受益于 Gitee 的国内服务器&#xf…