在今年的春晚上,刘谦表演了一个与“约瑟夫问题”相关的卡牌戏法。这两天忙来忙去,总算有空用代码来复现一下。
这是戏法的进程:
- 进程 1:将准备好的 4 张扑克牌平均撕成两份,并叠在一同。
- 进程 2:将牌堆顶数量为【姓姓名数】的牌移至牌堆底。
- 进程 3:将前三张牌放在牌堆中间并取出牌堆顶的牌,放置在一旁。
- 进程 4:取出牌堆顶的若干张牌刺进牌堆中间,此处选择的牌数为南方人取 1 张,北方人取 2 张,若不确定是南方人仍是北方人取 3 张。
- 进程 5:男生丢掉牌堆顶 1 张,女生丢掉牌堆顶 2 张。
- 进程 6:执行“见证奇迹的时间”循环,每说一个字,就取出牌堆顶一张牌放置在牌堆底。
- 进程 7:从牌堆顶开始,每次先将牌堆顶的一张牌放在牌堆底,再丢掉牌堆顶的一张牌,重复以上操作直到只剩一张牌,检查此牌和放置在一旁的牌是否符合。若符合,则戏法成功。
抽卡
咱们先模仿抽卡的进程,这儿需求先从排队中抽取4张牌,这儿我使用了python的randint模块,他可以生成随机整数,这儿需求留意的是randint的取值是前闭后闭。这儿要别离取得牌的数字和花色,需求留意的是,为了能区别结果,在抽牌时咱们用 if pork not in porks
判别已抽取的牌堆中没有重复的牌:
from random import randint
porks = []
while len(porks) < 4:
num = randint(0, 12)
ranks = [
"Ace",
"2",
"3",
"4",
"5",
"6",
"7",
"8",
"9",
"10",
"Jack",
"Queen",
"King",
]
colornnum = randint(0,4)
color = ["♥", "♠", "♦", "♣"]
pork = ranks[num] color[colornnum]
if pork not in porks:
porks.append(pork)
要模仿撕卡的进程很简单,在代码中重复抽取的卡片即可。
porks = porks porks
依据姓名移动卡片
第二步,咱们要将牌堆顶数量为【姓姓名数】的牌移至牌堆底。这儿我对姓名的长度进行模仿,randint(2, 8) 随机生成2-8个字长度的姓名。假如需求的话,也可以改成认为输入姓名并判别长度。nameporks表明抽出的卡片,porks[num:] nameporks把抽出点卡片放到牌堆底部。
num = randint(2, 8)
print(f"姓名的字数是{num}")
nameporks = porks[:num]
print(f"姓名抽出的卡片是{nameporks}")
porks = porks[num:] nameporks
print(f"此刻的卡片是{porks}")
移动三张卡片和抽取卡片
这一步需求咱们抽出牌堆顶部的三张牌,牌堆顶部的三张卡片并刺进到剩下的牌堆中,其中我用headporks代表抽出允许三张牌,bottomporks是剩下的牌。
num = randint(1, 4) 是要刺进纸牌的方位,需求留意点是,这儿我刺进纸牌的方位要排除去首位和结尾。在完成卡片的刺进后,咱们取出牌堆顶的第一张卡片。
headporks = porks[:3]
bottomporks = porks[3:]
num = randint(1, 4)
print(f"刺进扑克的方位是{num}")
porks = bottomporks[:num] headporks bottomporks[num:]
print(f"刺进扑克卡片次序是{porks}")
# 藏起卡片
print(f"删去的卡片是{porks[0]}")
porks = porks[1:]
抽出若干牌刺进剩下的的牌堆
这儿我经过生成随机数来判别是北方人、南方人仍是其他,仍是像之前做过的相同,经过生成随机数来判别是什么人num = randint(0, 2)。
num = randint(0, 2)
if num == 0:
selectcards = porks[:1]
porks = porks[1:]
numpork = randint(1, 5)
porks = porks[:numpork] selectcards porks[numpork:]
print(num)
print("南方人")
elif num == 1:
selectcards = porks[:2]
porks = porks[2:]
numpork = randint(1, 4)
porks = porks[:numpork] selectcards porks[numpork:]
print(num)
print("北方人")
elif num == 2:
selectcards = porks[:3]
porks = porks[3:]
numpork = randint(1, 3)
porks = porks[:numpork] selectcards porks[numpork:]
print(numpork)
print("外国人")
print(porks)
男生丢掉牌堆顶 1 张,女生丢掉牌堆顶 2 张。
这儿依据男女,去掉顶部的牌,男生去掉一张,女生去掉三张。
num = randint(0, 1)
if num == int(0):
porks = porks[1:]
print("性别为男")
elif num == int(1):
porks = porks[2:]
print("性别为女")
print(f"卡片上{porks}")
执行“见证奇迹的时间”循环
这儿循环七次即可,每次把顶部的第一张牌移动到底部。需求留意的是,在抽取牌的进程中,假如只抽出第一张牌,要人为添加一个列表[porks[0]]。
for i in range(0, 7):
headporks = [porks[0]]
bottomporks = porks[1:]
porks = bottomporks headporks
print(porks)
print(f"交流后的卡片是{porks}")
美好留下来和烦恼丢出去
在这一步的进程中,假如牌堆中的牌数大于1,就进行循环,首先把顶部的牌放到底部,然后丢掉顶部的牌。
while len(porks) > 1:
headporks = [porks[0]]
bottomporks = porks[1:]
porks = bottomporks headporks
print(f"欢喜{porks}")
# 烦恼
porks = porks[1:]
print(f"烦恼{porks}")
完好代码:
from random import randint
# 进程 1:将准备好的 4 张扑克牌平均撕成两份,并叠在一同。
porks = []
while len(porks) < 4:
num = randint(0, 12)
ranks = [
"Ace",
"2",
"3",
"4",
"5",
"6",
"7",
"8",
"9",
"10",
"Jack",
"Queen",
"King",
]
colornnum = randint(0, 3)
color = ["♥", "♠", "♦", "♣"]
pork = ranks[num] color[colornnum]
if pork not in porks:
porks.append(pork)
print(porks)
porks = porks porks
print(f"卡片次序是{porks}")
# 进程 2:将牌堆顶数量为【姓姓名数】的牌移至牌堆底。
num = randint(2, 8)
print(f"姓名的字数是{num}")
nameporks = porks[:num]
print(f"姓名抽出的卡片是{nameporks}")
porks = porks[num:] nameporks
print(f"此刻的卡片是{porks}")
# 进程 3:将前三张牌放在牌堆中间并取出牌堆顶的牌,放置在一旁。
headporks = porks[:3]
bottomporks = porks[3:]
num = randint(1, 4)
print(f"刺进扑克的方位是{num}")
porks = bottomporks[:num] headporks bottomporks[num:]
print(f"刺进扑克卡片次序是{porks}")
# 藏起卡片
print(f"删去的卡片是{porks[0]}")
porks = porks[1:]
print(porks)
# 南方人1,北方人2,其他3
num = randint(0, 2)
if num == 0:
selectcards = porks[:1]
porks = porks[1:]
numpork = randint(1, 5)
porks = porks[:numpork] selectcards porks[numpork:]
print(num)
print("南方人")
elif num == 1:
selectcards = porks[:2]
porks = porks[2:]
numpork = randint(1, 4)
porks = porks[:numpork] selectcards porks[numpork:]
print(num)
print("北方人")
elif num == 2:
selectcards = porks[:3]
porks = porks[3:]
numpork = randint(1, 3)
porks = porks[:numpork] selectcards porks[numpork:]
print(numpork)
print("外国人")
print(porks)
# 男生1,女生2
# 0 男生 1 女生
num = randint(0, 1)
if num == int(0):
porks = porks[1:]
print("性别为男")
elif num == int(1):
porks = porks[2:]
print("性别为女")
print(f"卡片上{porks}")
# 见证奇迹的时间
for i in range(0, 7):
headporks = [porks[0]]
bottomporks = porks[1:]
porks = bottomporks headporks
print(porks)
print(f"交流后的卡片是{porks}")
while len(porks) > 1:
headporks = [porks[0]]
bottomporks = porks[1:]
porks = bottomporks headporks
print(f"欢喜{porks}")
# 烦恼
porks = porks[1:]
print(f"烦恼{porks}")
print(porks)