赞
踩
ROT13 密码是最简单的加密算法之一,代表“旋转 13 个空格”密码将字母A
到Z
表示为数字 0 到 25,加密后的字母距离明文字母 13 个空格: A
变成N
,B
变成O
,以此类推。加密过程和解密过程是一样的,这使得编程变得很简单。然而,加密也很容易被破解。正因为如此,你会经常发现 ROT13 被用来隐藏非敏感信息,如剧透或琐事答案,所以它不会被无意中读取。更多关于 ROT13 密码的信息可以在en.wikipedia.org/wiki/ROT13
找到。如果你想更一般地了解密码和密码破解,你可以阅读我的书《Python 密码破解指南》(NoStarch 出版社,2018)。
当您运行rot13cipher.py
时,输出将如下所示:
ROT13 Cipher, by Al Sweigart email@protected
Enter a message to encrypt/decrypt (or QUIT):
> Meet me by the rose bushes tonight.
The translated message is:
Zrrg zr ol gur ebfr ohfurf gbavtug.
(Copied to clipboard.)
Enter a message to encrypt/decrypt (or QUIT):
`--snip--`
ROT13 与项目 6“凯撒密码”共享大量代码,尽管它要简单得多,因为它总是使用密钥 13。因为相同的代码执行加密和解密(第 27 到 39 行),所以没有必要询问玩家他们想要使用哪种模式。
一个不同之处是,这个程序保持原始消息的大小写,而不是自动将消息转换为大写。例如,HELLO
加密为URYYB
,而Hello
加密为Uryyb
。
"""ROT13 Cipher, by Al Sweigart email@protected The simplest shift cipher for encrypting and decrypting text. More info at https://en.wikipedia.org/wiki/ROT13 This code is available at https://nostarch.com/big-book-small-python-programming Tags: tiny, cryptography""" try: import pyperclip # pyperclip copies text to the clipboard. except ImportError: pass # If pyperclip is not installed, do nothing. It's no big deal. # Set up the constants: UPPER_LETTERS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' LOWER_LETTERS = 'abcdefghijklmnopqrstuvwxyz' print('ROT13 Cipher, by Al Sweigart email@protected') print() while True: # Main program loop. print('Enter a message to encrypt/decrypt (or QUIT):') message = input('> ') if message.upper() == 'QUIT': break # Break out of the main program loop. # Rotate the letters in message by 13 characters. translated = '' for character in message: if character.isupper(): # Concatenate uppercase translated character. transCharIndex = (UPPER_LETTERS.find(character) + 13) % 26 translated += UPPER_LETTERS[transCharIndex] elif character.islower(): # Concatenate lowercase translated character. transCharIndex = (LOWER_LETTERS.find(character) + 13) % 26 translated += LOWER_LETTERS[transCharIndex] else: # Concatenate the character untranslated. translated += character # Display the translation: print('The translated message is:') print(translated) print() try: # Copy the translation to the clipboard: pyperclip.copy(translated) print('(Copied to clipboard.)') except: pass
试着找出下列问题的答案。尝试对代码进行一些修改,然后重新运行程序,看看这些修改有什么影响。
character.isupper()
改成character.islower()
会怎么样?print(translated)
改成print(message)
会怎么样?这个项目的特点是使用三角函数的 3D 立方体旋转动画。您可以在自己的动画程序中修改 3D 点旋转数学和line()
函数。
虽然我们将用来绘制立方体的块文本字符看起来不像细而直的线,但这种绘制被称为线框模型,因为它只渲染物体表面的边缘。图 62-1 显示了立方体和 icosphere 的线框模型,icosphere 是一个由三角形组成的粗糙球体。
立方体(左)和 icosphere(右)的线框模型
图 62-2 显示了运行rotatingcube.py
时的输出。
:程序绘制到屏幕上的线框立方体
这个算法有两个主要部分:函数line()
和函数rotatePoint()
。立方体有八个点,每个角一个。程序将这些角存储为CUBE_CORNERS
列表中的(x, y, z)
元组。这些点也定义了立方体边缘线的连接。当所有的点都向同一个方向旋转相同的量时,它们会产生立方体旋转的错觉。
"""Rotating Cube, by Al Sweigart email@protected A rotating cube animation. Press Ctrl-C to stop. This code is available at https://nostarch.com/big-book-small-python-programming Tags: large, artistic, math""" # This program MUST be run in a Terminal/Command Prompt window. import math, time, sys, os # Set up the constants: PAUSE_AMOUNT = 0.1 # Pause length of one-tenth of a second. WIDTH, HEIGHT = 80, 24 SCALEX = (WIDTH - 4) // 8 SCALEY = (HEIGHT - 4) // 8 # Text cells are twice as tall as they are wide, so set scaley: SCALEY *= 2 TRANSLATEX = (WIDTH - 4) // 2 TRANSLATEY = (HEIGHT - 4) // 2 # (!) Try changing this to '#' or '*' or some other character: LINE_CHAR = chr(9608) # Character 9608 is a solid block. # (!) Try setting two of these values to zero to rotate the cube only # along a single axis: X_ROTATE_SPEED = 0.03 Y_ROTATE_SPEED = 0.08 Z_ROTATE_SPEED = 0.13 # This program stores XYZ coordinates in lists, with the X coordinate # at index 0, Y at 1, and Z at 2\. These constants make our code more # readable when accessing the coordinates in these lists. X = 0 Y = 1 Z = 2 def line(x1, y1, x2, y2): """Returns a list of points in a line between the given points. Uses the Bresenham line algorithm. More info at: https://en.wikipedia.org/wiki/Bresenham%27s_line_algorithm""" points = [] # Contains the points of the line. # "Steep" means the slope of the line is greater than 45 degrees or # less than -45 degrees: # Check for the special case where the start and end points are # certain neighbors, which this function doesn't handle correctly, # and return a hard coded list instead: if (x1 == x2 and y1 == y2 + 1) or (y1 == y2 and x1 == x2 + 1): return [(x1, y1), (x2, y2)] isSteep = abs(y2 - y1) > abs(x2 - x1) if isSteep: # This algorithm only handles non-steep lines, so let's change # the slope to non-steep and change it back later. x1, y1 = y1, x1 # Swap x1 and y1 x2, y2 = y2, x2 # Swap x2 and y2 isReversed = x1 > x2 # True if the line goes right-to-left. if isReversed: # Get the points on the line going right-to-left. x1, x2 = x2, x1 # Swap x1 and x2 y1, y2 = y2, y1 # Swap y1 and y2 deltax = x2 - x1 deltay = abs(y2 - y1) extray = int(deltax / 2) currenty = y2 if y1 < y2: ydirection = 1 else: ydirection = -1 # Calculate the y for every x in this line: for currentx in range(x2, x1 - 1, -1): if isSteep: points.append((currenty, currentx)) else: points.append((currentx, currenty)) extray -= deltay if extray <= 0: # Only change y once extray <= 0. currenty -= ydirection extray += deltax else: # Get the points on the line going left to right. deltax = x2 - x1 deltay = abs(y2 - y1) extray = int(deltax / 2) currenty = y1 if y1 < y2: ydirection = 1 else: ydirection = -1 # Calculate the y for every x in this line: for currentx in range(x1, x2 + 1): if isSteep: points.append((currenty, currentx)) else: points.append((currentx, currenty)) extray -= deltay if extray < 0: # Only change y once extray < 0. currenty += ydirection extray += deltax return points def rotatePoint(x, y, z, ax, ay, az): """Returns an (x, y, z) tuple of the x, y, z arguments rotated. The rotation happens around the 0, 0, 0 origin by angles ax, ay, az (in radians). Directions of each axis: -y | +-- +x / +z """ # Rotate around x axis: rotatedX = x rotatedY = (y * math.cos(ax)) - (z * math.sin(ax)) rotatedZ = (y * math.sin(ax)) + (z * math.cos(ax)) x, y, z = rotatedX, rotatedY, rotatedZ # Rotate around y axis: rotatedX = (z * math.sin(ay)) + (x * math.cos(ay)) rotatedY = y rotatedZ = (z * math.cos(ay)) - (x * math.sin(ay)) x, y, z = rotatedX, rotatedY, rotatedZ # Rotate around z axis: rotatedX = (x * math.cos(az)) - (y * math.sin(az)) rotatedY = (x * math.sin(az)) + (y * math.cos(az)) rotatedZ = z return (rotatedX, rotatedY, rotatedZ) def adjustPoint(point): """Adjusts the 3D XYZ point to a 2D XY point fit for displaying on the screen. This resizes this 2D point by a scale of SCALEX and SCALEY, then moves the point by TRANSLATEX and TRANSLATEY.""" return (int(point[X] * SCALEX + TRANSLATEX), int(point[Y] * SCALEY + TRANSLATEY)) """CUBE_CORNERS stores the XYZ coordinates of the corners of a cube. The indexes for each corner in CUBE_CORNERS are marked in this diagram: 0---1 /| /| 2---3 | | 4-|-5 |/ |/ 6---7""" CUBE_CORNERS = [[-1, -1, -1], # Point 0 [ 1, -1, -1], # Point 1 [-1, -1, 1], # Point 2 [ 1, -1, 1], # Point 3 [-1, 1, -1], # Point 4 [ 1, 1, -1], # Point 5 [-1, 1, 1], # Point 6 [ 1, 1, 1]] # Point 7 # rotatedCorners stores the XYZ coordinates from CUBE_CORNERS after # they've been rotated by rx, ry, and rz amounts: rotatedCorners = [None, None, None, None, None, None, None, None] # Rotation amounts for each axis: xRotation = 0.0 yRotation = 0.0 zRotation = 0.0 try: while True: # Main program loop. # Rotate the cube along different axes by different amounts: xRotation += X_ROTATE_SPEED yRotation += Y_ROTATE_SPEED zRotation += Z_ROTATE_SPEED for i in range(len(CUBE_CORNERS)): x = CUBE_CORNERS[i][X] y = CUBE_CORNERS[i][Y] z = CUBE_CORNERS[i][Z] rotatedCorners[i] = rotatePoint(x, y, z, xRotation, yRotation, zRotation) # Get the points of the cube lines: cubePoints = [] for fromCornerIndex, toCornerIndex in ((0, 1), (1, 3), (3, 2), (2, 0), (0, 4), (1, 5), (2, 6), (3, 7), (4, 5), (5, 7), (7, 6), (6, 4)): fromX, fromY = adjustPoint(rotatedCorners[fromCornerIndex]) toX, toY = adjustPoint(rotatedCorners[toCornerIndex]) pointsOnLine = line(fromX, fromY, toX, toY) cubePoints.extend(pointsOnLine) # Get rid of duplicate points: cubePoints = tuple(frozenset(cubePoints)) # Display the cube on the screen: for y in range(HEIGHT): for x in range(WIDTH): if (x, y) in cubePoints: # Display full block: print(LINE_CHAR, end='', flush=False) else: # Display empty space: print(' ', end='', flush=False) print(flush=False) print('Press Ctrl-C to quit.', end='', flush=True) time.sleep(PAUSE_AMOUNT) # Pause for a bit. # Clear the screen: if sys.platform == 'win32': os.system('cls') # Windows uses the cls command. else: os.system('clear') # macOS and Linux use the clear command. except KeyboardInterrupt: print('Rotating Cube, by Al Sweigart email@protected') sys.exit() # When Ctrl-C is pressed, end the program.
在输入源代码并运行几次之后,尝试对其进行实验性的修改。标有(!)
的注释对你可以做的小改变有建议。你也可以自己想办法做到以下几点:
CUBE_CORNERS
和第 184 行的元组,创建不同的线框模型,如金字塔和扁平六边形。CUBE_CORNERS
的坐标增加1.5
,使立方体围绕屏幕中心旋转,而不是围绕自己的中心旋转。试着找出下列问题的答案。尝试对代码进行一些修改,然后重新运行程序,看看这些修改有什么影响。
<((0, 1), (1, 3), (3, 2), (2, 0), (0,4), (4, 5), (5, 1))>
会怎么样?乌尔的皇家游戏是一个来自美索不达米亚的有 5000 年历史的游戏。考古学家在 1922 年至 1934 年间的挖掘过程中,在现代伊拉克南部的乌尔皇家墓地重新发现了这款游戏。这些规则是根据游戏棋盘(如图 63-1 所示)和一块巴比伦泥板重建的,它们类似于 Parcheesi。你需要运气和技巧才能赢。
图 63-1 :在乌尔皇家墓地发现的五块游戏板之一
两名玩家每人从家中的七个代币开始,第一个将所有七个代币移动到目标位置的玩家获胜。玩家轮流掷出四个骰子。这些骰子是称为四面体的四角金字塔形状。每个骰子都有两个标记点,这使得骰子有标记或无标记的机会均等。我们的游戏用硬币代替骰子,硬币的头部作为标记点。玩家可以为出现的每一个标记点移动一格代币。这意味着他们可以在 0 到 4 个空格之间移动一个代币,尽管他们最有可能掷出两个空格。
代币沿着图 63-2 中所示的路径行进。一个空间上一次只能存在一个代币。如果一个代币在共享中间路径上落在对手的代币上,对手的代币会被送回家。如果一个代币落在中间的花方格上,它就不会被落在上面。如果一个代币落在其他四个花牌中的任何一个上,玩家可以再掷一次。我们的游戏将用字母X
和O
来代表代币。
图 63-2 :每个玩家的代币从他们的家到他们的目标的路径
在www.youtube.com/watch?v=WZskjLq040I
可以找到优图伯·汤姆·斯科特和大英博物馆馆长欧文·芬克尔讨论乌尔王族游戏的视频。
当您运行royalgameofur.py
时,输出将如下所示:
The Royal Game of Ur, by Al Sweigart `--snip--` XXXXXXX ....... Home Goal v ^ +-----+-----+-----+--v--+ +--^--+-----+ |*****| | | | |*****| | |* *< < < | |* *< | |****h| g| f| e| |****t| s| +--v--+-----+-----+-----+-----+-----+-----+--^--+ | | | |*****| | | | | | > > >* *> > > > | | i| j| k|****l| m| n| o| p| +--^--+-----+-----+-----+-----+-----+-----+--v--+ |*****| | | | |*****| | |* *< < < | |* *< | |****d| c| b| a| |****r| q| +-----+-----+-----+--^--+ +--v--+-----+ ^ v Home Goal OOOOOOO ....... It is O's turn. Press Enter to flip... Flips: H-H-H-H Select token to move 4 spaces: home quit > home O landed on a flower space and gets to go again. Press Enter to continue... `--snip--`
就像项目 43“曼卡拉”一样,ASCII 艺术画游戏棋盘上的空格用字母a
到t
标注。掷骰子后,玩家可以选择一个包含其代币的空间来移动代币,或者他们可以选择home
开始将代币从家中移到棋盘上。该程序将棋盘表示为一个字典,其中键为'a'
到't'
,值为'X'
和'O'
用于标记(或' '
用于空格)。
此外,这个字典有关键字'x_home'
、'o_home'
、'x_goal'
和'o_goal'
,这些关键字的值是七个字符的字符串,表示家庭和目标有多满。这些字符串中的'X'
或'O'
字符代表主场或球门的代币,'.'
代表空位置。displayBoard()
函数在屏幕上显示这七个字符串。
"""The Royal Game of Ur, by Al Sweigart email@protected A 5,000 year old board game from Mesopotamia. Two players knock each other back as they race for the goal. More info https://en.wikipedia.org/wiki/Royal_Game_of_Ur This code is available at https://nostarch.com/big-book-small-python-programming Tags: large, board game, game, two-player """ import random, sys X_PLAYER = 'X' O_PLAYER = 'O' EMPTY = ' ' # Set up constants for the space labels: X_HOME = 'x_home' O_HOME = 'o_home' X_GOAL = 'x_goal' O_GOAL = 'o_goal' # The spaces in left to right, top to bottom order: ALL_SPACES = 'hgfetsijklmnopdcbarq' X_TRACK = 'HefghijklmnopstG' # (H stands for Home, G stands for Goal.) O_TRACK = 'HabcdijklmnopqrG' FLOWER_SPACES = ('h', 't', 'l', 'd', 'r') BOARD_TEMPLATE = """ {} {} 30\. Home Goal v ^ +-----+-----+-----+--v--+ +--^--+-----+ |*****| | | | |*****| | |* {} *< {} < {} < {} | |* {} *< {} | |****h| g| f| e| |****t| s| +--v--+-----+-----+-----+-----+-----+-----+--^--+ | | | |*****| | | | | | {} > {} > {} >* {} *> {} > {} > {} > {} | | i| j| k|****l| m| n| o| p| +--^--+-----+-----+-----+-----+-----+-----+--v--+ |*****| | | | |*****| | |* {} *< {} < {} < {} | |* {} *< {} | |****d| c| b| a| |****r| q| +-----+-----+-----+--^--+ +--v--+-----+ ^ v Home Goal {} {} 48\. """ def main(): print('''The Royal Game of Ur, by Al Sweigart This is a 5,000 year old game. Two players must move their tokens from their home to their goal. On your turn you flip four coins and can move one token a number of spaces equal to the heads you got. Ur is a racing game; the first player to move all seven of their tokens to their goal wins. To do this, tokens must travel from their home to their goal: X Home X Goal v ^ +---+---+---+-v-+ +-^-+---+ |v<<<<<<<<<<<<< | | ^<|<< | |v | | | | | | ^ | +v--+---+---+---+---+---+---+-^-+ |>>>>>>>>>>>>>>>>>>>>>>>>>>>>>^ | |>>>>>>>>>>>>>>>>>>>>>>>>>>>>>v | +^--+---+---+---+---+---+---+-v-+ |^ | | | | | | v | |^<<<<<<<<<<<<< | | v<<<< | +---+---+---+-^-+ +-v-+---+ ^ v O Home O Goal If you land on an opponent's token in the middle track, it gets sent back home. The **flower** spaces let you take another turn. Tokens in the middle flower space are safe and cannot be landed on.''') input('Press Enter to begin...') gameBoard = getNewBoard() turn = O_PLAYER while True: # Main game loop. # Set up some variables for this turn: if turn == X_PLAYER: opponent = O_PLAYER home = X_HOME track = X_TRACK goal = X_GOAL opponentHome = O_HOME elif turn == O_PLAYER: opponent = X_PLAYER home = O_HOME track = O_TRACK goal = O_GOAL opponentHome = X_HOME displayBoard(gameBoard) input('It is ' + turn + '\'s turn. Press Enter to flip...') flipTally = 0 print('Flips: ', end='') for i in range(4): # Flip 4 coins. result = random.randint(0, 1) if result == 0: print('T', end='') # Tails. else: print('H', end='') # Heads. if i != 3: print('-', end='') # Print separator. flipTally += result print(' ', end='') if flipTally == 0: input('You lose a turn. Press Enter to continue...') turn = opponent # Swap turns to the other player. continue # Ask the player for their move: validMoves = getValidMoves(gameBoard, turn, flipTally) if validMoves == []: print('There are no possible moves, so you lose a turn.') input('Press Enter to continue...') turn = opponent # Swap turns to the other player. continue while True: print('Select move', flipTally, 'spaces: ', end='') print(' '.join(validMoves) + ' quit') move = input('> ').lower() if move == 'quit': print('Thanks for playing!') sys.exit() if move in validMoves: break # Exit the loop when a valid move is selected. print('That is not a valid move.') # Perform the selected move on the board: if move == 'home': # Subtract tokens at home if moving from home: gameBoard[home] -= 1 nextTrackSpaceIndex = flipTally else: gameBoard[move] = EMPTY # Set the "from" space to empty. nextTrackSpaceIndex = track.index(move) + flipTally movingOntoGoal = nextTrackSpaceIndex == len(track) - 1 if movingOntoGoal: gameBoard[goal] += 1 # Check if the player has won: if gameBoard[goal] == 7: displayBoard(gameBoard) print(turn, 'has won the game!') print('Thanks for playing!') sys.exit() else: nextBoardSpace = track[nextTrackSpaceIndex] # Check if the opponent has a tile there: if gameBoard[nextBoardSpace] == opponent: gameBoard[opponentHome] += 1 # Set the "to" space to the player's token: gameBoard[nextBoardSpace] = turn # Check if the player landed on a flower space and can go again: if nextBoardSpace in FLOWER_SPACES: print(turn, 'landed on a flower space and goes again.') input('Press Enter to continue...') else: turn = opponent # Swap turns to the other player. def getNewBoard(): """ Returns a dictionary that represents the state of the board. The keys are strings of the space labels, the values are X_PLAYER, O_PLAYER, or EMPTY. There are also counters for how many tokens are at the home and goal of both players. """ board = {X_HOME: 7, X_GOAL: 0, O_HOME: 7, O_GOAL: 0} # Set each space as empty to start: for spaceLabel in ALL_SPACES: board[spaceLabel] = EMPTY return board def displayBoard(board): """Display the board on the screen.""" # "Clear" the screen by printing many newlines, so the old # board isn't visible anymore. print('\n' * 60) xHomeTokens = ('X' * board[X_HOME]).ljust(7, '.') xGoalTokens = ('X' * board[X_GOAL]).ljust(7, '.') oHomeTokens = ('O' * board[O_HOME]).ljust(7, '.') oGoalTokens = ('O' * board[O_GOAL]).ljust(7, '.') # Add the strings that should populate BOARD_TEMPLATE in order, # going from left to right, top to bottom. spaces = [] spaces.append(xHomeTokens) spaces.append(xGoalTokens) for spaceLabel in ALL_SPACES: spaces.append(board[spaceLabel]) spaces.append(oHomeTokens) spaces.append(oGoalTokens) print(BOARD_TEMPLATE.format(*spaces)) def getValidMoves(board, player, flipTally): validMoves = [] # Contains the spaces with tokens that can move. if player == X_PLAYER: opponent = O_PLAYER track = X_TRACK home = X_HOME elif player == O_PLAYER: opponent = X_PLAYER track = O_TRACK home = O_HOME # Check if the player can move a token from home: if board[home] > 0 and board[track[flipTally]] == EMPTY: validMoves.append('home') # Check which spaces have a token the player can move: for trackSpaceIndex, space in enumerate(track): if space == 'H' or space == 'G' or board[space] != player: continue nextTrackSpaceIndex = trackSpaceIndex + flipTally if nextTrackSpaceIndex >= len(track): # You must flip an exact number of moves onto the goal, # otherwise you can't move on the goal. continue else: nextBoardSpaceKey = track[nextTrackSpaceIndex] if nextBoardSpaceKey == 'G': # This token can move off the board: validMoves.append(space) continue if board[nextBoardSpaceKey] in (EMPTY, opponent): # If the next space is the protected middle space, you # can only move there if it is empty: if nextBoardSpaceKey == 'l' and board['l'] == opponent: continue # Skip this move, the space is protected. validMoves.append(space) return validMoves if __name__ == '__main__': main()
试着找出下列问题的答案。尝试对代码进行一些修改,然后重新运行程序,看看这些修改有什么影响。
nextTrackSpaceIndex == len(track) - 1
改成nextTrackSpaceIndex == 1
会怎么样?result = random.randint(0, 1)
改成result = 1
会怎么样?board = {X_HOME: 7, X_GOAL: 0, O_HOME: 7, O_GOAL: 0}
改成board = {}
会导致什么错误?七段显示器是一种 LCD 组件,用于在袖珍计算器、微波炉和其他小型电子设备中显示数字。通过 LCD 中七个线段的不同组合,七段显示器可以表示数字 0 到 9。它们看起来像这样:
__ __ __ __ __ __ __ __
| | | __| __| |__| |__ |__ | |__| |__|
|__| | |__ __| | __| |__| | |__| __|
这个程序的好处是其他程序可以把它作为一个模块导入。项目 14,“倒计时”和项目 19,“数字钟”,导入sevseg.py
文件,这样他们就可以使用它的getSevSegStr()
函数。你可以在en.wikipedia.org/wiki/Seven-segment_display
找到更多关于七段显示器和其他变化的信息。
尽管它是一个模块,当你直接运行程序时,sevseg.py
输出一个它产生的数字的示例演示。输出将如下所示:
This module is meant to be imported rather than run.
For example, this code:
import sevseg
myNumber = sevseg.getSevSegStr(42, 3)
print(myNumber)
Will print 42, zero-padded to three digits:
__ __
| | |__| __|
|__| | |__
getSevSegStr()
函数首先创建一个包含三个字符串的列表。这些字符串表示数字的顶行、中间行和底行。第 27 行到第 75 行有一长串针对每个数字(以及小数点和减号)的if
- elif
语句,这些语句将每个数字的行连接到这些字符串。这三个字符串在第 84 行用换行符连接在一起,因此函数返回一个适合传递给print()
的多行字符串。
"""Sevseg, by Al Sweigart email@protected A seven-segment number display module, used by the Countdown and Digital Clock programs. More info at https://en.wikipedia.org/wiki/Seven-segment_display This code is available at https://nostarch.com/big-book-small-python-programming Tags: short, module""" """A labeled seven-segment display, with each segment labeled A to G: __A__ | | Each digit in a seven-segment display: F B __ __ __ __ __ __ __ __ |__G__| | | | __| __| |__| |__ |__ | |__| |__| | | |__| | |__ __| | __| |__| | |__| __| E C |__D__|""" def getSevSegStr(number, minWidth=0): """Return a seven-segment display string of number. The returned string will be padded with zeros if it is smaller than minWidth.""" # Convert number to string in case it's an int or float: number = str(number).zfill(minWidth) rows = ['', '', ''] for i, numeral in enumerate(number): if numeral == '.': # Render the decimal point. rows[0] += ' ' rows[1] += ' ' rows[2] += '.' continue # Skip the space in between digits. elif numeral == '-': # Render the negative sign: rows[0] += ' ' rows[1] += ' __ ' rows[2] += ' ' elif numeral == '0': # Render the 0. rows[0] += ' __ ' rows[1] += '| |' rows[2] += '|__|' elif numeral == '1': # Render the 1. rows[0] += ' ' rows[1] += ' |' rows[2] += ' |' elif numeral == '2': # Render the 2. rows[0] += ' __ ' rows[1] += ' __|' rows[2] += '|__ ' elif numeral == '3': # Render the 3. rows[0] += ' __ ' rows[1] += ' __|' rows[2] += ' __|' elif numeral == '4': # Render the 4. rows[0] += ' ' rows[1] += '|__|' rows[2] += ' |' elif numeral == '5': # Render the 5. rows[0] += ' __ ' rows[1] += '|__ ' rows[2] += ' __|' elif numeral == '6': # Render the 6. rows[0] += ' __ ' rows[1] += '|__ ' rows[2] += '|__|' elif numeral == '7': # Render the 7. rows[0] += ' __ ' rows[1] += ' |' rows[2] += ' |' elif numeral == '8': # Render the 8. rows[0] += ' __ ' rows[1] += '|__|' rows[2] += '|__|' elif numeral == '9': # Render the 9. rows[0] += ' __ ' rows[1] += '|__|' rows[2] += ' __|' # Add a space (for the space in between numerals) if this # isn't the last numeral and the decimal point isn't next: if i != len(number) - 1 and number[i + 1] != '.': rows[0] += ' ' rows[1] += ' ' rows[2] += ' ' return '\n'.join(rows) # If this program isn't being imported, display the numbers 00 to 99. if __name__ == '__main__': print('This module is meant to be imported rather than run.') print('For example, this code:') print(' import sevseg') print(' myNumber = sevseg.getSevSegStr(42, 3)') print(' print(myNumber)') print() print('...will print 42, zero-padded to three digits:') print(' __ __ ') print('| | |__| __|') print('|__| | |__ ')
在输入源代码并运行几次之后,尝试对其进行实验性的修改。你也可以自己想办法做到以下几点:
chr(9608)
返回的块字符串。sevseg.py
。en.wikipedia.org/wiki/Sixteen-segment_display
学习十六段显示,并创建一个十六段显示模块来生成该样式的数字。试着找出下列问题的答案。尝试对代码进行一些修改,然后重新运行程序,看看这些修改有什么影响。
minWidth=0
改为minWidth=8
,会发生什么?斯坦利·库布里克执导的 1980 年心理恐怖片《闪光》发生在闹鬼的远眺酒店。酒店地毯的六边形设计成为这部著名电影的标志性部分。地毯的特点是交替和连锁的六边形,其催眠效果非常适合这样一部令人紧张的电影。这个项目中的短程序,类似于项目 35,“六边形网格”,在屏幕上打印这个重复的图案。
注意,这个程序使用原始字符串,它在开始的引号前面加上小写的r
,这样字符串中的反斜杠就不会被解释为转义字符。
当您运行shiningcarpet.py
时,输出将如下所示:
_ \ \ \_/ ___ \ \ \_/ ___ \ \ \_/ ___ \ \ \_/ ___ \ \ \_/ ___ \ \ \_/ __ \ \ \___/ _ \ \ \___/ _ \ \ \___/ _ \ \ \___/ _ \ \ \___/ _ \ \ \___/ _ \ \ \_____/ \ \ \_____/ \ \ \_____/ \ \ \_____/ \ \ \_____/ \ \ \_____/ / / / ___ \_/ / / ___ \_/ / / ___ \_/ / / ___ \_/ / / ___ \_/ / / ___ \_ _/ / / _ \___/ / / _ \___/ / / _ \___/ / / _ \___/ / / _ \___/ / / _ \__ __/ / / \_____/ / / \_____/ / / \_____/ / / \_____/ / / \_____/ / / \___ _ \ \ \_/ ___ \ \ \_/ ___ \ \ \_/ ___ \ \ \_/ ___ \ \ \_/ ___ \ \ \_/ __ \ \ \___/ _ \ \ \___/ _ \ \ \___/ _ \ \ \___/ _ \ \ \___/ _ \ \ \___/ _ \ \ \_____/ \ \ \_____/ \ \ \_____/ \ \ \_____/ \ \ \_____/ \ \ \_____/ / / / ___ \_/ / / ___ \_/ / / ___ \_/ / / ___ \_/ / / ___ \_/ / / ___ \_ _/ / / _ \___/ / / _ \___/ / / _ \___/ / / _ \___/ / / _ \___/ / / _ \__ __/ / / \_____/ / / \_____/ / / \_____/ / / \_____/ / / \_____/ / / \___ _ \ \ \_/ ___ \ \ \_/ ___ \ \ \_/ ___ \ \ \_/ ___ \ \ \_/ ___ \ \ \_/ __ \ \ \___/ _ \ \ \___/ _ \ \ \___/ _ \ \ \___/ _ \ \ \___/ _ \ \ \___/ _ \ \ \_____/ \ \ \_____/ \ \ \_____/ \ \ \_____/ \ \ \_____/ \ \ \_____/ / / / ___ \_/ / / ___ \_/ / / ___ \_/ / / ___ \_/ / / ___ \_/ / / ___ \_ _/ / / _ \___/ / / _ \___/ / / _ \___/ / / _ \___/ / / _ \___/ / / _ \__ __/ / / \_____/ / / \_____/ / / \_____/ / / \_____/ / / \_____/ / / \___
创建这样的程序(或类似的第三十五个项目)并不是从编码开始,而是在文本编辑器中绘制镶嵌形状。一旦你写出了图案,你就可以把它切割成需要平铺的最小单元:
_ \ \ \_/ __
\ \ \___/ _
\ \ \_____/
/ / / ___ \_
_/ / / _ \__
__/ / / \___
将这段文本复制并粘贴到源代码中后,您可以围绕它编写程序的其余部分。软件不仅仅是坐下来从头到尾写代码。每个专业软件开发人员都要经历几次反复的修补、实验和调试。最终的结果可能只有九行代码,但是一个小程序并不一定意味着花了很少的精力来完成它。
"""Shining Carpet, by Al Sweigart email@protected Displays a tessellation of the carpet pattern from The Shining. This code is available at https://nostarch.com/big-book-small-python-programming Tags: tiny, beginner, artistic""" # Set up the constants: X_REPEAT = 6 # How many times to tessellate horizontally. Y_REPEAT = 4 # How many times to tessellate vertically. for i in range(Y_REPEAT): print(r'_ \ \ \_/ __' * X_REPEAT) print(r' \ \ \___/ _' * X_REPEAT) print(r'\ \ \_____/ ' * X_REPEAT) print(r'/ / / ___ \_' * X_REPEAT) print(r'_/ / / _ \__' * X_REPEAT) print(r'__/ / / \___' * X_REPEAT)
在实践中,尝试创建如下模式:
___|___|___|___|___|___|___|___|___|___|___|___|___|___|___| _|___|___|___|___|___|___|___|___|___|___|___|___|___|___|__ ___|___|___|___|___|___|___|___|___|___|___|___|___|___|___| _|___|___|___|___|___|___|___|___|___|___|___|___|___|___|__ ___|___|___|___|___|___|___|___|___|___|___|___|___|___|___| _|___|___|___|___|___|___|___|___|___|___|___|___|___|___|__ (( )(( )(( )(( )(( )(( )(( )(( )(( )(( )(( )(( ) ))( ))( ))( ))( ))( ))( ))( ))( ))( ))( ))( ))( (( )(( )(( )(( )(( )(( )(( )(( )(( )(( )(( )(( ) ))( ))( ))( ))( ))( ))( ))( ))( ))( ))( ))( ))( (( )(( )(( )(( )(( )(( )(( )(( )(( )(( )(( )(( ) ))( ))( ))( ))( ))( ))( ))( ))( ))( ))( ))( ))( / __ \ \__/ / __ \ \__/ / __ \ \__/ / __ \ \__/ / __ \ \__/ / / \ \____/ / \ \____/ / \ \____/ / \ \____/ / \ \____ \ \__/ / __ \ \__/ / __ \ \__/ / __ \ \__/ / __ \ \__/ / __ \____/ / \ \____/ / \ \____/ / \ \____/ / \ \____/ / \ / __ \ \__/ / __ \ \__/ / __ \ \__/ / __ \ \__/ / __ \ \__/ / / \ \____/ / \ \____/ / \ \____/ / \ \____/ / \ \____ \ \__/ / __ \ \__/ / __ \ \__/ / __ \ \__/ / __ \ \__/ / __ \____/ / \ \____/ / \ \____/ / \ \____/ / \ \____/ / \ \__ \__ \__ \__ \__ \__ \__ \__ \__ \__ __/ \__/ \__/ \__/ \__/ \__/ \__/ \__/ \__/ \__/ \ \ \ \ \ \ \ \ \ \ \ __/ __/ __/ __/ __/ __/ __/ __/ __/ __/ \__/ \__/ \__/ \__/ \__/ \__/ \__/ \__/ \__/ \__/ __/ / / / / / / / / / \__ \__ \__ \__ \__ \__ \__ \__ \__ \__ __/ \__/ \__/ \__/ \__/ \__/ \__/ \__/ \__/ \__/ \ / ___ \ ^ / ___ \ ^ / ___ \ ^ / ___ \ ^ / ___ \ ^ / ___ \ ^ / \ VVV / \ VVV / \ VVV / \ VVV / \ VVV / \ VVV |() ()| |() ()| |() ()| |() ()| |() ()| |() ()| \ ^ / ___ \ ^ / ___ \ ^ / ___ \ ^ / ___ \ ^ / ___ \ ^ / ___ \ VVV / \ VVV / \ VVV / \ VVV / \ VVV / \ VVV / )| |() ()| |() ()| |() ()| |() ()| |() ()| |() (
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。