Python 小型项目大全 66~70

article/2025/11/6 18:27:29

六十六、简单替换密码

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

简单替换密码用一个字母代替另一个字母。由于字母A有 26 种可能的替换,B有 25 种可能的替换,C有 24 种可能的替换,等等,所以可能的键的总数是26 × 25 × 24 × 23 × ... × 1,即 403291461126605635584000000 个密钥!对于一台超级计算机来说,这对于暴力破解来说太多了,所以项目 7“凯撒破解”中使用的密码破解方法不能用于对抗简单的密码。不幸的是,狡猾的攻击者可以利用已知的弱点来破解代码。如果你想了解更多关于密码和密码破解的知识,你可以阅读我的书《Python 密码破解指南》(NoStarch 出版社,2018)。

运行示例

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

Simple Substitution Cipher, by Al Sweigart
A simple substitution cipher has a one-to-one translation for each
symbol in the plaintext and each symbol in the ciphertext.
Do you want to (e)ncrypt or (d)ecrypt?
> e
Please specify the key to use.
Or enter RANDOM to have one generated for you.
> random
The key is WNOMTRCEHDXBFVSLKAGZIPYJQU. KEEP THIS SECRET!
Enter the message to encrypt.
> Meet me by the rose bushes tonight.
The encrypted message is:
Fttz ft nq zet asgt nigetg zsvhcez.
Full encrypted text copied to clipboard.Simple Substitution Cipher, by Al Sweigart
A simple substitution cipher has a one-to-one translation for each
symbol in the plaintext and each symbol in the ciphertext.
Do you want to (e)ncrypt or (d)ecrypt?
> d
Please specify the key to use.
> WNOMTRCEHDXBFVSLKAGZIPYJQU
Enter the message to decrypt.
> Fttz ft nq zet asgt nigetg zsvhcez.
The decrypted message is:
Meet me by the rose bushes tonight.
Full decrypted text copied to clipboard.

工作原理

密钥的 26 个字母中的每一个的位置对应于字母表中相同位置的字母:

f66001

:字母表中的字母如何用一个以WNOM开头的密钥加密。若要解密,请将底部的字母替换为上面相应的字母。

用这个密钥,字母A加密到W (而W解密到A,字母B加密到N,以此类推。LETTERSkey变量被分配给charsAcharsB(或者在解密时反过来)。用charsB中的相应字符替换charsA中的任何消息字符,以产生最终翻译的消息。

"""Simple Substitution Cipher, by Al Sweigart email@protected
A simple substitution cipher has a one-to-one translation for each
symbol in the plaintext and each symbol in the ciphertext.
More info at: https://en.wikipedia.org/wiki/Substitution_cipher
This code is available at https://nostarch.com/big-book-small-python-programming
Tags: short, cryptography, math"""import randomtry: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:
LETTERS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'def main():print('''Simple Substitution Cipher, by Al Sweigart
A simple substitution cipher has a one-to-one translation for each
symbol in the plaintext and each symbol in the ciphertext.''')# Let the user specify 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'):myMode = 'encrypt'breakelif response.startswith('d'):myMode = 'decrypt'breakprint('Please enter the letter e or d.')# Let the user specify the key to use:while True:  # Keep asking until the user enters a valid key.print('Please specify the key to use.')if myMode == 'encrypt':print('Or enter RANDOM to have one generated for you.')response = input('> ').upper()if response == 'RANDOM':myKey = generateRandomKey()print('The key is {}. KEEP THIS SECRET!'.format(myKey))breakelse:if checkKey(response):myKey = responsebreak# Let the user specify the message to encrypt/decrypt:print('Enter the message to {}.'.format(myMode))myMessage = input('> ')# Perform the encryption/decryption:if myMode == 'encrypt':translated = encryptMessage(myMessage, myKey)elif myMode == 'decrypt':translated = decryptMessage(myMessage, myKey)# Display the results:print('The %sed message is:' % (myMode))print(translated)try:pyperclip.copy(translated)print('Full %sed text copied to clipboard.' % (myMode))except:pass  # Do nothing if pyperclip wasn't installed.def checkKey(key):"""Return True if key is valid. Otherwise return False."""keyList = list(key)lettersList = list(LETTERS)keyList.sort()lettersList.sort()if keyList != lettersList:print('There is an error in the key or symbol set.')return Falsereturn Truedef encryptMessage(message, key):"""Encrypt the message using the key."""return translateMessage(message, key, 'encrypt')def decryptMessage(message, key):"""Decrypt the message using the key."""return translateMessage(message, key, 'decrypt')def translateMessage(message, key, mode):"""Encrypt or decrypt the message using the key."""translated = ''charsA = LETTERScharsB = keyif mode == 'decrypt':# For decrypting, we can use the same code as encrypting. We# just need to swap where the key and LETTERS strings are used.charsA, charsB = charsB, charsA# Loop through each symbol in the message:for symbol in message:if symbol.upper() in charsA:# Encrypt/decrypt the symbol:symIndex = charsA.find(symbol.upper())if symbol.isupper():translated += charsB[symIndex].upper()else:translated += charsB[symIndex].lower()else:# The symbol is not in LETTERS, just add it unchanged.translated += symbolreturn translateddef generateRandomKey():"""Generate and return a random encryption key."""key = list(LETTERS)  # Get a list from the LETTERS string.random.shuffle(key)  # Randomly shuffle the list.return ''.join(key)  # Get a string from the list.# If this program was run (instead of imported), run the program:
if __name__ == '__main__':main() 

探索程序

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

  1. 如果删除或注释掉第 122 行的random.shuffle(key)并输入密钥RANDOM会发生什么?
  2. 如果将第 16 行的LETTERS字符串扩展成'ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890'会发生什么?

六十七、正弦消息

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

当文本向上滚动时,这个程序以波浪形显示用户选择的消息。它用实现三角正弦波函数的math.sin()来实现这个效果。但是即使你不懂数学,这个程序也很短,很容易复制。

运行示例

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

Sine Message, by Al Sweigart email@protected
(Press Ctrl-C to quit.)What message do you want to display? (Max 39 chars.)
> I <3 Programming!I <3 Programming!I <3 Programming!I <3 Programming!I <3 Programming!I <3 Programming!I <3 Programming!I <3 Programming!I <3 Programming!I <3 Programming!I <3 Programming!I <3 Programming!I <3 Programming!I <3 Programming!I <3 Programming!I <3 Programming!I <3 Programming!I <3 Programming!I <3 Programming!
I <3 Programming!
I <3 Programming!I <3 Programming!I <3 Programming!I <3 Programming!
`--snip--`

工作原理

Python 的math模块中的math.sin()函数接受一个参数,我们称之为x,并返回另一个数字,称为x正弦值。一些数学应用使用正弦函数;在我们的程序中,它的目的仅仅是创建一个整洁的波浪效果。我们将名为step的变量传递给math.sin()。该变量从0开始,在主程序循环的每次迭代中增加0.25

我们将使用math.sin()的返回值来计算我们应该在用户消息的两边打印多少空格的填充。由于math.sin()返回一个在-1.01.0之间的浮点数,但是我们想要的最小填充量是零,而不是负值,所以第 31 行在math.sin()的返回值上加上1,使得有效范围从0.02.0。我们当然需要不止 0 到 2 个空格,所以第 31 行将这个数字乘以一个名为multiplier的变量来增加填充量。这个乘积就是在打印用户消息之前要添加到左侧的空格数。

结果就是你运行程序时看到的挥动的信息动画。

"""Sine Message, by Al Sweigart email@protected
Create a sine-wavy message.
This code is available at https://nostarch.com/big-book-small-python-programming
Tags: tiny, artistic"""import math, shutil, sys, time# Get the size of the terminal window:
WIDTH, HEIGHT = shutil.get_terminal_size()
# We can't print to the last column on Windows without it adding a
# newline automatically, so reduce the width by one:
WIDTH -= 1print('Sine Message, by Al Sweigart email@protected')
print('(Press Ctrl-C to quit.)')
print()
print('What message do you want to display? (Max', WIDTH // 2, 'chars.)')
while True:message = input('> ')if 1 <= len(message) <= (WIDTH // 2):breakprint('Message must be 1 to', WIDTH // 2, 'characters long.')step = 0.0  # The "step" determines how far into the sine wave we are.
# Sine goes from -1.0 to 1.0, so we need to change it by a multiplier:
multiplier = (WIDTH - len(message)) / 2
try:while True:  # Main program loop.sinOfStep = math.sin(step)padding = ' ' * int((sinOfStep + 1) * multiplier)print(padding + message)time.sleep(0.1)step += 0.25  # (!) Try changing this to 0.1 or 0.5.
except KeyboardInterrupt:sys.exit()  # When Ctrl-C is pressed, end the program. 

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

探索程序

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

  1. 如果把第 30 行的math.sin(step)改成math.cos(step)会怎么样?
  2. 如果把第 30 行的math.sin(step)改成math.sin(0)会怎么样?

六十八、滑动谜题

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

这个经典的难题依赖于一个4 × 4的板子,有 15 个编号的瓷砖和一个自由空间。目标是滑动瓷砖,直到数字按正确的顺序排列,从左到右,从上到下。瓷砖只能滑动;不允许你直接拿起来重新排列。这个益智玩具的一些版本的特点是混乱的图像,一旦解决就形成一个完整的图片。

更多关于滑动谜题的信息可以在en.wikipedia.org/wiki/Sliding_puzzle找到。

运行示例

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

Sliding Tile Puzzle, by Al Sweigart email@protectedUse the WASD keys to move the tilesback into their original order:1  2  3  45  6  7  89 10 11 1213 14 15
Press Enter to begin...+------+------+------+------+
|      |      |      |      |
|  5   |  10  |      |  11  |
|      |      |      |      |
+------+------+------+------+
|      |      |      |      |
|  6   |  3   |  7   |  2   |
|      |      |      |      |
+------+------+------+------+
|      |      |      |      |
|  14  |  1   |  15  |  8   |
|      |      |      |      |
+------+------+------+------+
|      |      |      |      |
|  9   |  13  |  4   |  12  |
|      |      |      |      |
+------+------+------+------+(W)
Enter WASD (or QUIT): (A) ( ) (D)
> w+------+------+------+------+
|      |      |      |      |
|  5   |  10  |  7   |  11  |
|      |      |      |      |
+------+------+------+------+
|      |      |      |      |
|  6   |  3   |      |  2   |
|      |      |      |      |
+------+------+------+------+
|      |      |      |      |
|  14  |  1   |  15  |  8   |
|      |      |      |      |
+------+------+------+------+
|      |      |      |      |
|  9   |  13  |  4   |  12  |
|      |      |      |      |
+------+------+------+------+(W)
Enter WASD (or QUIT): (A) (S) (D)
`--snip--`

工作原理

表示滑动瓦片游戏板的数据结构是列表的列表。每个内部列表代表4 × 4棋盘的一列,并包含编号方块的字符串(或代表空白空间的BLANK字符串)。getNewBoard()函数返回列表的列表,所有的图块都在它们的起始位置,在右下角有一个空格。

Python 可以用类似于a, b = b, a的语句交换两个变量的值。该程序在第 101 到 108 行使用这种技术来交换空白空间和相邻的图块,并模拟将编号的图块滑入空白空间。getNewPuzzle()函数通过随机执行 200 次这样的交换来生成新的谜题。

"""Sliding Tile Puzzle, by Al Sweigart email@protected
Slide the numbered tiles into the correct order.
This code is available at https://nostarch.com/big-book-small-python-programming
Tags: large, game, puzzle"""import random, sysBLANK = '  '  # Note: This string is two spaces, not one.def main():print('''Sliding Tile Puzzle, by Al Sweigart email@protectedUse the WASD keys to move the tilesback into their original order:1  2  3  45  6  7  89 10 11 1213 14 15   ''')input('Press Enter to begin...')gameBoard = getNewPuzzle()while True:displayBoard(gameBoard)playerMove = askForPlayerMove(gameBoard)makeMove(gameBoard, playerMove)if gameBoard == getNewBoard():print('You won!')sys.exit()def getNewBoard():"""Return a list of lists that represents a new tile puzzle."""return [['1 ', '5 ', '9 ', '13'], ['2 ', '6 ', '10', '14'],['3 ', '7 ', '11', '15'], ['4 ', '8 ', '12', BLANK]]def displayBoard(board):"""Display the given board on the screen."""labels = [board[0][0], board[1][0], board[2][0], board[3][0],board[0][1], board[1][1], board[2][1], board[3][1],board[0][2], board[1][2], board[2][2], board[3][2],board[0][3], board[1][3], board[2][3], board[3][3]]boardToDraw = """
+------+------+------+------+
|      |      |      |      |
| {} | {} | {} | {} |
|      |      |      |      |
+------+------+------+------+
|      |      |      |      |
| {} | {} | {} | {} |
|      |      |      |      |
+------+------+------+------+
|      |      |      |      |
| {} | {} | {} | {} |
|      |      |      |      |
+------+------+------+------+
|      |      |      |      |
| {} | {} | {} | {} |
|      |      |      |      |
+------+------+------+------+
""".format(*labels)print(boardToDraw)def findBlankSpace(board):"""Return an (x, y) tuple of the blank space's location."""for x in range(4):for y in range(4):if board[x][y] == '  ':return (x, y)def askForPlayerMove(board):"""Let the player select a tile to slide."""blankx, blanky = findBlankSpace(board)w = 'W' if blanky != 3 else ' 'a = 'A' if blankx != 3 else ' 's = 'S' if blanky != 0 else ' 'd = 'D' if blankx != 0 else ' 'while True:print('                          ({})'.format(w))print('Enter WASD (or QUIT): ({}) ({}) ({})'.format(a, s, d))response = input('> ').upper()if response == 'QUIT':sys.exit()if response in (w + a + s + d).replace(' ', ''):return responsedef makeMove(board, move):"""Carry out the given move on the given board."""# Note: This function assumes that the move is valid.bx, by = findBlankSpace(board)if move == 'W':board[bx][by], board[bx][by+1] = board[bx][by+1], board[bx][by]elif move == 'A':board[bx][by], board[bx+1][by] = board[bx+1][by], board[bx][by]elif move == 'S':board[bx][by], board[bx][by-1] = board[bx][by-1], board[bx][by]elif move == 'D':board[bx][by], board[bx-1][by] = board[bx-1][by], board[bx][by]def makeRandomMove(board):"""Perform a slide in a random direction."""blankx, blanky = findBlankSpace(board)validMoves = []if blanky != 3:validMoves.append('W')if blankx != 3:validMoves.append('A')if blanky != 0:validMoves.append('S')if blankx != 0:validMoves.append('D')makeMove(board, random.choice(validMoves))def getNewPuzzle(moves=200):"""Get a new puzzle by making random slides from a solved state."""board = getNewBoard()for i in range(moves):makeRandomMove(board)return board# If this program was run (instead of imported), run the game:
if __name__ == '__main__':main() 

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

  • 创建一个更困难的5 × 5变种的滑动瓷砖谜题。
  • 创建一个“自动解决”模式,保存当前的瓷砖排列,然后尝试多达 40 个随机移动和停止,如果他们已经解决了难题。否则,谜题将加载保存的状态,并尝试另外 40 次随机移动。

探索程序

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

  1. 如果把第 22 行的getNewPuzzle()改成getNewPuzzle(1)会怎么样?
  2. 如果把第 22 行的getNewPuzzle()改成getNewPuzzle(0)会怎么样?
  3. 如果删除或注释掉第 31 行的sys.exit()会发生什么?

六十九、蜗牛赛跑

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

你将无法承受这些比赛的快节奏刺激。。。蜗牛。但是他们在速度上的不足被 ASCII 艺术画的可爱所弥补。每只蜗牛(由贝壳的@字符和两只眼柄的v字符代表)缓慢但坚定地向终点线移动。多达八只蜗牛,每只都有一个自定义的名字,可以互相比赛,在它们身后留下一条黏液痕迹。这个程序适合初学者。

运行示例

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

Snail Race, by Al Sweigart email@protected@v <-- snailHow many snails will race? Max: 8
> 3
Enter snail #1's name:
> Alice
Enter snail #2's name:
> Bob
Enter snail #3's name:
> Carol
START                                   FINISH
|                                       |Alice
email@protectedBob
email@protectedCarol
email@protected
`--snip--`

工作原理

这个程序使用两个数据结构,存储在两个变量中:snailNames是每个蜗牛名字的字符串列表,snailProgress是一个字典,它的关键字是蜗牛的名字,其值是表示蜗牛移动了多少个空格的整数。第 79 到 82 行读取这两个变量中的数据,在屏幕的适当位置画出蜗牛。

"""Snail Race, by Al Sweigart email@protected
Fast-paced snail racing action!
This code is available at https://nostarch.com/big-book-small-python-programming
Tags: short, artistic, beginner, game, multiplayer"""import random, time, sys# Set up the constants:
MAX_NUM_SNAILS = 8
MAX_NAME_LENGTH = 20
FINISH_LINE = 40  # (!) Try modifying this number.print('''Snail Race, by Al Sweigart email@protected@v <-- snail''')# Ask how many snails to race:
while True:  # Keep asking until the player enters a number.print('How many snails will race? Max:', MAX_NUM_SNAILS)response = input('> ')if response.isdecimal():numSnailsRacing = int(response)if 1 < numSnailsRacing <= MAX_NUM_SNAILS:breakprint('Enter a number between 2 and', MAX_NUM_SNAILS)# Enter the names of each snail:
snailNames = []  # List of the string snail names.
for i in range(1, numSnailsRacing + 1):while True:  # Keep asking until the player enters a valid name.print('Enter snail #' + str(i) + "'s name:")name = input('> ')if len(name) == 0:print('Please enter a name.')elif name in snailNames:print('Choose a name that has not already been used.')else:break  # The entered name is acceptable.snailNames.append(name)# Display each snail at the start line.
print('\n' * 40)
print('START' + (' ' * (FINISH_LINE - len('START')) + 'FINISH'))
print('|' + (' ' * (FINISH_LINE - len('|')) + '|'))
snailProgress = {}
for snailName in snailNames:print(snailName[:MAX_NAME_LENGTH])print('@v')snailProgress[snailName] = 0time.sleep(1.5)  # The pause right before the race starts.while True:  # Main program loop.# Pick random snails to move forward:for i in range(random.randint(1, numSnailsRacing // 2)):randomSnailName = random.choice(snailNames)snailProgress[randomSnailName] += 1# Check if a snail has reached the finish line:if snailProgress[randomSnailName] == FINISH_LINE:print(randomSnailName, 'has won!')sys.exit()# (!) EXPERIMENT: Add a cheat here that increases a snail's progress# if it has your name.time.sleep(0.5)  # (!) EXPERIMENT: Try changing this value.# (!) EXPERIMENT: What happens if you comment this line out?print('\n' * 40)# Display the start and finish lines:print('START' + (' ' * (FINISH_LINE - len('START')) + 'FINISH'))print('|' + (' ' * (FINISH_LINE - 1) + '|'))# Display the snails (with name tags):for snailName in snailNames:spaces = snailProgress[snailName]print((' ' * spaces) + snailName[:MAX_NAME_LENGTH])print(('.' * snailProgress[snailName]) + '@v') 

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

  • 添加一个随机的“速度提升”,让蜗牛向前推进四格,而不是一格。
  • 增加一个蜗牛在比赛过程中可以随机进入的“睡眠模式”。这种模式使它们停下来转几圈,zzz出现在它们旁边。
  • 加上领带的支撑,以防蜗牛同时到达终点。

探索程序

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

  1. 如果把第 81 行的snailName[:MAX_NAME_LENGTH]改成snailNames[0]会怎么样?
  2. 如果把第 50 行的print('@v')改成print('email@protected')会怎么样?

七十、日本算盘

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

算盘,也称为计数框,是一种计算工具,早在电子计算器发明之前就在许多文化中使用。图 70-1 显示了日本的算盘,叫做 soroban。每根线代表一个位置数字系统中的一个位置,线上的珠子代表该位置的数字。例如,一个 Soroban 在最右边的线上移动了两个珠子,在第二个最右边的线上移动了三个珠子,这将表示数字 32。这个程序模拟了一个 Soroban。(讽刺的是,用一台计算机来模拟一个计算机前的计算工具对我来说并非没有意义。)

f70001

soroban

soroban 中的每一列代表一个不同的数字。最右边的列是个位,左边的列是个位,左边的列是个位,以此类推。键盘顶部的QWERTYUIOP键可以增加它们各自位置的数字,而ASDFGHJKL;按键会减少它们。虚拟 soroban 上的珠子会滑动以反映当前的数字。也可以直接输入数字。

水平分隔线下面的四个珠子是“地”珠子,将它们举到分隔线上,该数字计为 1。水平分隔线上方的珠子是一个“天”珠子,对着分隔线向下拉动它会对该数字计数为 5,因此在十位栏中向下拉动一个天堂珠子并向上拉动三个地球珠子代表数字 80。更多关于算盘以及如何使用它们的信息可以在/en.wikipedia.org/wiki/Abacus找到。

运行示例

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

Soroban - The Japanese Abacus
By Al Sweigart email@protected+================================+
I  O  O  O  O  O  O  O  O  O  O  I
I  |  |  |  |  |  |  |  |  |  |  I
I  |  |  |  |  |  |  |  |  |  |  I
+================================+
I  |  |  |  |  |  |  |  |  |  |  I
I  |  |  |  |  |  |  |  |  |  |  I
I  O  O  O  O  O  O  O  O  O  O  I
I  O  O  O  O  O  O  O  O  O  O  I
I  O  O  O  O  O  O  O  O  O  O  I
I  O  O  O  O  O  O  O  O  O  O  I
+==0==0==0==0==0==0==0==0==0==0==++q  w  e  r  t  y  u  i  o  p-a  s  d  f  g  h  j  k  l  ;
(Enter a number, "quit", or a stream of up/down letters.)
> pppiiiii+================================+
I  O  O  O  O  O  O  O  |  O  O  I
I  |  |  |  |  |  |  |  |  |  |  I
I  |  |  |  |  |  |  |  O  |  |  I
+================================+
I  |  |  |  |  |  |  |  |  |  O  I
I  |  |  |  |  |  |  |  |  |  O  I
I  O  O  O  O  O  O  O  O  O  O  I
I  O  O  O  O  O  O  O  O  O  |  I
I  O  O  O  O  O  O  O  O  O  |  I
I  O  O  O  O  O  O  O  O  O  O  I
+==0==0==0==0==0==0==0==5==0==3==++q  w  e  r  t  y  u  i  o  p-a  s  d  f  g  h  j  k  l  ;
(Enter a number, "quit", or a stream of up/down letters.)
`--snip--`

工作原理

displayAbacus()函数接受一个number参数,该参数用于计算应该在算盘上的什么位置呈现珠子。soroban 总是正好有 80 个可能的位置来放置'O'珠子或'|'杆段,如第 127 到 139 行多行字符串中的花括号({})所示。另外 10 个花括号代表number参数的数字。

我们需要创建一个字符串列表来填充这些花括号,从左到右,从上到下。displayAbacus()中的代码将用一个True值填充一个hasBead列表以显示一个'O'珠子,用一个False值显示一个'|'。该列表中的前 10 个值是针对顶部“天堂”行的。如果列的数字是 0、1、2、3 或 4,我们将在该行中放置一个珠子,因为除非该列的数字是 0 到 4,否则天堂珠子不会在该行中。对于剩余的行,我们将布尔值添加到hasBead

第 118 到 123 行使用hasBead创建一个包含实际的'O''|'字符串的abacusChar列表。当与第 126 行的numberList结合时,程序形成一个chars列表,填充 soroban 的多行字符串 ASCII 艺术画的花括号({})。

"""Soroban Japanese Abacus, by Al Sweigart email@protected
A simulation of a Japanese abacus calculator tool.
More info at: https://en.wikipedia.org/wiki/Soroban
This code is available at https://nostarch.com/big-book-small-python-programming
Tags: large, artistic, math, simulation"""NUMBER_OF_DIGITS = 10def main():print('Soroban - The Japanese Abacus')print('By Al Sweigart email@protected')print()abacusNumber = 0  # This is the number represented on the abacus.while True:  # Main program loop.displayAbacus(abacusNumber)displayControls()commands = input('> ')if commands == 'quit':# Quit the program:breakelif commands.isdecimal():# Set the abacus number:abacusNumber = int(commands)else:# Handle increment/decrement commands:for letter in commands:if letter == 'q':abacusNumber += 1000000000elif letter == 'a':abacusNumber -= 1000000000elif letter == 'w':abacusNumber += 100000000elif letter == 's':abacusNumber -= 100000000elif letter == 'e':abacusNumber += 10000000elif letter == 'd':abacusNumber -= 10000000elif letter == 'r':abacusNumber += 1000000elif letter == 'f':abacusNumber -= 1000000elif letter == 't':abacusNumber += 100000elif letter == 'g':abacusNumber -= 100000elif letter == 'y':abacusNumber += 10000elif letter == 'h':abacusNumber -= 10000elif letter == 'u':abacusNumber += 1000elif letter == 'j':abacusNumber -= 1000elif letter == 'i':abacusNumber += 100elif letter == 'k':abacusNumber -= 100elif letter == 'o':abacusNumber += 10elif letter == 'l':abacusNumber -= 10elif letter == 'p':abacusNumber += 1elif letter == ';':abacusNumber -= 1# The abacus can't show negative numbers:if abacusNumber < 0:abacusNumber = 0  # Change any negative numbers to 0.# The abacus can't show numbers larger than 9999999999:if abacusNumber > 9999999999:abacusNumber = 9999999999def displayAbacus(number):numberList = list(str(number).zfill(NUMBER_OF_DIGITS))hasBead = []  # Contains a True or False for each bead position.# Top heaven row has a bead for digits 0, 1, 2, 3, and 4.for i in range(NUMBER_OF_DIGITS):hasBead.append(numberList[i] in '01234')# Bottom heaven row has a bead for digits 5, 6, 7, 8, and 9.for i in range(NUMBER_OF_DIGITS):hasBead.append(numberList[i] in '56789')# 1st (topmost) earth row has a bead for all digits except 0.for i in range(NUMBER_OF_DIGITS):hasBead.append(numberList[i] in '12346789')# 2nd earth row has a bead for digits 2, 3, 4, 7, 8, and 9.for i in range(NUMBER_OF_DIGITS):hasBead.append(numberList[i] in '234789')# 3rd earth row has a bead for digits 0, 3, 4, 5, 8, and 9.for i in range(NUMBER_OF_DIGITS):hasBead.append(numberList[i] in '034589')# 4th earth row has a bead for digits 0, 1, 2, 4, 5, 6, and 9.for i in range(NUMBER_OF_DIGITS):hasBead.append(numberList[i] in '014569')# 5th earth row has a bead for digits 0, 1, 2, 5, 6, and 7.for i in range(NUMBER_OF_DIGITS):hasBead.append(numberList[i] in '012567')# 6th earth row has a bead for digits 0, 1, 2, 3, 5, 6, 7, and 8.for i in range(NUMBER_OF_DIGITS):hasBead.append(numberList[i] in '01235678')# Convert these True or False values into O or | characters.abacusChar = []for i, beadPresent in enumerate(hasBead):if beadPresent:abacusChar.append('O')else:abacusChar.append('|')# Draw the abacus with the O/| characters.chars = abacusChar + numberListprint("""
+================================+
I {}  {}  {}  {}  {}  {}  {}  {}  {}  {} I
I  |  |  |  |  |  |  |  |  |  |  I
I {}  {}  {}  {}  {}  {}  {}  {}  {}  {} I
+================================+
I {}  {}  {}  {}  {}  {}  {}  {}  {}  {} I
I {}  {}  {}  {}  {}  {}  {}  {}  {}  {} I
I {}  {}  {}  {}  {}  {}  {}  {}  {}  {} I
I {}  {}  {}  {}  {}  {}  {}  {}  {}  {} I
I {}  {}  {}  {}  {}  {}  {}  {}  {}  {} I
I {}  {}  {}  {}  {}  {}  {}  {}  {}  {} I
+=={}=={}=={}=={}=={}=={}=={}=={}=={}=={}==+""".format(*chars))def displayControls():print('  +q  w  e  r  t  y  u  i  o  p')print('  -a  s  d  f  g  h  j  k  l  ;')print('(Enter a number, "quit", or a stream of up/down letters.)')if __name__ == '__main__':main() 

探索程序

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

  1. 如果把第 15 行的abacusNumber = 0改成abacusNumber = 9999会怎么样?
  2. 如果把 121 行的abacusChar.append('O')改成abacusChar.append('@')会怎么样?

http://chatgpt.dhexx.cn/article/U7ZibWpk.shtml

相关文章

河北软件职业技术学院05级NIIT班第四学习小组——流氓山好汉一览

李大毛&#xff1a;只所以叫大毛&#xff0c;并不是因为这家伙浑身长毛&#xff0c;而是因为这家伙天天下载毛片&#xff0c;使毛片比病毒还疯狂地通过QQ在班里乱窜。 王狗狗&#xff1a;只所以叫狗狗是因为这家伙特别坏&#xff0c;在女生面前常常装成一正人君子面&#xff0…

软件精英齐聚张江 “校园之星”闪亮沪上——微软院校IT课程“校园之星”大赛决赛结果揭晓

2007年8月10日&#xff0c;微软院校IT课程“校园之星”大赛总决赛和颁奖仪式在上海张江软件园举行。自活动开展以来&#xff0c;备受人们关注的冠军获得者终于水落石 出&#xff0c;冠军组成员为湖北武汉商贸职业学院陶泽华、江苏南通农业职业技术学院王珍勇、辽宁沈阳理工大学…

重磅:吴晟当选 Apache 软件基金会 2021年董事

点击上方“开源社”关注我们 | 作者&#xff1a;刘天栋 | 编辑&#xff1a;王玥敏 | 设计&#xff1a;王福政 宣布新一届 ASF 董事会成员名单 在本周举行的 Apache 软件基金会&#xff08;ASF&#xff09;年度会员大会上&#xff0c;以下人员当选为ASF董事会成员。 Bertrand De…

科东软件Intewell操作系统获2023数字中国创新大赛·信创赛道全国总决赛三等奖

深耕信创生态&#xff0c;科东软件捷报频传 科东软件Intewell操作系统获2023数字中国创新大赛信创赛道全国总决赛三等奖 4月27日&#xff0c;2023数字中国创新大赛信创赛道全国总决赛(以下简称“大赛”)落下帷幕&#xff0c;历时2个多月&#xff0c;全国282支队伍&#xff0c;…

麦聪软件喜获双软认证

近日&#xff0c;北京麦聪软件有限公司&#xff08;以下简称&#xff1a;麦聪软件&#xff09;喜获由中国软件行业协会颁发并由北京软件和信息服务业协会评估的“软件产品证书”和“软件企业证书”&#xff0c;即业界公认的“双软认证”。 据了解&#xff0c;获得“双软认证”…

清华学姐熬了一个月肝出这份32W字软件测试知识手册,在 Github标星31K+

前言 金三银四即将过去&#xff0c;后面迎来的便是金九银十&#xff0c;一直想着说分享一些软件测试的面试题&#xff0c;这段时间做了一些收集和整理&#xff0c;大家可以试着做一下&#xff0c;希望能帮助到大家。 包括测试理论、Linux基础、MySQL基础、Web测试、接口测试、…

MFC学生成绩管理系统

MFC学生成绩管理系统 程序使用MFC框架编写&#xff0c;开发工具是VC6.0。 要求完成以下功能&#xff1a; 添加学生信息&#xff08;学生信息包含学号、姓名、班级、密码、各科成绩等&#xff09;&#xff1b;删除学生信息&#xff08;指定学号删除&#xff09;&#xff1b;修…

不是科班出身可以做配音演员吗?成都环宇博睿告诉你有没有学历要求?

成都环宇博睿今天给大家带来的是大多学生问得比较多的问题&#xff0c;在此成都环宇博睿给大家解读&#xff1a;文凭&#xff0c;对配音演员来说重要吗&#xff1f;不重要的话&#xff0c;各大求职网站都写着“大专及以上学历&#xff0c;本科学历”等字样&#xff1b;重要的话…

【软件测试】复习完整版还不快看怎么复习?--电子科技大学2023年期末考试

《软件测试》重要知识点 作者内容发布时间博客地址GithubTrae1ounG软件测试复习2023/6/3Trae1ounG的博客_CSDN博客-软件测试,计算机组成原理,数据库领域博主GitHub - Trae1ounG/jisuanjizuchengyuanli: 计组期末复习汇总 期末题型 分析题 分析怎么解决 分析修改缺陷 应用题 …

从7k到14k,软件测试三年,其中的辛酸只有我自己知道

我是今年2月换的工作&#xff0c;上一份工作刚好做满了2年&#xff0c;上一家公司月薪7000&#xff0c;实际拿到手就6450左右。但是工作了一阵后&#xff0c;工作越来越忙&#xff0c;感觉自己的技能已经跟不上了&#xff0c;加上周围的朋友也都开始跳槽&#xff0c;薪资都从之…

MindCon极客周 | 第四届如期而至,挑战硬核任务,C位出道赢万元激励 !

MindCon 极客周是华为昇思 MindSpore 开源社区每半年举办一次的开发者狂欢盛会&#xff0c;旨在引领兴趣者们走入 AI 探索的世界。第四届 MindCon 极客周以超级挑战赛为主题&#xff0c;发布多领域多级别应用场景的挑战任务&#xff0c;与开发者共同探索 AI 开源趣味世界。 第四…

河北工程科技学院软件学院学子在第二届“火焰杯”软件测试高校就业选拔赛中斩获大奖

本文由河北工程科技学院首发。http://www.hebsoft.com/?p5967 2022年4月&#xff0c;我院软件工程专业老师组织学生参加了第二届火焰杯高校就业选拔赛&#xff0c;我院学生与广西大学、重庆邮电大学、华东师范大学、华东交通大学、西安邮电大学、石家庄铁道大学、河北工程大学…

Linux上一款强大的GIF录制软件,Peek

1、Peek简介 Peek是在Linux平台下一款十分好用的GIF录制软件&#xff0c;至少我是这么认为的&#xff0c;其界面的简洁、功能的丰富&#xff08;应对平时录制GIF完全足够&#xff09;。自2018年以来推出的Peek 1.4.0是首次的重大更新&#xff0c;此更新功能包括一些重要的错误和…

简易MFC的成绩管理系统

意义 掌握MFC控件的基本使用&#xff0c;结合了面向对象和Window消息机制的知识。 选择做简单的成绩管理系统&#xff0c;该项目切合大学生实际情况。易于更好理解。 项目实现了成绩的增加、修改、删除、存储&#xff08;文件读写操作&#xff09;的功能。 创建项目 打开软件…

项目——基于MFC的成绩管理系统

一、项目介绍 1、本项目结合了面向对象和window消息机制的知识&#xff0c;实现了一个简单的成绩管理系统。 2、项目包含两个类&#xff0c;学生类和管理类&#xff0c;一个用于成绩的存储&#xff0c;一个用于成绩的管理。 3、项目使用了MFC&#xff08;微软基础类库&#xf…

Python作用域总结

Python特有的语法规则和诸如Java等其他静态类型语言有很大不同&#xff0c;而作用域规则则是其一&#xff0c;初识Python会遇到一些问题&#xff0c;现在对Python作用域相关的知识做个总结。 Python作用域规则一句话概括就是 LEGB 规则; L 代表 Local、E 代表 enclosing、G 代表…

python作用域问题

python作用域问题 有一句话很重要&#xff0c;要说在前面&#xff1b;类型是属于对象的&#xff0c;并不是属于变量&#xff1b; 而在python这门语言中&#xff0c;有一种说法叫做“鸭子类型”&#xff1a;“当看到一直鸟走起来像鸭子,游泳起来像鸭子 &#xff0c;叫起来也像…

python的作用域问题

命名空间 python中的namespace &#xff08;命名空间&#xff09;是映射到对象的名称。 命名空间的几个常见示例&#xff1a; abs() 函数、内置异常等的内置函数集合&#xff1b;模块中的全局名称&#xff1b;函数调用中的局部名称。对象的属性集合也算是一种命名空间。关于命…

实用解决Python作用域问题

前言&#xff1a;一直以来对Python的作用域问题有很多的疑惑&#xff0c;看了很多大牛的讲解之后有所收获&#xff0c;所以就记录下来 1、块级作用域 想想此时运行下面的程序会有输出吗&#xff1f;执行会成功吗&#xff1f; 1 2 3 4 5 6 7 8 9 10 11 12 #块级作用域 if 1…