三卡蒙特是一个常见的骗局,对轻信的游客和其他容易的标志。三张扑克牌,其中一张是红心皇后,正面朝下放在一个纸板盒上。庄家迅速重新排列纸牌,然后让马克挑选红心皇后。但是庄家可以使用各种各样的伎俩来隐藏卡片或欺骗,保证受害者永远不会赢。庄家还经常在人群中找到一些骗子,他们与庄家秘密合作,但假装赢了游戏(让受害者认为他们也能赢)或故意输得很惨(让受害者认为他们能做得更好)。
这个程序展示了三张牌,然后快速描述了一系列的交换。最后,它清空屏幕,玩家必须选择一张牌。你能跟上“红娘”吗?对于真正的三卡蒙特体验,您可以启用作弊功能,这将导致玩家总是输,即使他们选择了正确的卡。
当您运行threecardmonte.py时,输出将如下所示:
Three-Card Monte, by Al Sweigart email@protected
Find the red lady (the Queen of Hearts)! Keep an eye on how
the cards move.
Here are the cards:
___ ___ ___
|J | |Q | |8 |
| ♦ | | ♥ | | ♣ |
|__J| |__Q| |__8|
Press Enter when you are ready to begin...
swapping left and middle...
swapping right and middle...
swapping middle and left...
swapping right and left...
swapping left and middle...
`--snip--`
`<screen clears>`
Which card has the Queen of Hearts? (LEFT MIDDLE RIGHT)
> middle
___ ___ ___
|Q | |8 | |J |
| ♥ | | ♣ | | ♦ |
|__Q| |__8| |__J|
You lost!
Thanks for playing, sucker!在这个程序中,我们用一个(rank, suit)元组来表示一张扑克牌。等级是代表卡号的字符串,如'2'、'10'、'Q'或'K',花色是心形、梅花、黑桃或菱形表情符号的字符串。因为你不能用键盘输入表情符号,我们将在第 16 到 19 行使用chr()函数调用来产生它们。元组('9', '♦')代表方块 9。
第 28 到 43 行的displayCards()函数解释这些元组并在屏幕上显示 ASCII 艺术画表示,而不是直接打印出来,就像项目 4“21 点”一样。这个函数的cards参数是扑克牌元组的列表,允许在一行中显示多张牌。
"""Three-Card Monte, by Al Sweigart email@protected
Find the Queen of Hearts after cards have been swapped around.
(In the real-life version, the scammer palms the Queen of Hearts so you
always lose.)
More info at https://en.wikipedia.org/wiki/Three-card_Monte
This code is available at https://nostarch.com/big-book-small-python-programming
Tags: large, card game, game"""
import random, time
# Set up the constants:
NUM_SWAPS = 16 # (!) Try changing this to 30 or 100.
DELAY = 0.8 # (!) Try changing this 2.0 or 0.0.
# The card suit characters:
HEARTS = chr(9829) # Character 9829 is '♥'
DIAMONDS = chr(9830) # Character 9830 is '♦'
SPADES = chr(9824) # Character 9824 is '♠'
CLUBS = chr(9827) # Character 9827 is '♣'
# A list of chr() codes is at https://inventwithpython.com/chr
# The indexes of a 3-card list:
LEFT = 0
MIDDLE = 1
RIGHT = 2
def displayCards(cards):
"""Display the cards in "cards", which is a list of (rank, suit)
tuples."""
rows = ['', '', '', '', ''] # Stores the text to display.
for i, card in enumerate(cards):
rank, suit = card # The card is a tuple data structure.
rows[0] += ' ___ ' # Print the top line of the card.
rows[1] += '|{} | '.format(rank.ljust(2))
rows[2] += '| {} | '.format(suit)
rows[3] += '|_{}| '.format(rank.rjust(2, '_'))
# Print each row on the screen:
for i in range(5):
print(rows[i])
def getRandomCard():
"""Returns a random card that is NOT the Queen of Hearts."""
while True: # Make cards until you get a non-Queen of hearts.
rank = random.choice(list('23456789JQKA') + ['10'])
suit = random.choice([HEARTS, DIAMONDS, SPADES, CLUBS])
# Return the card as long as it's not the Queen of Hearts:
if rank != 'Q' and suit != HEARTS:
return (rank, suit)
print('Three-Card Monte, by Al Sweigart email@protected')
print()
print('Find the red lady (the Queen of Hearts)! Keep an eye on how')
print('the cards move.')
print()
# Show the original arrangement:
cards = [('Q', HEARTS), getRandomCard(), getRandomCard()]
random.shuffle(cards) # Put the Queen of Hearts in a random place.
print('Here are the cards:')
displayCards(cards)
input('Press Enter when you are ready to begin...')
# Print the swaps:
for i in range(NUM_SWAPS):
swap = random.choice(['l-m', 'm-r', 'l-r', 'm-l', 'r-m', 'r-l'])
if swap == 'l-m':
print('swapping left and middle...')
cards[LEFT], cards[MIDDLE] = cards[MIDDLE], cards[LEFT]
elif swap == 'm-r':
print('swapping middle and right...')
cards[MIDDLE], cards[RIGHT] = cards[RIGHT], cards[MIDDLE]
elif swap == 'l-r':
print('swapping left and right...')
cards[LEFT], cards[RIGHT] = cards[RIGHT], cards[LEFT]
elif swap == 'm-l':
print('swapping middle and left...')
cards[MIDDLE], cards[LEFT] = cards[LEFT], cards[MIDDLE]
elif swap == 'r-m':
print('swapping right and middle...')
cards[RIGHT], cards[MIDDLE] = cards[MIDDLE], cards[RIGHT]
elif swap == 'r-l':
print('swapping right and left...')
cards[RIGHT], cards[LEFT] = cards[LEFT], cards[RIGHT]
time.sleep(DELAY)
# Print several new lines to hide the swaps.
print('\n' * 60)
# Ask the user to find the red lady:
while True: # Keep asking until LEFT, MIDDLE, or RIGHT is entered.
print('Which card has the Queen of Hearts? (LEFT MIDDLE RIGHT)')
guess = input('> ').upper()
# Get the index in cards for the position that the player entered:
if guess in ['LEFT', 'MIDDLE', 'RIGHT']:
if guess == 'LEFT':
guessIndex = 0
elif guess == 'MIDDLE':
guessIndex = 1
elif guess == 'RIGHT':
guessIndex = 2
break
# (!) Uncomment this code to make the player always lose:
#if cards[guessIndex] == ('Q', HEARTS):
# # Player has won, so let's move the queen.
# possibleNewIndexes = [0, 1, 2]
# possibleNewIndexes.remove(guessIndex) # Remove the queen's index.
# newInd = random.choice(possibleNewIndexes) # Choose a new index.
# # Place the queen at the new index:
# cards[guessIndex], cards[newInd] = cards[newInd], cards[guessIndex]
displayCards(cards) # Show all the cards.
# Check if the player won:
if cards[guessIndex] == ('Q', HEARTS):
print('You won!')
print('Thanks for playing!')
else:
print('You lost!')
print('Thanks for playing, sucker!') 在输入源代码并运行几次之后,尝试对其进行实验性的修改。标有(!)的注释对你可以做的小改变有建议。你也可以自己想办法做到以下几点:
- 使用项目 57“进度条”中的退格打印技术,简单显示每条交换信息,然后打印
\b字符,在打印下一条信息之前将其删除。 - 创建一个增加难度的四卡蒙特游戏。
试着找出下列问题的答案。尝试对代码进行一些修改,然后重新运行程序,看看这些修改有什么影响。
- 如果把第 64 行的
[('Q', HEARTS), getRandomCard(), getRandomCard()]改成[('Q', HEARTS), ('Q', HEARTS), ('Q', HEARTS)]会怎么样? - 如果把第 49 行的
list('23456789JQKA')改成list('ABCDEFGHIJK')会怎么样? - 如果删除或注释掉第 93 行的
time.sleep(DELAY)会怎么样?
