Python 小型项目大全 6~10

news2025/6/21 1:14:16

六、凯撒密码

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

凯撒密码是朱利叶斯·凯撒使用的一种古老的加密算法。它通过将字母在字母表中移动一定的位置来加密字母。我们称移位的长度为密钥。比如,如果密钥是 3,那么A变成DB变成EC变成F,以此类推。要解密信息,你必须将加密的字母向相反的方向移动。这个程序让用户根据这个算法加密和解密信息。

在现代,凯撒密码不是很复杂,但这使它成为初学者的理想选择。Project 7 中的程序“凯撒破解”可以暴力破解所有 26 个可能的密钥来解密消息,即使你不知道原始密钥。此外,如果您使用密钥 13 对消息进行加密,凯撒密码将与项目 61 的“ROT 13 密码”相同。在en.wikipedia.org/wiki/Caesar_cipher了解更多关于凯撒密码的信息。如果你想学习一般的密码和密码破解,你可以阅读我的书《Python 密码破解指南》(NoStarch 出版社,2018)。

运行示例

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

Caesar Cipher, by Al Sweigart email@protected
Do you want to (e)ncrypt or (d)ecrypt?
> e
Please enter the key (0 to 25) to use.
> 4
Enter the message to encrypt.
> Meet me by the rose bushes tonight.
QIIX QI FC XLI VSWI FYWLIW XSRMKLX.
Full encrypted text copied to clipboard.

Caesar Cipher, by Al Sweigart email@protected
Do you want to (e)ncrypt or (d)ecrypt?
> d
Please enter the key (0 to 26) to use.
> 4
Enter the message to decrypt.
> QIIX QI FC XLI VSWI FYWLIW XSRMKLX.
MEET ME BY THE ROSE BUSHES TONIGHT.
Full decrypted text copied to clipboard.

工作原理

像大多数密码程序一样,凯撒密码的工作原理是将字符翻译成数字,对这些数字执行一些数学运算,然后将数字翻译回文本字符。在密码的上下文中,我们称这些文本字符为符号。符号可以包括字母、数字和标点符号,每个符号都被赋予一个唯一的整数。在凯撒密码程序的情况下,符号都是字母,它们的整数就是它们在SYMBOLS字符串:'ABCDEFGHIJKLMNOPQRSTUVWXYZ'中的位置。

"""Caesar Cipher, by Al Sweigart email@protected
The Caesar cipher is a shift cipher that uses addition and subtraction
to encrypt and decrypt letters.
More info at: https://en.wikipedia.org/wiki/Caesar_cipher
View this code at https://nostarch.com/big-book-small-python-projects
Tags: short, beginner, cryptography, math"""

try:
   import pyperclip  # pyperclip copies text to the clipboard.
except ImportError:
    pass  # If pyperclip is not installed, do nothing. It's no big deal.

# Every possible symbol that can be encrypted/decrypted:
# (!) You can add numbers and punctuation marks to encrypt those
# symbols as well.
SYMBOLS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'

print('Caesar Cipher, by Al Sweigart email@protected')
print('The Caesar cipher encrypts letters by shifting them over by a')
print('key number. For example, a key of 2 means the letter A is')
print('encrypted into C, the letter B encrypted into D, and so on.')
print()

# Let the user enter if they are encrypting or decrypting:
while True:  # Keep asking until the user enters e or d.
    print('Do you want to (e)ncrypt or (d)ecrypt?')
    response = input('> ').lower()
    if response.startswith('e'):
        mode = 'encrypt'
        break
    elif response.startswith('d'):
        mode = 'decrypt'
        break
    print('Please enter the letter e or d.')

# Let the user enter the key to use:
while True:  # Keep asking until the user enters a valid key.
    maxKey = len(SYMBOLS) - 1
    print('Please enter the key (0 to {}) to use.'.format(maxKey))
    response = input('> ').upper()
    if not response.isdecimal():
        continue

    if 0 <= int(response) < len(SYMBOLS):
        key = int(response)
        break

# Let the user enter the message to encrypt/decrypt:
print('Enter the message to {}.'.format(mode))
message = input('> ')

# Caesar cipher only works on uppercase letters:
message = message.upper()

# Stores the encrypted/decrypted form of the message:
translated = ''

# Encrypt/decrypt each symbol in the message:
for symbol in message:
    if symbol in SYMBOLS:
        # Get the encrypted (or decrypted) number for this symbol.
        num = SYMBOLS.find(symbol)  # Get the number of the symbol.
        if mode == 'encrypt':
            num = num + key
        elif mode == 'decrypt':
            num = num - key

        # Handle the wrap-around if num is larger than the length of
        # SYMBOLS or less than 0:
        if num >= len(SYMBOLS):
            num = num - len(SYMBOLS)
        elif num < 0:
            num = num + len(SYMBOLS)

        # Add encrypted/decrypted number's symbol to translated:
        translated = translated + SYMBOLS[num]
    else:
        # Just add the symbol without encrypting/decrypting:
        translated = translated + symbol

# Display the encrypted/decrypted string to the screen:
print(translated)

try:
    pyperclip.copy(translated)
    print('Full {}ed text copied to clipboard.'.format(mode))
except:
    pass  # Do nothing if pyperclip wasn't installed. 

在输入源代码并运行几次之后,尝试对其进行实验性的修改。标有(!)的注释对你可以做的小改变有建议。您可以通过向SYMBOLS字符串添加字符来扩展可加密的符号。

探索程序

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

  1. 如果把第 16 行的SYMBOLS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'改成SYMBOLS = 'ABC'会怎么样?
  2. 用密钥0加密一条消息会发生什么?
  3. 如果删除或注释掉第 56 行的translated = '',会得到什么错误信息?
  4. 如果删除或注释掉第 45 行的key = int(response),会得到什么错误信息?
  5. 如果把第 76 行的translated = translated + SYMBOLS[num]改成translated = translated + symbol会怎么样?

七、凯撒破解

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

这个程序可以破解来自第六个项目的用凯撒密码加密的信息,即使你不知道密钥。凯撒密码只有 26 个可能的密钥,所以计算机可以很容易地尝试所有可能的解密,并向用户显示结果。在密码学中,我们称这种技术为暴力攻击。如果你想了解更多关于密码和密码破解的知识,你可以阅读我的书《Python 密码破解指南》(NoStarch 出版社,2018)。

运行示例

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

Caesar Cipher Hacker, by Al Sweigart email@protected
Enter the encrypted Caesar cipher message to hack.
> QIIX QI FC XLI VSWI FYWLIW XSRMKLX.
Key #0: QIIX QI FC XLI VSWI FYWLIW XSRMKLX.
Key #1: PHHW PH EB WKH URVH EXVKHV WRQLJKW.
Key #2: OGGV OG DA VJG TQUG DWUJGU VQPKIJV.
Key #3: NFFU NF CZ UIF SPTF CVTIFT UPOJHIU.
Key #4: MEET ME BY THE ROSE BUSHES TONIGHT.
Key #5: LDDS LD AX SGD QNRD ATRGDR SNMHFGS.
Key #6: KCCR KC ZW RFC PMQC ZSQFCQ RMLGEFR.
`--snip--`

工作原理

请注意,这个程序中的第 20 行到第 36 行与凯撒密码程序中的第 55 行到第 78 行几乎相同。黑客程序实现了相同的解密代码,除了它是在一个for循环中实现的,这个循环为每一个可能的密钥运行代码。

不幸的是,黑客程序不够复杂,无法识别何时找到了正确的密钥。它依赖于人来读取输出,并识别哪个解密产生了原始英语(或任何被加密的书面语言)。《Python 密码破解指南》(NoStarch 出版社,2018)详细介绍了如何编写 Python 代码来检测英文消息。

"""Caesar Cipher Hacker, by Al Sweigart email@protected
This programs hacks messages encrypted with the Caesar cipher by doing
a brute force attack against every possible key.
More info at:
https://en.wikipedia.org/wiki/Caesar_cipher#Breaking_the_cipher
This code is available at https://nostarch.com/big-book-small-python-programming
Tags: tiny, beginner, cryptography, math"""

print('Caesar Cipher Hacker, by Al Sweigart email@protected')

# Let the user specify the message to hack:
print('Enter the encrypted Caesar cipher message to hack.')
message = input('> ')

# Every possible symbol that can be encrypted/decrypted:
# (This must match the SYMBOLS used when encrypting the message.)
SYMBOLS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'

for key in range(len(SYMBOLS)):  # Loop through every possible key.
    translated = ''

    # Decrypt each symbol in the message:
    for symbol in message:
        if symbol in SYMBOLS:
            num = SYMBOLS.find(symbol)  # Get the number of the symbol.
            num = num - key  # Decrypt the number.

            # Handle the wrap-around if num is less than 0:
            if num < 0:
                num = num + len(SYMBOLS)

            # Add decrypted number's symbol to translated:
            translated = translated + SYMBOLS[num]
        else:
            # Just add the symbol without decrypting:
            translated = translated + symbol

    # Display the key being tested, along with its decrypted text:
    print('Key #{}: {}'.format(key, translated)) 

在输入源代码并运行几次之后,尝试对其进行实验性的修改。请记住,存储在SYMBOLS变量中的字符串必须与生成加密文本的凯撒密码程序中的SYMBOLS变量相匹配。

探索程序

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

  1. 如果删除或注释掉第 20 行的translated = '',会得到什么错误信息?
  2. 如果把第 33 行的translated = translated + SYMBOLS[num]改成translated = translated + symbol会怎么样?
  3. 如果你在凯撒密码黑客程序中输入一条未加密的信息会发生什么?

八、日历制作器

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

这个程序为你输入的月份和年份生成可打印的月历文本文件。日期和日历在编程中是一个棘手的话题,因为有太多不同的规则来确定一个月中的天数,哪一年是闰年,以及特定日期是星期几。幸运的是,Python 的datetime模块为您处理这些细节。这个程序主要是为月历页面生成多行字符串。

运行示例

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

Calendar Maker, by Al Sweigart email@protected
Enter the year for the calendar:
> 2029
Enter the month for the calendar, 1-12:
> 12
                                  December 2029
...Sunday.....Monday....Tuesday...Wednesday...Thursday....Friday....Saturday..
+----------+----------+----------+----------+----------+----------+----------+
|25        |26        |27        |28        |29        |30        | 1        |
|          |          |          |          |          |          |          |
|          |          |          |          |          |          |          |
|          |          |          |          |          |          |          |
+----------+----------+----------+----------+----------+----------+----------+
| 2        | 3        | 4        | 5        | 6        | 7        | 8        |
|          |          |          |          |          |          |          |
|          |          |          |          |          |          |          |
|          |          |          |          |          |          |          |
+----------+----------+----------+----------+----------+----------+----------+
| 9        |10        |11        |12        |13        |14        |15        |
|          |          |          |          |          |          |          |
|          |          |          |          |          |          |          |
|          |          |          |          |          |          |          |
+----------+----------+----------+----------+----------+----------+----------+
|16        |17        |18        |19        |20        |21        |22        |
|          |          |          |          |          |          |          |
|          |          |          |          |          |          |          |
|          |          |          |          |          |          |          |
+----------+----------+----------+----------+----------+----------+----------+
|23        |24        |25        |26        |27        |28        |29        |
|          |          |          |          |          |          |          |
|          |          |          |          |          |          |          |
|          |          |          |          |          |          |          |
+----------+----------+----------+----------+----------+----------+----------+
|30        |31        | 1        | 2        | 3        | 4        | 5        |
|          |          |          |          |          |          |          |
|          |          |          |          |          |          |          |
|          |          |          |          |          |          |          |
+----------+----------+----------+----------+----------+----------+----------+

Saved to calendar_2029_12.txt

工作原理

注意,getCalendarFor()函数返回给定月份和年份的日历的一个巨大的多行字符串。在这个函数中,calText变量存储这个字符串,这个字符串添加了行、空格和日期。为了跟踪日期,currentDate变量保存了一个datetime.date()对象,通过增加或减少datetime.timedelta()对象将其设置为下一个或上一个日期。你可以通过阅读《Python 自动化指南》的第 17 章来了解 Python 的日期和时间模块,automatetheboringstuff.com/2e/chapter17

"""Calendar Maker, by Al Sweigart email@protected
Create monthly calendars, saved to a text file and fit for printing.
This code is available at https://nostarch.com/big-book-small-python-programming
Tags: short"""

import datetime

# Set up the constants:
DAYS = ('Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday',
       'Friday', 'Saturday')
MONTHS = ('January', 'February', 'March', 'April', 'May', 'June', 'July',
         'August', 'September', 'October', 'November', 'December')

print('Calendar Maker, by Al Sweigart email@protected')

while True:  # Loop to get a year from the user.
   print('Enter the year for the calendar:')
   response = input('> ')

   if response.isdecimal() and int(response) > 0:
       year = int(response)
       break

   print('Please enter a numeric year, like 2023.')
   continue

while True:  # Loop to get a month from the user.
   print('Enter the month for the calendar, 1-12:')
   response = input('> ')

   if not response.isdecimal():
       print('Please enter a numeric month, like 3 for March.')
       continue

   month = int(response)
   if 1 <= month <= 12:
       break

   print('Please enter a number from 1 to 12.')


def getCalendarFor(year, month):
   calText = ''  # calText will contain the string of our calendar.

   # Put the month and year at the top of the calendar:
   calText += (' ' * 34) + MONTHS[month - 1] + ' ' + str(year) + '\n'

   # Add the days of the week labels to the calendar:
   # (!) Try changing this to abbreviations: SUN, MON, TUE, etc.
   calText += '...Sunday.....Monday....Tuesday...Wednesday...Thursday....Friday....Saturday..\n'

   # The horizontal line string that separate weeks:
   weekSeparator = ('+----------' * 7) + '+\n'

   # The blank rows have ten spaces in between the | day separators:
   blankRow = ('|          ' * 7) + '|\n'

   # Get the first date in the month. (The datetime module handles all
   # the complicated calendar stuff for us here.)
   currentDate = datetime.date(year, month, 1)

   # Roll back currentDate until it is Sunday. (weekday() returns 6
   # for Sunday, not 0.)
   while currentDate.weekday() != 6:
       currentDate -= datetime.timedelta(days=1)

   while True:  # Loop over each week in the month.
       calText += weekSeparator

       # dayNumberRow is the row with the day number labels:
       dayNumberRow = ''
       for i in range(7):
           dayNumberLabel = str(currentDate.day).rjust(2)
           dayNumberRow += '|' + dayNumberLabel + (' ' * 8)
           currentDate += datetime.timedelta(days=1) # Go to next day.
       dayNumberRow += '|\n'  # Add the vertical line after Saturday.

       # Add the day number row and 3 blank rows to the calendar text.
       calText += dayNumberRow
       for i in range(3):  # (!) Try changing the 4 to a 5 or 10.
           calText += blankRow

       # Check if we're done with the month:
       if currentDate.month != month:
           break

   # Add the horizontal line at the very bottom of the calendar.
   calText += weekSeparator
   return calText


calText = getCalendarFor(year, month)
print(calText)  # Display the calendar.

# Save the calendar to a text file:
calendarFilename = 'calendar_{}_{}.txt'.format(year, month)
with open(calendarFilename, 'w') as fileObj:
   fileObj.write(calText)

print('Saved to ' + calendarFilename) 

在你输入代码并运行几次之后,试着从头开始重新创建这个程序,不要看这本书里的源代码。不一定要和这个程序一模一样;你可以发明你自己的版本!你也可以自己想办法做到以下几点:

  • 在一些方框内添加假日文本。
  • 为重复发生的事件在一些框中添加文本。
  • 打印一个没有方框的“迷你”日历。

探索程序

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

  1. 如何让日历显示缩写的月份?比如显示'Jan'而不是'January'
  2. 如果删除或注释掉第 21 行的year = int(response),会得到什么错误信息?
  3. 如何让日历不在顶部显示星期几?
  4. 如何让程序不将日历保存到文件中?
  5. 如果删除或注释掉第 93 行的print(calText)会怎么样?

九、盒子里的胡萝卜

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

这是两个人类玩家玩的简单而愚蠢的诈唬游戏。每个玩家都有一个盒子。一个盒子里有一根胡萝卜,每个玩家都想得到这根胡萝卜。第一个玩家看着他们的盒子,然后告诉第二个玩家他们要么有要么没有胡萝卜。第二个玩家可以决定是否交换盒子。

代码中的 ASCII 艺术画使得输入这个程序需要一些时间(虽然复制和粘贴 ASCII 艺术画可以加快任务),但是这个项目对于初学者来说是很好的,因为它很简单,循环最少,没有定义函数。

运行示例

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

Carrot in a Box, by Al Sweigart email@protected
`--snip--`
Human player 1, enter your name: Alice
Human player 2, enter your name: Bob
HERE ARE TWO BOXES:
  __________     __________
 /         /|   /         /|
+---------+ |  +---------+ |
|   RED   | |  |   GOLD  | |
|   BOX   | /  |   BOX   | /
+---------+/   +---------+/
   Alice           Bob

Alice, you have a RED box in front of you.
Bob, you have a GOLD box in front of you.
Press Enter to continue...
`--snip--`
When Bob has closed their eyes, press Enter...
Alice here is the inside of your box:

   ___VV____
  |   VV    |
  |   VV    |
  |___||____|    __________
 /    ||   /|   /         /|
+---------+ |  +---------+ |
|   RED   | |  |   GOLD  | |
|   BOX   | /  |   BOX   | /
+---------+/   +---------+/
 (carrot!)
   Alice           Bob
Press Enter to continue...
`--snip--`

工作原理

这个程序依赖于第二个玩家闭上眼睛,这样他们就看不到第一个玩家盒子里的东西。为了不让第二个玩家在这一步之后看到盒子里的内容,我们需要找到一个清空屏幕的方法。第 83 行用print('\n' * 100)做这个。这将打印 100 个换行符,导致先前打印的内容向上滚动并超出视图。这防止第二个玩家意外地看到只打算给第一个玩家的东西。虽然第二个玩家总是可以向上滚动来查看这段文字,但是对于坐在他们旁边的第一个玩家来说,这是显而易见的。

在第 114、130 和 142 行,垂直线的间距可能看起来不正确,但是程序用字符串'RED '(末尾有一个空格)或'GOLD'替换了花括号。这些字符串中的四个字符将导致框的其余垂直线与 ASCII 艺术画图像的其余部分对齐。

"""Carrot in a Box, by Al Sweigart email@protected
A silly bluffing game between two human players. Based on the game
from the show, 8 Out of 10 Cats.
This code is available at https://nostarch.com/big-book-small-python-programming
Tags: large, beginner, game, two-player"""

import random

print('''Carrot in a Box, by Al Sweigart email@protected

This is a bluffing game for two human players. Each player has a box.
One box has a carrot in it. To win, you must have the box with the
carrot in it.

This is a very simple and silly game.

The first player looks into their box (the second player must close
their eyes during this.) The first player then says "There is a carrot
in my box" or "There is not a carrot in my box". The second player then
gets to decide if they want to swap boxes or not.
''')
input('Press Enter to begin...')

p1Name = input('Human player 1, enter your name: ')
p2Name = input('Human player 2, enter your name: ')
playerNames = p1Name[:11].center(11) + '    ' + p2Name[:11].center(11)

print('''HERE ARE TWO BOXES:
 __________     __________
/         /|   /         /|
+---------+ |  +---------+ |
|   RED   | |  |   GOLD  | |
|   BOX   | /  |   BOX   | /
+---------+/   +---------+/''')

print()
print(playerNames)
print()
print(p1Name + ', you have a RED box in front of you.')
print(p2Name + ', you have a GOLD box in front of you.')
print()
print(p1Name + ', you will get to look into your box.')
print(p2Name.upper() + ', close your eyes and don\'t look!!!')
input('When ' + p2Name + ' has closed their eyes, press Enter...')
print()

print(p1Name + ' here is the inside of your box:')

if random.randint(1, 2) == 1:
   carrotInFirstBox = True
else:
   carrotInFirstBox = False

if carrotInFirstBox:
   print('''
  ___VV____
 |   VV    |
 |   VV    |
 |___||____|    __________
/    ||   /|   /         /|
+---------+ |  +---------+ |
|   RED   | |  |   GOLD  | |
|   BOX   | /  |   BOX   | /
+---------+/   +---------+/
(carrot!)''')
   print(playerNames)
else:
   print('''
  _________
 |         |
 |         |
 |_________|    __________
/         /|   /         /|
+---------+ |  +---------+ |
|   RED   | |  |   GOLD  | |
|   BOX   | /  |   BOX   | /
+---------+/   +---------+/
(no carrot!)''')
   print(playerNames)

input('Press Enter to continue...')

print('\n' * 100)  # Clear the screen by printing several newlines.
print(p1Name + ', tell ' + p2Name + ' to open their eyes.')
input('Press Enter to continue...')

print()
print(p1Name + ', say one of the following sentences to ' + p2Name + '.')
print('  1) There is a carrot in my box.')
print('  2) There is not a carrot in my box.')
print()
input('Then press Enter to continue...')

print()
print(p2Name + ', do you want to swap boxes with ' + p1Name + '? YES/NO')
while True:
   response = input('> ').upper()
   if not (response.startswith('Y') or response.startswith('N')):
       print(p2Name + ', please enter "YES" or "NO".')
    else:
        break

firstBox = 'RED '  # Note the space after the "D".
secondBox = 'GOLD'

if response.startswith('Y'):
    carrotInFirstBox = not carrotInFirstBox
    firstBox, secondBox = secondBox, firstBox

print('''HERE ARE THE TWO BOXES:
  __________     __________
 /         /|   /         /|
+---------+ |  +---------+ |
| {} | |  | {} | |
|   BOX   | /  |   BOX   | /
+---------+/   +---------+/'''.format(firstBox, secondBox))
print(playerNames)

input('Press Enter to reveal the winner...')
print()

if carrotInFirstBox:
    print('''
   ___VV____      _________
  |   VV    |    |         |
  |   VV    |    |         |
  |___||____|    |_________|
 /    ||   /|   /         /|
+---------+ |  +---------+ |
| {} | |  | {} | |
|   BOX   | /  |   BOX   | /
+---------+/   +---------+/'''.format(firstBox, secondBox))

else:
    print('''
   _________      ___VV____
  |         |    |   VV    |
  |         |    |   VV    |
  |_________|    |___||____|
 /         /|   /    ||   /|
+---------+ |  +---------+ |
| {} | |  | {} | |
|   BOX   | /  |   BOX   | /
+---------+/   +---------+/'''.format(firstBox, secondBox))

print(playerNames)

# This modification made possible through the 'carrotInFirstBox variable
if carrotInFirstBox:
    print(p1Name + ' is the winner!')
else:
    print(p2Name + ' is the winner!')

print('Thanks for playing!') 

在输入源代码并运行几次之后,尝试对其进行实验性的修改。你也可以自己想办法做到以下几点:

  • 把盒子和胡萝卜的 ASCII 艺术画改成更华丽的。
  • 加一句“还想再玩一次吗?”让玩家在保持得分的同时再次游戏的功能。
  • 添加第三名玩家,第二名玩家必须向其诈牌。

探索程序

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

  1. 注意,第 26 行有代码p1Name[:11]p2Name[:11]。请输入超过 11 个字母的名称。你注意到程序是如何显示这个名字的吗?
  2. 如果省略第 103 行firstBox = 'RED '末尾的空格会怎么样?
  3. 如果删除或注释掉第 83 行的print('\n' * 100)会怎么样?
  4. 如果删除或注释掉第 100 行的else:和第 101 行的break,会发生什么?

十、乔汉

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

乔汉是日本封建时代赌场里玩的一种骰子游戏。两个六面骰子在一个杯子里滚动,赌客必须猜和是偶数(乔)还是奇数(汉)。赌场从所有赢款中抽取一小部分。简单的随机数生成和用于确定奇数或偶数和的基本数学使得这个项目特别适合初学者。更多关于赵晗的信息可以在en.wikipedia.org/wiki/Cho-han找到。

运行示例

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

Cho-Han, by Al Sweigart email@protected

In this traditional Japanese dice game, two dice are rolled in a bamboo
cup by the dealer sitting on the floor. The player must guess if the
dice total to an even (cho) or odd (han) number.

You have 5000 mon. How much do you bet? (or QUIT)
> 400
The dealer swirls the cup and you hear the rattle of dice.
The dealer slams the cup on the floor, still covering the
dice and asks for your bet.

    CHO (even) or HAN (odd)?
> cho
The dealer lifts the cup to reveal:
   GO - GO
     5 - 5
You won! You take 800 mon.
The house collects a 40 mon fee.
`--snip--`

工作原理

random.randint(1, 6)调用返回一个在16之间的随机整数,非常适合表示六面骰子。但是,我们还需要显示数字一到六的日语单词。我们有一个字典,存储在JAPANESE_NUMBERS中,将整数16映射到日语单词的字符串,而不是有一个if语句后跟五个elif语句。这就是第 57 行的JAPANESE_NUMBERS[dice1]JAPANESE_NUMBERS[dice2]如何在一行代码中显示骰子结果的日语单词。

"""Cho-Han, by Al Sweigart email@protected
The traditional Japanese dice game of even-odd.
View this code athttps://nostarch.com/big-book-small-python-projects
Tags: short, beginner, game"""

import random, sys

JAPANESE_NUMBERS = {1: 'ICHI', 2: 'NI', 3: 'SAN',
                   4: 'SHI', 5: 'GO', 6: 'ROKU'}

print('''Cho-Han, by Al Sweigart email@protected

In this traditional Japanese dice game, two dice are rolled in a bamboo
cup by the dealer sitting on the floor. The player must guess if the
dice total to an even (cho) or odd (han) number.
''')

purse = 5000
while True:  # Main game loop.
    # Place your bet:
    print('You have', purse, 'mon. How much do you bet? (or QUIT)')
    while True:
        pot = input('> ')
        if pot.upper() == 'QUIT':
            print('Thanks for playing!')
            sys.exit()
        elif not pot.isdecimal():
            print('Please enter a number.')
        elif int(pot) > purse:
            print('You do not have enough to make that bet.')
        else:
            # This is a valid bet.
            pot = int(pot)  # Convert pot to an integer.
            break  # Exit the loop once a valid bet is placed.

    # Roll the dice.
    dice1 = random.randint(1, 6)
    dice2 = random.randint(1, 6)

    print('The dealer swirls the cup and you hear the rattle of dice.')
    print('The dealer slams the cup on the floor, still covering the')
    print('dice and asks for your bet.')
    print()
    print('    CHO (even) or HAN (odd)?')

    # Let the player bet cho or han:
    while True:
        bet = input('> ').upper()
        if bet != 'CHO' and bet != 'HAN':
            print('Please enter either "CHO" or "HAN".')
            continue
        else:
            break

    # Reveal the dice results:
    print('The dealer lifts the cup to reveal:')
    print('  ', JAPANESE_NUMBERS[dice1], '-', JAPANESE_NUMBERS[dice2])
    print('    ', dice1, '-', dice2)

    # Determine if the player won:
    rollIsEven = (dice1 + dice2) % 2 == 0
    if rollIsEven:
        correctBet = 'CHO'
    else:
        correctBet = 'HAN'

    playerWon = bet == correctBet

    # Display the bet results:
    if playerWon:
        print('You won! You take', pot, 'mon.')
        purse = purse + pot  # Add the pot from player's purse.
        print('The house collects a', pot // 10, 'mon fee.')
        purse = purse - (pot // 10)  # The house fee is 10%.
    else:
        purse = purse - pot  # Subtract the pot from player's purse.
        print('You lost!')

    # Check if the player has run out of money:
    if purse == 0:
        print('You have run out of money!')
        print('Thanks for playing!')
        sys.exit() 

在输入源代码并运行几次之后,尝试对其进行实验性的修改。你也可以自己想办法做到以下几点:

  • 实现这个游戏的一个变种,在维基百科的文章中有描述,多个玩家互相打赌。添加电脑控制的赌徒,他们有自己的钱包来玩。
  • 为某些掷骰增加额外奖励,如 7 或蛇眼。
  • 允许玩家在特定的数字上下注,以获得奖金。

探索程序

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

  1. 你如何让玩家以不同的金额开始游戏?
  2. 该计划如何防止玩家下注超过他们的钱?
  3. 程序如何知道两个骰子的和是偶数还是奇数?
  4. 如果把第 37 行的random.randint(1, 6)改成random.randint(1, 1)会怎么样?
  5. 把 73 行(不是 74 行)的pot // 10改成0,房子还收 10%的费用吗?
  6. 如果删除或注释掉第 80、81、82 和 83 行会发生什么?

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

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

相关文章

Linux-初学者系列——篇幅2_系统命令界面

系统命令界面-目录一、命令行提示符1、提示符2、提示符组成3、提示符修改二、系统命令语法规范三、系统命令行常用快捷键1、常用快捷键2、移动光标快捷键3、剪切、粘贴、清楚快捷键4、系统管理控制快捷键5、重复执行命令快捷键上篇: Linux-初学者系列——篇幅1_文件管理命令 一…

Python 小型项目大全 36~40

三十六、沙漏 原文&#xff1a;http://inventwithpython.com/bigbookpython/project36.html 这个可视化程序有一个粗糙的物理引擎&#xff0c;模拟沙子通过沙漏的小孔落下。沙子堆积在沙漏的下半部分&#xff1b;然后把沙漏翻过来&#xff0c;重复这个过程。 运行示例 图 36-…

手写vuex4源码(八)插件机制实现

一、插件的使用 Vuex 不仅提供了全局状态管理能力&#xff0c;还进一步提供了插件机制&#xff0c;便于开发者对 Vuex 插件进行增强&#xff1b; Vuex 插件的使用方式&#xff1a;通过 Store 类提供的 plugin 数组进行 Vuex 插件注册&#xff1a; export default createStor…

ModuleNotFoundError:No module named “te_fusion“

Asecend Tensor Compiler简称ATC&#xff0c;昇腾张量编译器&#xff0c;主要是将开源框架的网络模型或Ascend IR定义的单算子描述文件(json格式)转换为昇腾AI处理器支持的om格式 场景描述:ONNXRuntime调用CANN后端执行时&#xff0c;报了没有找到te_fusion的error&#xff0c…

多项式特征应用案例

多项式特征应用案例 描述 对于线性模型而言&#xff0c;扩充数据的特征&#xff08;即对原特征进行计算&#xff0c;增加新的特征列&#xff09;通常是提升模型表现的可选方法&#xff0c;Scikit-learn提供了PolynomialFeatures类来增加多项式特征&#xff08;polynomial fea…

JavaScript【一】JavaScript变量与数据类型

文章目录&#x1f31f;前言&#x1f31f;变量&#x1f31f; 变量是什么&#xff1f;&#x1f31f; 变量提升&#x1f31f; 声明变量&#x1f31f; JavaScript有三种声明方式&#x1f31f; 命名规范&#x1f31f; 注意&#x1f31f;数据类型以及运算&#x1f31f; 检测变量数据类…

【Linux】System V IPC-命名管道共享内存消息队列

System V IPC-命名管道&共享内存&消息队列命名管道共享内存创建共享内存附加和分离共享内存消息队列消息队列的接口命名管道 使用mkfifo命令&#xff0c;创建一个命名管道&#xff0c;通过ll可以查看当前命名管道的类型 p类型&#xff0c;也就是pipe管道类型。 之前我…

Docker镜像之Docker Compose讲解

文章目录1 docker-compose1.1 compose编排工具简介1.2 安装docker-compose1.3 编排启动镜像1.4 haproxy代理后端docker容器1.5 安装socat 直接操作socket控制haproxy1.6 compose中yml 配置指令参考1.6.1 简单命令1.6.2 build1.6.3 depends_on1.6.4 deploy1.6.5 logging1.6.6 ne…

【C++进阶】01:概述

概述 OVERVIEW概述C11新特性&#xff1a;C14新特性&#xff1a;C17新特性&#xff1a;C20新特性&#xff1a;C程序编译过程C内存模型CSTL1.Queue&Stack2.String3.MapC语言C语言面向过程编程✅✅面向对象编程&#xff08;类和对象&#xff09;❌✅泛型编程、元编程&#xff…

基于PaddlePaddle的图片分类实战 | 深度学习基础任务教程系列

图像相比文字能够提供更加生动、容易理解及更具艺术感的信息&#xff0c;图像分类是根据图像的语义信息将不同类别图像区分开来&#xff0c;是图像检测、图像分割、物体跟踪、行为分析等其他高层视觉任务的基础。图像分类在安防、交通、互联网、医学等领域有着广泛的应用。 一般…

LeetCode:77. 组合——回溯法,是暴力法?

&#x1f34e;道阻且长&#xff0c;行则将至。&#x1f353; &#x1f33b;算法&#xff0c;不如说它是一种思考方式&#x1f340;算法专栏&#xff1a; &#x1f449;&#x1f3fb;123 一、&#x1f331;77. 组合 题目描述&#xff1a;给定两个整数 n 和 k&#xff0c;返回范…

风场数据抓取程序实现(java+python实现)

一、数据源参数定义 关键参数代码&#xff1a; package com.grab.catchWindData.pram;/*** ClassName: DevPrams* Description: TODO**/ public class DevPrams {public static String lev_0to0p1_m_below_ground "lev_0-0.1_m_below_ground";public static Stri…

【微服务笔记08】微服务组件之Hystrix实现请求合并功能

这篇文章&#xff0c;主要介绍微服务组件之Hystrix实现请求合并功能。 目录 一、Hystrix请求合并 1.1、什么是请求合并 1.2、请求合并的实现 &#xff08;1&#xff09;引入依赖 &#xff08;2&#xff09;编写服务提供者 &#xff08;3&#xff09;消费者&#xff08;Se…

React | 认识React开发

✨ 个人主页&#xff1a;CoderHing &#x1f5a5;️ Node.js专栏&#xff1a;Node.js 初级知识 &#x1f64b;‍♂️ 个人简介&#xff1a;一个不甘平庸的平凡人&#x1f36c; &#x1f4ab; 系列专栏&#xff1a;吊打面试官系列 16天学会Vue 11天学会React Node专栏 &#x…

【分享】免梯子的GPT,玩 ChatGPT 的正确姿势

火了一周的 ChatGPT&#xff0c;HG 不允许还有小伙伴不知道这个东西是什么&#xff1f;简单来说就是&#xff0c;你可以让它扮演任何事物&#xff0c;据说已经有人用它开始了颜色文学创作。因为它太火了&#xff0c;所以&#xff0c;本周特推在几十个带有“chatgpt”的项目中选…

双交叉注意学习用于细粒度视觉分类和目标重新识别

目录Dual Cross-Attention Learning for Fine-Grained Visual Categorization and Object Re-Identification摘要本文方法消融实验Dual Cross-Attention Learning for Fine-Grained Visual Categorization and Object Re-Identification 摘要 目的&#xff1a; 探索了如何扩展…

JDK8——新增时间类、有关时间数据的交互问题

目录 一、实体类 二、数据库 三、数据交换 四、关于LocalDateTime类型 (java 8) 4.1 旧版本日期时间问题 4.2 新版日期时间API介绍 4.2.1 LocalDate、LocalTime、LocalDateTime 4.2.2 日期时间的修改与比较 4.2.3 格式化和解析操作 4.2.4 Instant: 时间戳 4.2.5 Duration 与…

Doris(6):数据导入(Load)之Stream Load

Broker load是一个同步的导入方式&#xff0c;用户通过发送HTTP协议将本地文件或者数据流导入到Doris中&#xff0c;Stream Load同步执行导入并返回结果&#xff0c;用户可以通过返回判断导入是否成功。 1 适用场景 Stream load 主要适用于导入本地文件&#xff0c;或通过程序…

小厂实习要不要去?

大家好&#xff0c;我是帅地。 最近暑假实习招聘&#xff0c;不少 训练营 学员都拿到了小厂实习来保底&#xff0c;但是很多小厂基本要求一周内给答复&#xff0c;中大厂就还在流程之中&#xff0c;所以很纠结小厂实习要不要去。 不知道你是否有这样的纠结&#xff0c;今天帅地…

【测试面试汇总2】

目录Linux操作系统1.Linux操作命令2.在Linux中find和grep的区别&#xff1f;3.绝对路径用什么符号表示&#xff1f;4.当前目录、上层目录用什么表示&#xff1f;5.主目录用什么表示&#xff1f;6.怎么查看进程信息&#xff1f;7.保存文件并退出vi 编辑?8.怎么查看当前用户id&a…