Python 小型项目大全 1~5

news2025/6/16 9:31:35

一、百吉饼

原文:http://inventwithpython.com/bigbookpython/project1.html

在百吉饼这种演绎逻辑游戏中,你必须根据线索猜出一个秘密的三位数。该游戏提供以下提示之一来响应您的猜测:"Pico",当您的猜测在错误的位置有正确的数字时,"Fermi",当您的猜测在正确的位置有正确的数字时,以及"Bagels",如果您的猜测没有正确的数字。你有 10 次机会猜这个秘密数字。

运行示例

当您运行bagels.py时,输出将如下所示:

Bagels, a deductive logic game.
By Al Sweigart email@protected
I am thinking of a 3-digit number. Try to guess what it is.
Here are some clues:
When I say:    That means:
  Pico         One digit is correct but in the wrong position.
  Fermi        One digit is correct and in the right position.
  Bagels       No digit is correct.
I have thought up a number.
 You have 10 guesses to get it.
Guess #1:
> 123
Pico
Guess #2:
> 456
Bagels
Guess #3:
> 178
Pico Pico
`--snip--`
Guess #7:
> 791
Fermi Fermi
Guess #8:
> 701
You got it!
Do you want to play again? (yes or no)
> no
Thanks for playing!

工作原理

请记住,这个程序使用的不是整数值,而是包含数字的字符串值。例如,'426'是与426不同的值。我们需要这样做,因为我们执行的是与秘密数字的字符串比较,而不是数学运算。记住'0'可以是前导数字:字符串'026''26'不同,但整数02626相同。

"""Bagels, by Al Sweigart email@protected
A deductive logic game where you must guess a number based on clues.
This code is available at https://nostarch.com/big-book-small-python-programming
A version of this game is featured in the book, "Invent Your Own
Computer Games with Python" https://nostarch.com/inventwithpython
Tags: short, game, puzzle"""

import random

NUM_DIGITS = 3  # (!) Try setting this to 1 or 10.
MAX_GUESSES = 10  # (!) Try setting this to 1 or 100.


def main():
   print('''Bagels, a deductive logic game.
By Al Sweigart email@protected

I am thinking of a {}-digit number with no repeated digits.
Try to guess what it is. Here are some clues:
When I say:    That means:
 Pico         One digit is correct but in the wrong position.
 Fermi        One digit is correct and in the right position.
 Bagels       No digit is correct.

For example, if the secret number was 248 and your guess was 843, the
clues would be Fermi Pico.'''.format(NUM_DIGITS))

   while True:  # Main game loop.
       # This stores the secret number the player needs to guess:
       secretNum = getSecretNum()
       print('I have thought up a number.')
       print(' You have {} guesses to get it.'.format(MAX_GUESSES))

       numGuesses = 1
       while numGuesses <= MAX_GUESSES:
           guess = ''
           # Keep looping until they enter a valid guess:
           while len(guess) != NUM_DIGITS or not guess.isdecimal():
               print('Guess #{}: '.format(numGuesses))
               guess = input('> ')

           clues = getClues(guess, secretNum)
           print(clues)
           numGuesses += 1

           if guess == secretNum:
               break  # They're correct, so break out of this loop.
           if numGuesses > MAX_GUESSES:
               print('You ran out of guesses.')
               print('The answer was {}.'.format(secretNum))

       # Ask player if they want to play again.
       print('Do you want to play again? (yes or no)')
       if not input('> ').lower().startswith('y'):
           break
   print('Thanks for playing!')


def getSecretNum():
   """Returns a string made up of NUM_DIGITS unique random digits."""
   numbers = list('0123456789')  # Create a list of digits 0 to 9.
   random.shuffle(numbers)  # Shuffle them into random order.

   # Get the first NUM_DIGITS digits in the list for the secret number:
   secretNum = ''
   for i in range(NUM_DIGITS):
       secretNum += str(numbers[i])
   return secretNum


def getClues(guess, secretNum):
   """Returns a string with the pico, fermi, bagels clues for a guess
   and secret number pair."""
   if guess == secretNum:
       return 'You got it!'

   clues = []

   for i in range(len(guess)):
       if guess[i] == secretNum[i]:
           # A correct digit is in the correct place.
           clues.append('Fermi')
       elif guess[i] in secretNum:
           # A correct digit is in the incorrect place.
           clues.append('Pico')
   if len(clues) == 0:
       return 'Bagels'  # There are no correct digits at all.
   else:
       # Sort the clues into alphabetical order so their original order
       # doesn't give information away.
       clues.sort()
       # Make a single string from the list of string clues.
       return ' '.join(clues)


# If the program is run (instead of imported), run the game:
if __name__ == '__main__':
   main() 

在输入源代码并运行几次之后,尝试对其进行实验性的修改。标有(!)的注释对你可以做的小改变有建议。你也可以自己想办法做到以下几点:

  • 通过改变NUM_DIGITS来改变密码的位数。
  • 通过改变MAX_GUESSES来改变玩家获得的猜测次数。
  • 尝试创建一个密码中包含字母和数字的版本。

探索程序

试着找出下列问题的答案。尝试对代码进行一些修改,然后重新运行程序,看看这些修改有什么影响。

  1. 改变NUM_DIGITS常数会发生什么?
  2. 改变MAX_GUESSES常数会发生什么?
  3. 如果将NUM_DIGITS设置为大于10的数字会发生什么?
  4. 如果把第 30 行的secretNum = getSecretNum()换成secretNum = '123'会怎么样?
  5. 如果删除或注释掉第 34 行的numGuesses = 1,会得到什么错误信息?
  6. 如果删除或注释掉第 62 行的random.shuffle(numbers)会发生什么?
  7. 如果删除或注释掉第 74 行的if guess == secretNum:和第 75 行的return 'You got it!'会怎么样?
  8. 如果在第 44 行注释掉numGuesses += 1会发生什么?

二、生日悖论

原文:http://inventwithpython.com/bigbookpython/project2.html

生日悖论(Birthday Paradox),也称为生日问题,是指即使在一小群人中,两个人过同一个生日的概率也高得惊人。在一个 70 人的小组中,有 99.9%的可能性两个人有相同的生日。但是,即使在一个只有 23 人的小组中,也有 50%的机会有相同的生日。这个程序执行几个概率实验来确定不同大小的组的百分比。我们称这种类型的实验为蒙特卡洛实验,在这种实验中,我们进行多次随机试验来了解可能的结果。

你可以在en.wikipedia.org/wiki/Birthday_problem找到更多关于生日悖论的信息。

运行示例

当您运行birthdayparadox.py时,输出如下:

Birthday Paradox, by Al Sweigart email@protected
`--snip--`
How many birthdays shall I generate? (Max 100)
> 23
Here are 23 birthdays:
Oct 9, Sep 1, May 28, Jul 29, Feb 17, Jan 8, Aug 18, Feb 19, Dec 1, Jan 22,
May 16, Sep 25, Oct 6, May 6, May 26, Oct 11, Dec 19, Jun 28, Jul 29, Dec 6,
Nov 26, Aug 18, Mar 18
In this simulation, multiple people have a birthday on Jul 29
Generating 23 random birthdays 100,000 times...
Press Enter to begin...
Let's run another 100,000 simulations.
0 simulations run...
10000 simulations run...
`--snip--`
90000 simulations run...
100000 simulations run.
Out of 100,000 simulations of 23 people, there was a
matching birthday in that group 50955 times. This means
that 23 people have a 50.95 % chance of
having a matching birthday in their group.
That's probably more than you would think!

工作原理

运行 100,000 次模拟可能需要一段时间,这就是为什么第 95 行和第 96 行报告另外 10,000 次模拟已经完成。这个反馈可以向用户保证程序没有冻结。注意一些整数,比如第 95 行的10_000和第 93、103 行的100_000,有下划线。这些下划线没有特殊的含义,但是 Python 允许使用它们,这样程序员可以使整数值更容易阅读。换句话说,读100_000的《十万》比读100000的更容易。

"""Birthday Paradox Simulation, by Al Sweigart email@protected
Explore the surprising probabilities of the "Birthday Paradox".
More info at https://en.wikipedia.org/wiki/Birthday_problem
This code is available at https://nostarch.com/big-book-small-python-programming
Tags: short, math, simulation"""

import datetime, random


def getBirthdays(numberOfBirthdays):
   """Returns a list of number random date objects for birthdays."""
   birthdays = []
   for i in range(numberOfBirthdays):
       # The year is unimportant for our simulation, as long as all
       # birthdays have the same year.
       startOfYear = datetime.date(2001, 1, 1)

       # Get a random day into the year:
       randomNumberOfDays = datetime.timedelta(random.randint(0, 364))
       birthday = startOfYear + randomNumberOfDays
       birthdays.append(birthday)
   return birthdays


def getMatch(birthdays):
   """Returns the date object of a birthday that occurs more than once
   in the birthdays list."""
   if len(birthdays) == len(set(birthdays)):
       return None  # All birthdays are unique, so return None.

   # Compare each birthday to every other birthday:
   for a, birthdayA in enumerate(birthdays):
       for b, birthdayB in enumerate(birthdays[a + 1 :]):
           if birthdayA == birthdayB:
               return birthdayA  # Return the matching birthday.


# Display the intro:
print('''Birthday Paradox, by Al Sweigart email@protected

The birthday paradox shows us that in a group of N people, the odds
that two of them have matching birthdays is surprisingly large.
This program does a Monte Carlo simulation (that is, repeated random
simulations) to explore this concept.

(It's not actually a paradox, it's just a surprising result.)
''')

# Set up a tuple of month names in order:
MONTHS = ('Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
         'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec')

while True:  # Keep asking until the user enters a valid amount.
   print('How many birthdays shall I generate? (Max 100)')
   response = input('> ')
   if response.isdecimal() and (0 < int(response) <= 100):
       numBDays = int(response)
       break  # User has entered a valid amount.
print()

# Generate and display the birthdays:
print('Here are', numBDays, 'birthdays:')
birthdays = getBirthdays(numBDays)
for i, birthday in enumerate(birthdays):
   if i != 0:
       # Display a comma for each birthday after the first birthday.
       print(', ', end='')
   monthName = MONTHS[birthday.month - 1]
   dateText = '{}  {}'.format(monthName, birthday.day)
   print(dateText, end='')
print()
print()

# Determine if there are two birthdays that match.
match = getMatch(birthdays)

# Display the results:
print('In this simulation, ', end='')
if match != None:
   monthName = MONTHS[match.month - 1]
   dateText = '{}  {}'.format(monthName, match.day)
   print('multiple people have a birthday on', dateText)
else:
   print('there are no matching birthdays.')
print()

# Run through 100,000 simulations:
print('Generating', numBDays, 'random birthdays 100,000 times...')
input('Press Enter to begin...')

print('Let\'s run another 100,000 simulations.')
simMatch = 0  # How many simulations had matching birthdays in them.
for i in range(100000):
   # Report on the progress every 10,000 simulations:
   if i % 10000 == 0:
       print(i, 'simulations run...')
   birthdays = getBirthdays(numBDays)
   if getMatch(birthdays) != None:
       simMatch = simMatch + 1
print('100,000 simulations run.')

# Display simulation results:
probability = round(simMatch / 100000 * 100, 2)
print('Out of 100,000 simulations of', numBDays, 'people, there was a')
print('matching birthday in that group', simMatch, 'times. This means')
print('that', numBDays, 'people have a', probability, '% chance of')
print('having a matching birthday in their group.')
print('That\'s probably more than you would think!') 

探索程序

试着找出下列问题的答案。尝试对代码进行一些修改,然后重新运行程序,看看这些修改有什么影响。

  1. 生日在这个节目中是如何表示的?(提示:请看第 16 行。)
  2. 你如何取消程序生成的 100 个生日的最大限制?
  3. 如果删除或注释掉第 57 行的numBDays = int(response),会得到什么错误信息?
  4. 如何让程序显示完整的月份名称,比如'January'而不是'Jan'
  5. 你如何让'X simulations run...'每 1000 次模拟出现一次,而不是每 10000 次?

三、位图消息

原文:http://inventwithpython.com/bigbookpython/project3.html

这个程序使用一个多行字符串作为位图,一个每个像素只有两种可能颜色的 2D 图像,来决定它应该如何显示来自用户的消息。在这个位图中,空格字符代表一个空白,所有其他字符都被用户消息中的字符所替换。提供的位图类似于世界地图,但是您可以将其更改为您喜欢的任何图像。空格或消息字符系统的二进制简单性使它非常适合初学者。尝试不同的消息,看看结果是什么样的!

运行示例

当您运行bitmapmessage.py时,输出将如下所示:

Bitmap Message, by Al Sweigart email@protected
Enter the message to display with the bitmap.
> Hello!

Hello!Hello!Hello!Hello!Hello!Hello!Hello!Hello!Hello!Hello!Hello!He
   lo!Hello!Hello   l  !He lo  e      llo!Hello!Hello!Hello!Hello!He
  llo!Hello!Hello!Hello He lo H  l !Hello!Hello!Hello!Hello!Hello H
 el      lo!Hello!Hello!He       lo!Hello!Hello!Hello!Hello!Hel
          o!Hello!Hello          lo  e lo!H ll !Hello!Hello!H l
           !Hello!He            llo!Hel   Hello!Hello!Hell ! e
            Hello!He           ello!Hello!Hello!Hello!Hell  H
   l        H llo! ell         ello!Hello!Hell !Hello  el o
               lo!H  l         ello!Hello!Hell   ell !He  o
                 !Hello         llo!Hello!Hel    el   He  o
                 !Hello!H        lo!Hello!Hell    l  !H llo
                   ello!Hel         Hello!He          H llo Hell
                   ello!Hell         ello!H  l        Hell !H l o!
                   ello!Hell         ello!H l o           o!H l   H
                     lo!Hel          ello! el             o!Hel   H
                     lo!He            llo! e            llo!Hell
                    llo!H             llo!              llo!Hello
                    llo!              ll                 lo!Hell   e
                    llo                                       l    e
                    ll     l                    H
Hello!Hello!Hello!Hello!Hello!Hello!Hello!Hello!Hello!Hello!Hello!He 

工作原理

你可以从inventwithpython.com/bitmapworld.txt复制并粘贴整个世界地图图案,而不是单独输入每个字符。图案顶部和底部的 68 个句点组成的线充当标尺,帮助您正确对齐。然而,如果您在模式中输入了错误,该程序仍然可以工作。

第 43 行的bitmap.splitlines()方法调用返回一个字符串列表,每个字符串都是多行bitmap字符串中的一行。使用多行字符串使位图更容易编辑成您喜欢的任何图案。该程序填充模式中的任何非空格字符,这就是星号、句点或任何其他字符做同样事情的原因。

第 51 行的message[i % len(message)]代码导致message中文本的重复。随着i0增加到大于len(message)的数字,表达式i % len(message)再次计算为0。这使得message[i % len(message)]随着i的增加而重复message中的字符。

"""Bitmap Message, by Al Sweigart email@protected
Displays a text message according to the provided bitmap image.
This code is available at https://nostarch.com/big-book-small-python-programming
Tags: tiny, beginner, artistic"""

import sys

# (!) Try changing this multiline string to any image you like:

# There are 68 periods along the top and bottom of this string:
# (You can also copy and paste this string from
# https://inventwithpython.com/bitmapworld.txt)
bitmap = """
....................................................................
   **************   *  *** **  *      ******************************
  ********************* ** ** *  * ****************************** *
 **      *****************       ******************************
          *************          **  * **** ** ************** *
           *********            *******   **************** * *
            ********           ***************************  *
   *        * **** ***         *************** ******  ** *
               ****  *         ***************   *** ***  *
                 ******         *************    **   **  *
                 ********        *************    *  ** ***
                   ********         ********          * *** ****
                   *********         ******  *        **** ** * **
                   *********         ****** * *           *** *   *
                     ******          ***** **             *****   *
                     *****            **** *            ********
                    *****             ****              *********
                    ****              **                 *******   *
                    ***                                       *    *
                    **     *                    *
...................................................................."""

print('Bitmap Message, by Al Sweigart email@protected')
print('Enter the message to display with the bitmap.')
message = input('> ')
if message == '':
    sys.exit()

# Loop over each line in the bitmap:
for line in bitmap.splitlines():
    # Loop over each character in the line:
    for i, bit in enumerate(line):
        if bit == ' ':
            # Print an empty space since there's a space in the bitmap:
            print(' ', end='')
        else:
            # Print a character from the message:
            print(message[i % len(message)], end='')
    print()  # Print a newline. 

在输入源代码并运行几次之后,尝试对其进行实验性的修改。您可以更改bitmap中的字符串来创建全新的模式。

探索程序

试着找出下列问题的答案。尝试对代码进行一些修改,然后重新运行程序,看看这些修改有什么影响。

  1. 如果玩家为消息输入一个空字符串会发生什么?
  2. bitmap变量的字符串中有什么非空格字符有关系吗?
  3. 第 45 行创建的i变量代表什么?
  4. 如果删除或注释掉第 52 行的print(),会出现什么 bug?

四、二十一点

原文:http://inventwithpython.com/bigbookpython/project4.html

21 点,也称为 21 点,是一种纸牌游戏,玩家试图在不超过 21 点的情况下尽可能接近 21 点。这个程序使用用文本字符绘制的图像,称为 ASCII 艺术画。美国信息交换标准码(ASCII)是 Unicode 取代之前计算机使用的文本字符到数字代码的映射。本程序中的扑克牌是 ASCII 艺术画的一个例子:

 ___   ___
|A  | |10 |
|| ||
|__A| |_10|

你可以在en.wikipedia.org/wiki/Blackjack找到其他规则和这个纸牌游戏的历史。

运行示例

当您运行blackjack.py时,输出将如下所示:

Blackjack, by Al Sweigart email@protected

    Rules:
      Try to get as close to 21 without going over.
      Kings, Queens, and Jacks are worth 10 points.
      Aces are worth 1 or 11 points.
      Cards 2 through 10 are worth their face value.
      (H)it to take another card.
      (S)tand to stop taking cards.
      On your first play, you can (D)ouble down to increase your bet
      but must hit exactly one more time before standing.
      In case of a tie, the bet is returned to the player.
      The dealer stops hitting at 17.
Money: 5000
How much do you bet? (1-5000, or QUIT)
> 400
Bet: 400

DEALER: ???
 ___   ___
|## | |2  |
|###| | ♥ |
|_##| |__2|

PLAYER: 17
 ___   ___
|K  | |7  |
|| ||
|__K| |__7|

(H)it, (S)tand, (D)ouble down
> h
You drew a 4 of ♦.
`--snip--`
DEALER: 18
 ___   ___   ___
|K  | |2  | |6  |
|| || ||
|__K| |__2| |__6|

PLAYER: 21
 ___   ___   ___
|K  | |7  | |4  |
|| || ||
|__K| |__7| |__4|

You won $400!
`--snip—`

工作原理

你的键盘上没有牌组符号,这就是为什么我们调用chr()函数来创建它们。传递给chr()的整数被称为 Unicode 码位,这是根据 Unicode 标准标识字符的唯一数字。Unicode 经常被误解。然而,Ned Batchelder 的 2012 年 PyCon US talk“实用 Unicode,或者我如何停止痛苦?”是对 Unicode 的极好介绍,您可以在youtu.be/sgHbC6udIqc找到它。附录 B 给出了可以在 Python 程序中使用的 Unicode 字符的完整列表。

"""Blackjack, by Al Sweigart email@protected
The classic card game also known as 21\. (This version doesn't have
splitting or insurance.)
More info at: https://en.wikipedia.org/wiki/Blackjack
This code is available at https://nostarch.com/big-book-small-python-programming
Tags: large, game, card game"""

import random, sys

# Set up the constants:
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/charactermap)
BACKSIDE = 'backside'


def main():
   print('''Blackjack, by Al Sweigart email@protected

   Rules:
     Try to get as close to 21 without going over.
     Kings, Queens, and Jacks are worth 10 points.
     Aces are worth 1 or 11 points.
     Cards 2 through 10 are worth their face value.
     (H)it to take another card.
     (S)tand to stop taking cards.
     On your first play, you can (D)ouble down to increase your bet
     but must hit exactly one more time before standing.
     In case of a tie, the bet is returned to the player.
     The dealer stops hitting at 17.''')

   money = 5000
   while True:  # Main game loop.
       # Check if the player has run out of money:
       if money <= 0:
           print("You're broke!")
           print("Good thing you weren't playing with real money.")
           print('Thanks for playing!')
           sys.exit()

       # Let the player enter their bet for this round:
       print('Money:', money)
       bet = getBet(money)

       # Give the dealer and player two cards from the deck each:
       deck = getDeck()
       dealerHand = [deck.pop(), deck.pop()]
       playerHand = [deck.pop(), deck.pop()]

       # Handle player actions:
       print('Bet:', bet)
       while True:  # Keep looping until player stands or busts.
           displayHands(playerHand, dealerHand, False)
           print()

           # Check if the player has bust:
           if getHandValue(playerHand) > 21:
               break

           # Get the player's move, either H, S, or D:
           move = getMove(playerHand, money - bet)

           # Handle the player actions:
           if move == 'D':
               # Player is doubling down, they can increase their bet:
               additionalBet = getBet(min(bet, (money - bet)))
               bet += additionalBet
               print('Bet increased to {}.'.format(bet))
               print('Bet:', bet)

           if move in ('H', 'D'):
               # Hit/doubling down takes another card.
               newCard = deck.pop()
               rank, suit = newCard
               print('You drew a {} of {}.'.format(rank, suit))
               playerHand.append(newCard)

               if getHandValue(playerHand) > 21:
                   # The player has busted:
                   continue

           if move in ('S', 'D'):
               # Stand/doubling down stops the player's turn.
               break

       # Handle the dealer's actions:
       if getHandValue(playerHand) <= 21:
           while getHandValue(dealerHand) < 17:
               # The dealer hits:
               print('Dealer hits...')
               dealerHand.append(deck.pop())
               displayHands(playerHand, dealerHand, False)

               if getHandValue(dealerHand) > 21:
                   break  # The dealer has busted.
               input('Press Enter to continue...')
               print('\n\n')

        # Show the final hands:
        displayHands(playerHand, dealerHand, True)

        playerValue = getHandValue(playerHand)
        dealerValue = getHandValue(dealerHand)
        # Handle whether the player won, lost, or tied:
        if dealerValue > 21:
            print('Dealer busts! You win ${}!'.format(bet))
            money += bet
        elif (playerValue > 21) or (playerValue < dealerValue):
            print('You lost!')
            money -= bet
        elif playerValue > dealerValue:
            print('You won ${}!'.format(bet))
            money += bet
        elif playerValue == dealerValue:
            print('It\'s a tie, the bet is returned to you.')

        input('Press Enter to continue...')
        print('\n\n')


def getBet(maxBet):
    """Ask the player how much they want to bet for this round."""
    while True:  # Keep asking until they enter a valid amount.
        print('How much do you bet? (1-{}, or QUIT)'.format(maxBet))
        bet = input('> ').upper().strip()
        if bet == 'QUIT':
            print('Thanks for playing!')
            sys.exit()

        if not bet.isdecimal():
            continue  # If the player didn't enter a number, ask again.

        bet = int(bet)
        if 1 <= bet <= maxBet:
            return bet  # Player entered a valid bet.


def getDeck():
    """Return a list of (rank, suit) tuples for all 52 cards."""
    deck = []
    for suit in (HEARTS, DIAMONDS, SPADES, CLUBS):
        for rank in range(2, 11):
            deck.append((str(rank), suit))  # Add the numbered cards.
        for rank in ('J', 'Q', 'K', 'A'):
            deck.append((rank, suit))  # Add the face and ace cards.
    random.shuffle(deck)
    return deck


def displayHands(playerHand, dealerHand, showDealerHand):
    """Show the player's and dealer's cards. Hide the dealer's first
    card if showDealerHand is False."""
    print()
    if showDealerHand:
        print('DEALER:', getHandValue(dealerHand))
        displayCards(dealerHand)
    else:
        print('DEALER: ???')
        # Hide the dealer's first card:
        displayCards([BACKSIDE] + dealerHand[1:])

    # Show the player's cards:
    print('PLAYER:', getHandValue(playerHand))
    displayCards(playerHand)


def getHandValue(cards):
    """Returns the value of the cards. Face cards are worth 10, aces are
    worth 11 or 1 (this function picks the most suitable ace value)."""
    value = 0
    numberOfAces = 0

    # Add the value for the non-ace cards:
    for card in cards:
        rank = card[0]  # card is a tuple like (rank, suit)
        if rank == 'A':
            numberOfAces += 1
        elif rank in ('K', 'Q', 'J'):  # Face cards are worth 10 points.
            value += 10
        else:
            value += int(rank)  # Numbered cards are worth their number.

    # Add the value for the aces:
    value += numberOfAces  # Add 1 per ace.
    for i in range(numberOfAces):
        # If another 10 can be added without busting, do so:
        if value + 10 <= 21:
            value += 10

    return value


def displayCards(cards):
    """Display all the cards in the cards list."""
    rows = ['', '', '', '', '']  # The text to display on each row.

    for i, card in enumerate(cards):
        rows[0] += ' ___  '  # Print the top line of the card.
        if card == BACKSIDE:
            # Print a card's back:
            rows[1] += '|## | '
            rows[2] += '|###| '
            rows[3] += '|_##| '
        else:
            # Print the card's front:
            rank, suit = card  # The card is a tuple data structure.
            rows[1] += '|{} | '.format(rank.ljust(2))
            rows[2] += '| {} | '.format(suit)
            rows[3] += '|_{}| '.format(rank.rjust(2, '_'))

    # Print each row on the screen:
    for row in rows:
        print(row)


def getMove(playerHand, money):
    """Asks the player for their move, and returns 'H' for hit, 'S' for
    stand, and 'D' for double down."""
    while True:  # Keep looping until the player enters a correct move.
        # Determine what moves the player can make:
        moves = ['(H)it', '(S)tand']

        # The player can double down on their first move, which we can
        # tell because they'll have exactly two cards:
        if len(playerHand) == 2 and money > 0:
            moves.append('(D)ouble down')

        # Get the player's move:
        movePrompt = ', '.join(moves) + '> '
        move = input(movePrompt).upper()
        if move in ('H', 'S'):
            return move  # Player has entered a valid move.
        if move == 'D' and '(D)ouble down' in moves:
            return move  # Player has entered a valid move.


# If the program is run (instead of imported), run the game:
if __name__ == '__main__':
    main() 

在输入源代码并运行几次之后,尝试对其进行实验性的修改。21 点有几个自定义规则,你可以实现。例如,如果前两张牌的价值相同,玩家可以将它们分成两只手,分别下注。此外,如果玩家的前两张牌中有一张“21 点”(黑桃 A 和 21 点),玩家将赢得十比一的奖金。你可以从en.wikipedia.org/wiki/Blackjack那里找到更多关于这个游戏的信息。

探索程序

试着找出下列问题的答案。尝试对代码进行一些修改,然后重新运行程序,看看这些修改有什么影响。

  1. 你如何让玩家以不同的金额开始游戏?
  2. 该计划如何防止玩家下注超过他们的钱?
  3. 程序如何表示单卡?
  4. 该程序如何表示一手牌?
  5. rows列表中的每个字符串(在第 197 行创建)代表什么?
  6. 如果删除或注释掉第 148 行的random.shuffle(deck)会发生什么?
  7. 如果把 112 行的money -= bet改成money += bet会怎么样?
  8. displayHands()函数中的showDealerHand设置为True时会发生什么?到了False会怎么样?

五、弹跳 DVD 标志

原文:http://inventwithpython.com/bigbookpython/project5.html

如果你到了一定的年龄,你会记得那些被称为 DVD 播放器的古老技术设备。当不播放 DVD 时,他们会显示一个从屏幕边缘反弹回来的对角线方向的 DVD 标志。这个程序通过每次碰到边缘时改变方向来模拟这个彩色的 DVD 标志。我们还将记录一个标志点击屏幕一角的次数。这创造了一个有趣的视觉动画,特别是当一个标志与一个角完美地对齐的神奇时刻。

您不能从您的集成开发环境(IDE)或编辑器运行此程序,因为它使用了bext模块。因此,必须从命令提示符或终端运行它才能正确显示。你可以在pypi.org/project/bext找到更多关于bext模块的信息。

运行示例

当你运行bouncingdvd.py时,输出将看起来像图 5-1 。

f05001

bouncingdvd.py节目的斜向移动的 DVD 标识

工作原理

你可能还记得学校数学课上的笛卡尔坐标。在编程中,x 坐标表示对象的水平位置,y 坐标表示其垂直位置,就像数学中一样。然而,与数学中不同的是,原点(0, 0)在屏幕的左上角,y 坐标随着向下移动而增加。x 坐标随着对象向右移动而增加,就像数学中一样。图 5-2 显示了屏幕的坐标系统。

f05002

:原点(0,0)在屏幕的左上方,x 和 y 坐标分别向右下递增。

bext模块的goto()函数工作方式相同:调用bext.goto(0, 0)将文本光标放在终端窗口的左上角。我们使用一个 Python 字典,用关键字'color''direction''x''y'来表示每个跳动的 DVD 标志。'x''y'的值是代表窗口中徽标位置的整数。由于这些值被传递到bext.goto(),增加它们将使徽标向右和向下移动,而减少它们将使徽标向左和向上移动。

"""Bouncing DVD Logo, by Al Sweigart email@protected
A bouncing DVD logo animation. You have to be "of a certain age" to
appreciate this. Press Ctrl-C to stop.

NOTE: Do not resize the terminal window while this program is running.
This code is available at https://nostarch.com/big-book-small-python-programming
Tags: short, artistic, bext"""

import sys, random, time

try:
   import bext
except ImportError:
   print('This program requires the bext module, which you')
   print('can install by following the instructions at')
   print('https://pypi.org/project/Bext/')
   sys.exit()

# Set up the constants:
WIDTH, HEIGHT = bext.size()
# We can't print to the last column on Windows without it adding a
# newline automatically, so reduce the width by one:
WIDTH -= 1

NUMBER_OF_LOGOS = 5  # (!) Try changing this to 1 or 100.
PAUSE_AMOUNT = 0.2  # (!) Try changing this to 1.0 or 0.0.
# (!) Try changing this list to fewer colors:
COLORS = ['red', 'green', 'yellow', 'blue', 'magenta', 'cyan', 'white']

UP_RIGHT   = 'ur'
UP_LEFT    = 'ul'
DOWN_RIGHT = 'dr'
DOWN_LEFT  = 'dl'
DIRECTIONS = (UP_RIGHT, UP_LEFT, DOWN_RIGHT, DOWN_LEFT)

# Key names for logo dictionaries:
COLOR = 'color'
X = 'x'
Y = 'y'
DIR = 'direction'


def main():
   bext.clear()

   # Generate some logos.
   logos = []
   for i in range(NUMBER_OF_LOGOS):
       logos.append({COLOR: random.choice(COLORS),
                     X: random.randint(1, WIDTH - 4),
                     Y: random.randint(1, HEIGHT - 4),
                     DIR: random.choice(DIRECTIONS)})
       if logos[-1][X] % 2 == 1:
           # Make sure X is even so it can hit the corner.
           logos[-1][X] -= 1

   cornerBounces = 0  # Count how many times a logo hits a corner.
   while True:  # Main program loop.
       for logo in logos:  # Handle each logo in the logos list.
           # Erase the logo's current location:
           bext.goto(logo[X], logo[Y])
           print('   ', end='')  # (!) Try commenting this line out.

           originalDirection = logo[DIR]

           # See if the logo bounces off the corners:
           if logo[X] == 0 and logo[Y] == 0:
               logo[DIR] = DOWN_RIGHT
               cornerBounces += 1
           elif logo[X] == 0 and logo[Y] == HEIGHT - 1:
               logo[DIR] = UP_RIGHT
               cornerBounces += 1
           elif logo[X] == WIDTH - 3 and logo[Y] == 0:
               logo[DIR] = DOWN_LEFT
               cornerBounces += 1
           elif logo[X] == WIDTH - 3 and logo[Y] == HEIGHT - 1:
               logo[DIR] = UP_LEFT
               cornerBounces += 1

           # See if the logo bounces off the left edge:
           elif logo[X] == 0 and logo[DIR] == UP_LEFT:
               logo[DIR] = UP_RIGHT
           elif logo[X] == 0 and logo[DIR] == DOWN_LEFT:
               logo[DIR] = DOWN_RIGHT

           # See if the logo bounces off the right edge:
           # (WIDTH - 3 because 'DVD' has 3 letters.)
           elif logo[X] == WIDTH - 3 and logo[DIR] == UP_RIGHT:
               logo[DIR] = UP_LEFT
           elif logo[X] == WIDTH - 3 and logo[DIR] == DOWN_RIGHT:
               logo[DIR] = DOWN_LEFT

           # See if the logo bounces off the top edge:
           elif logo[Y] == 0 and logo[DIR] == UP_LEFT:
               logo[DIR] = DOWN_LEFT
           elif logo[Y] == 0 and logo[DIR] == UP_RIGHT:
               logo[DIR] = DOWN_RIGHT

           # See if the logo bounces off the bottom edge:
            elif logo[Y] == HEIGHT - 1 and logo[DIR] == DOWN_LEFT:
                logo[DIR] = UP_LEFT
            elif logo[Y] == HEIGHT - 1 and logo[DIR] == DOWN_RIGHT:
                logo[DIR] = UP_RIGHT

            if logo[DIR] != originalDirection:
                # Change color when the logo bounces:
                logo[COLOR] = random.choice(COLORS)

            # Move the logo. (X moves by 2 because the terminal
            # characters are twice as tall as they are wide.)
            if logo[DIR] == UP_RIGHT:
                logo[X] += 2
                logo[Y] -= 1
            elif logo[DIR] == UP_LEFT:
                logo[X] -= 2
                logo[Y] -= 1
            elif logo[DIR] == DOWN_RIGHT:
                logo[X] += 2
                logo[Y] += 1
            elif logo[DIR] == DOWN_LEFT:
                logo[X] -= 2
                logo[Y] += 1

        # Display number of corner bounces:
        bext.goto(5, 0)
        bext.fg('white')
        print('Corner bounces:', cornerBounces, end='')

        for logo in logos:
            # Draw the logos at their new location:
            bext.goto(logo[X], logo[Y])
            bext.fg(logo[COLOR])
            print('DVD', end='')

        bext.goto(0, 0)

        sys.stdout.flush()  # (Required for bext-using programs.)
        time.sleep(PAUSE_AMOUNT)


# If this program was run (instead of imported), run the game:
if __name__ == '__main__':
    try:
        main()
    except KeyboardInterrupt:
        print()
        print('Bouncing DVD Logo, by Al Sweigart')
        sys.exit()  # When Ctrl-C is pressed, end the program. 

在输入源代码并运行几次之后,尝试对其进行实验性的修改。标有(!)的注释对你可以做的小改变有建议。你也可以自己想办法做到以下几点:

  • 更改NUMBER_OF_LOGOS以增加屏幕上跳跃标志的数量。
  • 更改PAUSE_AMOUNT以加快或减慢徽标的速度。

探索程序

试着找出下列问题的答案。尝试对代码进行一些修改,然后重新运行程序,看看这些修改有什么影响。

  1. 如果把第 20 行的WIDTH, HEIGHT = bext.size()改成WIDTH, HEIGHT = 10, 5会怎么样?
  2. 如果把第 52 行的DIR: random.choice(DIRECTIONS)换成DIR: DOWN_RIGHT会怎么样?
  3. 如何让'Corner bounces:'文字不出现在屏幕上?
  4. 如果删除或注释掉第 57 行的cornerBounces = 0,会得到什么错误信息?

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

询问ChatGPT的高质量答案艺术——提示工程指南(更新中……)

目录前言一、提示工程简介二、提示技巧2-1、生成法律文件2-2、添加提示技巧三、角色扮演3-1、智能手机产品描述3-2、添加角色扮演四、标准提示4-1、写一篇有关于新智能手机的评论4-2、添加标准提示、角色提示、种子词提示等等五、示例很少、或者没有示例5-1、生成一个手机配置六…

深度理解PyTorch的WeightedRandomSampler处理图像分类任务的类别不平衡问题

最近做活体检测任务&#xff0c;将其看成是一个图像二分类问题&#xff0c;然而面临的一个很大问题就是正负样本的不平衡问题&#xff0c;也就是正样本&#xff08;活体&#xff09;很多&#xff0c;而负样本&#xff08;假体&#xff09;很少&#xff0c;如何处理好数据集的类…

springboot实现邮箱验证码功能

引言 邮箱验证码是一个常见的功能&#xff0c;常用于邮箱绑定、修改密码等操作上&#xff0c;这里我演示一下如何使用springboot实现验证码的发送功能&#xff1b; 这里用qq邮箱进行演示&#xff0c;其他都差不多&#xff1b; 准备工作 首先要在设置->账户中开启邮箱POP…

ChatAudio 通过TTS + STT + GPT 实现语音对话(低仿微信聊天)

效果图什么是 STT 和 TTS&#xff1f;STT 是语音转文字&#xff08;Speech To Text&#xff09;TTS 是文字转语音&#xff08;Text To Speech&#xff09;为什么要使用 SST TTS 如果用户直接输入音频&#xff0c;OpenAI 的 API 中并没有直接使用语音和 GPT 进行对话的功能。所…

(C++)模板分离编译面对的问题

什么是分离编译模板的分离编译什么是分离编译 一个程序&#xff08;项目&#xff09;由若干个源文件共同实现&#xff0c;而每个源文件单独编译生成目标文件&#xff0c;最后将所有目标文件链接起来形成单一的可执行文件的过程称为分离编译模式。 模板的分离编译 假如有以下…

Java锁机制

Java锁机制1. 什么是锁JVM运行时内存结构2. 对象、对象头结构Mark Word中的字段3. synchronizedMonitor原理四种锁状态的由来4. 锁的4种状态4.1 无锁CAS&#xff08;Compare and Swap&#xff09;4.2 偏向锁实现原理4.3 轻量级锁如何判断线程和锁之间的绑定关系自旋4.4 重量级锁…

【计算机视觉·OpenCV】使用Haar+Cascade实现人脸检测

前言 人脸检测的目标是找出图像中所有的人脸对应的位置&#xff0c;算法的输出是人脸的外接矩形在图像中的坐标。使用 haar 特征和 cascade 检测器进行人脸检测是一种传统的方式&#xff0c;下面将给出利用 OpenCV 中的 haarcascade 进行人脸检测的代码。 程序流程 代码 impo…

摩兽Pesgo plus首发爆卖,全网关注度破亿!中国潮玩跨骑电自浪潮已至?

2023年4月11日&#xff0c;TROMOX摩兽圆满举办了“跨骑潮电&#xff0c;大有所玩”Pesgo plus新品发布会。发布会在抖音、天猫、视频号平台进行了同步直播并开启线上预定。发布会直播当晚&#xff0c;摩兽Pesgo plus即狂揽线上订单&#xff0c;全网各大平台相关话题累计热度已破…

XXL-JOB分布式任务调度平台详细介绍

一、概述 在平时的业务场景中&#xff0c;经常有一些场景需要使用定时任务&#xff0c;比如&#xff1a; 时间驱动的场景&#xff1a;某个时间点发送优惠券&#xff0c;发送短信等等。 批量处理数据&#xff1a;批量统计上个月的账单&#xff0c;统计上个月销售数据等等。 固…

用SQL语句操作oracle数据库--数据查询(上篇)

SQL操作Oracle数据库进行数据查询 Oracle 数据库是业界领先的关系型数据库管理系统之一&#xff0c;广泛应用于企业级应用和数据仓库等场景中。本篇博客将介绍如何使用 SQL 语句对 Oracle 数据库进行数据查询操作。 1.连接到数据库 在开始查询之前&#xff0c;需要使用合适的…

素材管理系统概念导入

引言 由于工作上的调整安排&#xff0c;有幸参加营销素材管理系统的产品建设工作中&#xff0c;营销宣传领域一直是我的知识盲区&#xff0c;所以素材管理系统的产品建设对我来说是个富有挑战性的工作&#xff0c;在这过程中&#xff0c;我也秉持着“好记性不如烂笔头”的原则&…

Golang每日一练(leetDay0033) 二叉树专题(2)

目录 97. 交错字符串 Interleaving String &#x1f31f;&#x1f31f; 98. 验证二叉搜索树 Validate Binary Search Tree &#x1f31f;&#x1f31f; 99. 恢复二叉搜索树 Recover Binary Search Tree &#x1f31f;&#x1f31f; &#x1f31f; 每日一练刷题专栏 &am…

中国人工智能企业CIMCAI世界前三大船公司落地,智能船公司产品20秒AI自动验箱,箱信息箱况+精确地点报备智慧港航中国人工智能企业

中国人工智能企业CIMCAI世界前三大船公司落地&#xff0c;智能船公司产品20秒AI自动验箱&#xff0c;箱信息箱况精确地点报备智慧港航。小程序全时全域自动化箱况检测信息识别&#xff0c;CIMCAI全球领先新一代集装箱管理方案&#xff0c;人工智能AI自动化箱信息识别箱况检测地…

Python 小型项目大全 21~25

二十一、DNA 可视化 原文&#xff1a;http://inventwithpython.com/bigbookpython/project21.html 脱氧核糖核酸是一种微小的分子&#xff0c;存在于我们身体的每个细胞中&#xff0c;包含着我们身体如何生长的蓝图。它看起来像一对核苷酸分子的双螺旋结构&#xff1a;鸟嘌呤、…

【跟着陈七一起学C语言】今天总结:C语言的函数相关知识

友情链接&#xff1a;专栏地址 知识总结顺序参考C Primer Plus&#xff08;第六版&#xff09;和谭浩强老师的C程序设计&#xff08;第五版&#xff09;等&#xff0c;内容以书中为标准&#xff0c;同时参考其它各类书籍以及优质文章&#xff0c;以至减少知识点上的错误&#x…

太阳能电池板AI视觉检测:不良品全程阻断,高效助力光伏扩产

2022年&#xff0c;面对复杂严峻的国内外形势&#xff0c;我国光伏行业依然实现高速增长&#xff0c;多晶硅、硅片、电池片、组件产量稳居全球首位。2023年以来&#xff0c;扩产项目已多点开花。光伏装机量天花板将不断提升&#xff0c;分布式电站占比也将逐年上升。中国光伏行…

4月软件测试面试太难,吃透这份软件测试面试笔记后,成功跳槽涨薪30K

4 月开始&#xff0c;生活工作渐渐步入正轨&#xff0c;但金三银四却没有往年顺利。昨天跟一位高级架构师的前辈聊天时&#xff0c;聊到今年的面试。有两个感受&#xff0c;一个是今年面邀的次数比往年要低不少&#xff0c;再一个就是很多面试者准备明显不足。不少候选人能力其…

python学籍管理系统

1&#xff0c;创建登陆的首页面&#xff0c;且封装起来。LoginPage.py import tkinter as tk#导入tk模块 from tkinter import messagebox#导入消息提示模块 from tkinter import messagebox from db import db #导入数据库db class LoginPage:#把整个登陆页面创建一个class类…

搭建自己的饥荒Don‘t Starve服务器-饥荒Don‘t Starve开服教程

前言 饥荒这个游戏&#xff0c;虽然首发于2016年&#xff0c;但是贵在好玩呀。和Minecraft一样&#xff0c;可玩性很高&#xff0c;并且有很多mods&#xff0c;最近和小伙伴玩的过程中&#xff0c;就想着搭建一个服务器&#xff0c;方便在主机玩家不在线时候&#xff0c;也可以…

Linux软件安装---Tomcat安装

安装Tomcat 操作步骤&#xff1a; 使用xftp上传工具将tomcat的 二进制发布包上传到Linux解压安装包&#xff0c;命令为tar -zxvf apache-tomcat*** -C /usr/local进入Tomcat的bin的启动目录&#xff0c;命令为sh startup.sh或者./startup.sh 验证Tomcat启动是否成功&#xff0…