一、流程分析
先简单用流程图分析一下魔术操作,图片来源B站漫士沉思录,具体可以看视频了解具体原理,这里不做展示。
二、代码实现
需要关注几个python代码写法:
(1)定义三个函数:生成随机的扑克牌、把第一张牌移到最后、将最上面的几张牌整体任意插入中间,但不能最后
(2)使用集合(set)来确保生成的牌不重复
cards = set()
(3)不能插入到最后,这一步也是小尼出错原因所在
if insert_index == len(cards) - num_cards:
insert_index -= 1
全部代码如下:
# 作者:Alex Xia
# 日期:2024-02-12
import random
import time
from PIL import Image, ImageDraw, ImageFont
import matplotlib.pyplot as plt
#定义扑克牌的花色和数字
suits = ['红桃', '黑桃', '方块', '梅花']
ranks = ['2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K', 'A']
#生成随机的扑克牌
def generate_random_cards(num_cards):
cards = set() #使用集合(set)来确保生成的牌不重复
while len(cards) < num_cards:
suit = random.choice(suits)
rank = random.choice(ranks)
cards.add(suit + rank)
return list(cards)
#把第一张牌移到最后
def move_first_card_to_last(cards):
if len(cards) > 0:
first_card = cards.pop(0)
cards.append(first_card)
#将最上面的几张牌整体任意插入中间,但不能最后
def insert_cards_in_middle(cards, num_cards):
if len(cards) >= num_cards:
insert_index = random.randint(1, len(cards) - num_cards)
if insert_index == len(cards) - num_cards: #不能插入到最后,这一步也是小尼出错原因所在
insert_index -= 1
cards_to_insert = cards[:num_cards]
del cards[:num_cards]
cards[insert_index:insert_index] = cards_to_insert
if __name__ == "__main__":
#随机生成4张扑克牌
random_cards = generate_random_cards(4)
#print('抽4张扑克牌:',random_cards)
#time.sleep(1)
#洗混/打乱扑克牌
random.shuffle(random_cards)
#print('打乱扑克牌:',random_cards)
#time.sleep(1)
#对折撕成两半(复制四张牌到原有序列)
random_cards.extend(random_cards)
#print('对折撕成两半:', random_cards)
#time.sleep(1)
#名字几个字,往后放几张
name = input("请输入你的名字:")
n = len(name)
for _ in range(n):
move_first_card_to_last(random_cards)
#print('名字{}个字,往后放{}张: {}'.format(n, n, random_cards))
#time.sleep(1)
#将最上面的三张牌插入中间
insert_cards_in_middle(random_cards, 3)
#print('将最上面的三张牌插入中间:', random_cards)
#time.sleep(1)
#展示最上面的牌
top_card = random_cards[0]
#print('最上面的牌:', top_card)
#time.sleep(1)
#从牌堆中删除最上面的牌
del random_cards[0]
#print('剩余的牌:', random_cards)
#time.sleep(1)
#根据地域移动牌的位置
region = input("南方人扣1,北方人扣2,不确定扣3:")
insert_cards_in_middle(random_cards, int(region))
#print('根据地域移动牌的位置:', random_cards)
#time.sleep(1)
#根据性别丢牌
gender = input("男性扣1,女性扣2:")
for _ in range(int(gender)):
del random_cards[0]
#print('根据性别丢牌:', random_cards)
#time.sleep(1)
#七字真言移动牌
for _ in range(7):
move_first_card_to_last(random_cards)
#print('七字真言移动牌:', random_cards)
#time.sleep(1)
#好运留下来,烦恼丢出去
while len(random_cards) != 1:
move_first_card_to_last(random_cards)
del random_cards[0]
final_card = random_cards[0]
#print('好运留下来,烦恼丢出去:', final_card)
print('之前留下的牌:', top_card)
print('最后的一张牌:', final_card)
#print('其实刘谦想表达的是,无论你身处南北,不管你男和女,你叫什么,最终都会连为一体,海峡两岸一定会统一')
width, height = 400, 200
background_color = (255, 255, 255) # 白色
image = Image.new("RGB", (width, height), background_color)
draw = ImageDraw.Draw(image)
text = "其实刘谦想表达的是,\n无论你身处南北,\n不管你男和女,\n你叫什么,\n最终都会连为一体,\n海峡两岸一定会统一"
font_size = 20
font_path = "simsun.ttc"
font = ImageFont.truetype(font_path, font_size)
text_color = (0, 0, 0) # 黑色
text_position = (20, 20)
draw.text(text_position, text, fill=text_color, font=font)
plt.imshow(image)
plt.axis('off')
plt.show()
最后的图片文字是一位B友的评论,写的很好,格局打开
三、如何解决小尼出现的状况?
如果出现小尼的情况,我们该怎么解决,如何修改代码?
原因所在就是牌没有完全插入到中间,有一张牌插入到最后,可以这样修改(增加一个判断语句)
#名字几个字,往后放几张
name = input("请输入你的名字:")
n = len(name)
for _ in range(n):
move_first_card_to_last(random_cards)
Verification1 = random_cards[-1]
Origin1 = random_cards[:]
#print('名字{}个字,往后放{}张: {}'.format(n, n, random_cards))
#time.sleep(1)
#将最上面的三张牌插入中间
insert_cards_in_middle(random_cards, 3)
while random_cards[-1] != Verification1:
random_cards = Origin1[:]
insert_cards_in_middle(random_cards, 3)
#print('将最上面的三张牌插入中间:', random_cards)
#time.sleep(1)
#从牌堆中删除最上面的牌
del random_cards[0]
Verification2 = random_cards[-1]
Origin2 = random_cards[:]
#print('剩余的牌:', random_cards)
#time.sleep(1)
#根据地域移动牌的位置
#region = input("南方人扣1,北方人扣2,不确定扣3:")
region = 2
insert_cards_in_middle(random_cards, int(region))
while random_cards[-1] != Verification2:
random_cards = Origin2[:]
insert_cards_in_middle(random_cards, int(region))
#print('根据地域移动牌的位置:', random_cards)
#time.sleep(1)