Python 小型项目大全 36~40

article/2025/11/6 16:18:00

三十六、沙漏

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

这个可视化程序有一个粗糙的物理引擎,模拟沙子通过沙漏的小孔落下。沙子堆积在沙漏的下半部分;然后把沙漏翻过来,重复这个过程。

运行示例

图 36-1 显示了运行hourglass.py时的输出。

f36001

:沙漏程序在落砂时的输出

工作原理

沙漏程序实现了一个基本的物理引擎。一个物理引擎是模拟物理物体在重力作用下下落,相互碰撞,按照物理定律运动的软件。你会发现在视频游戏、计算机动画和科学模拟中使用的物理引擎。在第 91 到 102 行,每一粒沙子检查它下面的空间是否是空的,如果是,就向下移动。否则,它检查它是否可以向左下方移动(第 104 到 112 行)或向右下方移动(第 114 到 122 行)。当然,运动学,经典物理学的一个分支,处理宏观物体的运动,远不止这些。然而,你不需要一个物理学学位来制作一个沙漏中沙子的原始模拟,它看起来是令人愉快的。

"""Hourglass, by Al Sweigart email@protected
An animation of an hourglass with falling sand. Press Ctrl-C to stop.
This code is available at https://nostarch.com/big-book-small-python-programming
Tags: large, artistic, bext, simulation"""import random, sys, timetry: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:
PAUSE_LENGTH = 0.2  # (!) Try changing this to 0.0 or 1.0.
# (!) Try changing this to any number between 0 and 100:
WIDE_FALL_CHANCE = 50SCREEN_WIDTH = 79
SCREEN_HEIGHT = 25
X = 0  # The index of X values in an (x, y) tuple is 0.
Y = 1  # The index of Y values in an (x, y) tuple is 1.
SAND = chr(9617)
WALL = chr(9608)# Set up the walls of the hour glass:
HOURGLASS = set()  # Has (x, y) tuples for where hourglass walls are.
# (!) Try commenting out some HOURGLASS.add() lines to erase walls:
for i in range(18, 37):HOURGLASS.add((i, 1))  # Add walls for the top cap of the hourglass.HOURGLASS.add((i, 23))  # Add walls for the bottom cap.
for i in range(1, 5):HOURGLASS.add((18, i))  # Add walls for the top left straight wall.HOURGLASS.add((36, i))  # Add walls for the top right straight wall.HOURGLASS.add((18, i + 19))  # Add walls for the bottom left.HOURGLASS.add((36, i + 19))  # Add walls for the bottom right.
for i in range(8):HOURGLASS.add((19 + i, 5 + i))  # Add the top left slanted wall.HOURGLASS.add((35 - i, 5 + i))  # Add the top right slanted wall.HOURGLASS.add((25 - i, 13 + i))  # Add the bottom left slanted wall.HOURGLASS.add((29 + i, 13 + i))  # Add the bottom right slanted wall.# Set up the initial sand at the top of the hourglass:
INITIAL_SAND = set()
for y in range(8):for x in range(19 + y, 36 - y):INITIAL_SAND.add((x, y + 4))def main():bext.fg('yellow')bext.clear()# Draw the quit message:bext.goto(0, 0)print('Ctrl-C to quit.', end='')# Display the walls of the hourglass:for wall in HOURGLASS:bext.goto(wall[X], wall[Y])print(WALL, end='')while True:  # Main program loop.allSand = list(INITIAL_SAND)# Draw the initial sand:for sand in allSand:bext.goto(sand[X], sand[Y])print(SAND, end='')runHourglassSimulation(allSand)def runHourglassSimulation(allSand):"""Keep running the sand falling simulation until the sand stopsmoving."""while True:  # Keep looping until sand has run out.random.shuffle(allSand)  # Random order of grain simulation.sandMovedOnThisStep = Falsefor i, sand in enumerate(allSand):if sand[Y] == SCREEN_HEIGHT - 1:# Sand is on the very bottom, so it won't move:continue# If nothing is under this sand, move it down:noSandBelow = (sand[X], sand[Y] + 1) not in allSandnoWallBelow = (sand[X], sand[Y] + 1) not in HOURGLASScanFallDown = noSandBelow and noWallBelowif canFallDown:# Draw the sand in its new position down one space:bext.goto(sand[X], sand[Y])print(' ', end='')  # Clear the old position.bext.goto(sand[X], sand[Y] + 1)print(SAND, end='')# Set the sand in its new position down one space:allSand[i] = (sand[X], sand[Y] + 1)sandMovedOnThisStep = Trueelse:# Check if the sand can fall to the left:belowLeft = (sand[X] - 1, sand[Y] + 1)noSandBelowLeft = belowLeft not in allSandnoWallBelowLeft = belowLeft not in HOURGLASSleft = (sand[X] - 1, sand[Y])noWallLeft = left not in HOURGLASSnotOnLeftEdge = sand[X] > 0canFallLeft = (noSandBelowLeft and noWallBelowLeftand noWallLeft and notOnLeftEdge)# Check if the sand can fall to the right:belowRight = (sand[X] + 1, sand[Y] + 1)noSandBelowRight = belowRight not in allSandnoWallBelowRight = belowRight not in HOURGLASSright = (sand[X] + 1, sand[Y])noWallRight = right not in HOURGLASSnotOnRightEdge = sand[X] < SCREEN_WIDTH - 1canFallRight = (noSandBelowRight and noWallBelowRightand noWallRight and notOnRightEdge)# Set the falling direction:fallingDirection = Noneif canFallLeft and not canFallRight:fallingDirection = -1  # Set the sand to fall left.elif not canFallLeft and canFallRight:fallingDirection = 1  # Set the sand to fall right.elif canFallLeft and canFallRight:# Both are possible, so randomly set it:fallingDirection = random.choice((-1, 1))# Check if the sand can "far" fall two spaces to# the left or right instead of just one space:if random.random() * 100 <= WIDE_FALL_CHANCE:belowTwoLeft = (sand[X] - 2, sand[Y] + 1)noSandBelowTwoLeft = belowTwoLeft not in allSandnoWallBelowTwoLeft = belowTwoLeft not in HOURGLASSnotOnSecondToLeftEdge = sand[X] > 1canFallTwoLeft = (canFallLeft and noSandBelowTwoLeftand noWallBelowTwoLeft and notOnSecondToLeftEdge)belowTwoRight = (sand[X] + 2, sand[Y] + 1)noSandBelowTwoRight = belowTwoRight not in allSandnoWallBelowTwoRight = belowTwoRight not in HOURGLASSnotOnSecondToRightEdge = sand[X] < SCREEN_WIDTH - 2canFallTwoRight = (canFallRightand noSandBelowTwoRight and noWallBelowTwoRightand notOnSecondToRightEdge)if canFallTwoLeft and not canFallTwoRight:fallingDirection = -2elif not canFallTwoLeft and canFallTwoRight:fallingDirection = 2elif canFallTwoLeft and canFallTwoRight:fallingDirection = random.choice((-2, 2))if fallingDirection == None:# This sand can't fall, so move on.continue# Draw the sand in its new position:bext.goto(sand[X], sand[Y])print(' ', end='')  # Erase old sand.bext.goto(sand[X] + fallingDirection, sand[Y] + 1)print(SAND, end='')  # Draw new sand.# Move the grain of sand to its new position:allSand[i] = (sand[X] + fallingDirection, sand[Y] + 1)sandMovedOnThisStep = Truesys.stdout.flush()  # (Required for bext-using programs.)time.sleep(PAUSE_LENGTH)  # Pause after this# If no sand has moved on this step, reset the hourglass:if not sandMovedOnThisStep:time.sleep(2)# Erase all of the sand:for sand in allSand:bext.goto(sand[X], sand[Y])print(' ', end='')break  # Break out of main simulation loop.# If this program was run (instead of imported), run the game:
if __name__ == '__main__':try:main()except KeyboardInterrupt:sys.exit()  # When Ctrl-C is pressed, end the program. 

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

  • 创建除沙漏以外的墙壁形状。
  • 在屏幕上创建点,不断涌出新的沙粒。

探索程序

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

  1. 如果把第 31 行的range(18, 37)改成range(18, 30)会怎么样?
  2. 如果把第 39 行的range(8)改成range(0)会怎么样?
  3. 如果把第 82 行的sandMovedOnThisStep = False改成sandMovedOnThisStep = True会怎么样?
  4. 如果把 125 行的fallingDirection = None改成fallingDirection = 1会怎么样?
  5. 如果把 136 行的random.random() * 100 <= WIDE_FALL_CHANCE改成random.random() * 0 <= WIDE_FALL_CHANCE会怎么样?

三十七、饥饿机器人

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

你和饥饿的机器人被困在一个迷宫里!你不知道机器人为什么需要吃饭,但你也不想知道。机器人的程序设计很糟糕,即使被墙挡住,它们也会直接向你移动。你必须欺骗机器人互相碰撞(或死亡的机器人)而不被抓住。

你有一个个人传送装置,可以把你送到一个随机的新地方,但它的电池只够两次旅行。此外,你和机器人可以溜过角落!

运行示例

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

Hungry Robots, by Al Sweigart email@protected
`--snip--`
░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
░   ░ R             R ░  ░             ░
░ ░    ░░░   R░                    ░░  ░
░     ░ ░    ░ ░  ░         ░  ░░░     ░
░    R░   ░    ░      ░░   ░░     ░    ░
░ ░░  ░     ░ ░░░    ░           ░     ░
░ ░░    ░   RX░░░  ░  ░  ░      ░      ░
░          ░ R     R        R ░      ░ ░
░    ░   ░            ░        ░   R ░ ░
░ ░ R       R     ░   R ░   R          ░
░   ░  ░     ░       ░  ░       ░   ░  ░
░  @            ░          ░    R░░░ ░ ░
░   ░  ░░      ░░                 ░    ░
░  ░   ░░  ░            ░     R       ░░
░░X          ░  ░        ░ R ░░RR  ░ R ░
░RR R       R ░    ░          ░       R░
░   ░░  RRR   R                        ░
░           ░░R     ░                  ░
░      R  ░ ░                     ░    ░
░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
(T)eleports remaining: 2(Q) (W) ( )(A) (S) (D)
Enter move or QUIT: (Z) (X) ( )
`--snip--`

工作原理

在这个游戏中代表位置的 x 和 y 笛卡尔坐标允许我们使用数学来确定机器人应该移动的方向。在编程中,x 坐标向右增加,y 坐标向下增加。这意味着如果机器人的 x 坐标大于玩家的坐标,它应该向左移动(即代码应该从其当前的 x 坐标中减去)以靠近玩家。如果机器人的 x 坐标更小,它应该向右移动(也就是说,代码应该添加到其当前的 x 坐标中)。这同样适用于基于相对 y 坐标的上下移动。

"""Hungry Robots, by Al Sweigart email@protected
Escape the hungry robots by making them crash into each other.
This code is available at https://nostarch.com/big-book-small-python-programming
Tags: large, game"""import random, sys# Set up the constants:
WIDTH = 40           # (!) Try changing this to 70 or 10.
HEIGHT = 20          # (!) Try changing this to 10.
NUM_ROBOTS = 10      # (!) Try changing this to 1 or 30.
NUM_TELEPORTS = 2    # (!) Try changing this to 0 or 9999.
NUM_DEAD_ROBOTS = 2  # (!) Try changing this to 0 or 20.
NUM_WALLS = 100      # (!) Try changing this to 0 or 300.EMPTY_SPACE = ' '    # (!) Try changing this to '.'.
PLAYER = '@'         # (!) Try changing this to 'R'.
ROBOT = 'R'          # (!) Try changing this to '@'.
DEAD_ROBOT = 'X'     # (!) Try changing this to 'R'.# (!) Try changing this to '#' or 'O' or ' ':
WALL = chr(9617)  # Character 9617 is '░'def main():print('''Hungry Robots, by Al Sweigart email@protectedYou are trapped in a maze with hungry robots! You don't know why robots
need to eat, but you don't want to find out. The robots are badly
programmed and will move directly toward you, even if blocked by walls.
You must trick the robots into crashing into each other (or dead robots)
without being caught. You have a personal teleporter device, but it only
has enough battery for {} trips. Keep in mind, you and robots can slip
through the corners of two diagonal walls!
'''.format(NUM_TELEPORTS))input('Press Enter to begin...')# Set up a new game:board = getNewBoard()robots = addRobots(board)playerPosition = getRandomEmptySpace(board, robots)while True:  # Main game loop.displayBoard(board, robots, playerPosition)if len(robots) == 0:  # Check if the player has won.print('All the robots have crashed into each other and you')print('lived to tell the tale! Good job!')sys.exit()# Move the player and robots:playerPosition = askForPlayerMove(board, robots, playerPosition)robots = moveRobots(board, robots, playerPosition)for x, y in robots:  # Check if the player has lost.if (x, y) == playerPosition:displayBoard(board, robots, playerPosition)print('You have been caught by a robot!')sys.exit()def getNewBoard():"""Returns a dictionary that represents the board. The keys are(x, y) tuples of integer indexes for board positions, the values areWALL, EMPTY_SPACE, or DEAD_ROBOT. The dictionary also has the key'teleports' for the number of teleports the player has left.The living robots are stored separately from the board dictionary."""board = {'teleports': NUM_TELEPORTS}# Create an empty board:for x in range(WIDTH):for y in range(HEIGHT):board[(x, y)] = EMPTY_SPACE# Add walls on the edges of the board:for x in range(WIDTH):board[(x, 0)] = WALL  # Make top wall.board[(x, HEIGHT - 1)] = WALL  # Make bottom wall.for y in range(HEIGHT):board[(0, y)] = WALL  # Make left wall.board[(WIDTH - 1, y)] = WALL  # Make right wall.# Add the random walls:for i in range(NUM_WALLS):x, y = getRandomEmptySpace(board, [])board[(x, y)] = WALL# Add the starting dead robots:for i in range(NUM_DEAD_ROBOTS):x, y = getRandomEmptySpace(board, [])board[(x, y)] = DEAD_ROBOTreturn boarddef getRandomEmptySpace(board, robots):"""Return a (x, y) integer tuple of an empty space on the board."""while True:randomX = random.randint(1, WIDTH - 2)randomY = random.randint(1, HEIGHT - 2)if isEmpty(randomX, randomY, board, robots):breakreturn (randomX, randomY)def isEmpty(x, y, board, robots):"""Return True if the (x, y) is empty on the board and there's alsono robot there."""return board[(x, y)] == EMPTY_SPACE and (x, y) not in robotsdef addRobots(board):"""Add NUM_ROBOTS number of robots to empty spaces on the board andreturn a list of these (x, y) spaces where robots are now located."""robots = []for i in range(NUM_ROBOTS):x, y = getRandomEmptySpace(board, robots)robots.append((x, y))return robotsdef displayBoard(board, robots, playerPosition):"""Display the board, robots, and player on the screen."""# Loop over every space on the board:for y in range(HEIGHT):for x in range(WIDTH):# Draw the appropriate character:if board[(x, y)] == WALL:print(WALL, end='')elif board[(x, y)] == DEAD_ROBOT:print(DEAD_ROBOT, end='')elif (x, y) == playerPosition:print(PLAYER, end='')elif (x, y) in robots:print(ROBOT, end='')else:print(EMPTY_SPACE, end='')print()  # Print a newline.def askForPlayerMove(board, robots, playerPosition):"""Returns the (x, y) integer tuple of the place the player movesnext, given their current location and the walls of the board."""playerX, playerY = playerPosition# Find which directions aren't blocked by a wall:q = 'Q' if isEmpty(playerX - 1, playerY - 1, board, robots) else ' 'w = 'W' if isEmpty(playerX + 0, playerY - 1, board, robots) else ' 'e = 'E' if isEmpty(playerX + 1, playerY - 1, board, robots) else ' 'd = 'D' if isEmpty(playerX + 1, playerY + 0, board, robots) else ' 'c = 'C' if isEmpty(playerX + 1, playerY + 1, board, robots) else ' 'x = 'X' if isEmpty(playerX + 0, playerY + 1, board, robots) else ' 'z = 'Z' if isEmpty(playerX - 1, playerY + 1, board, robots) else ' 'a = 'A' if isEmpty(playerX - 1, playerY + 0, board, robots) else ' 'allMoves = (q + w + e + d + c + x + a + z + 'S')while True:# Get player's move:print('(T)eleports remaining: {}'.format(board["teleports"]))print('                    ({}) ({}) ({})'.format(q, w, e))print('                    ({}) (S) ({})'.format(a, d))print('Enter move or QUIT: ({}) ({}) ({})'.format(z, x, c))move = input('> ').upper()if move == 'QUIT':print('Thanks for playing!')sys.exit()elif move == 'T' and board['teleports'] > 0:# Teleport the player to a random empty space:board['teleports'] -= 1return getRandomEmptySpace(board, robots)elif move != '' and move in allMoves:# Return the new player position based on their move:return {'Q': (playerX - 1, playerY - 1),'W': (playerX + 0, playerY - 1),'E': (playerX + 1, playerY - 1),'D': (playerX + 1, playerY + 0),'C': (playerX + 1, playerY + 1),'X': (playerX + 0, playerY + 1),'Z': (playerX - 1, playerY + 1),'A': (playerX - 1, playerY + 0),'S': (playerX, playerY)}[move]def moveRobots(board, robotPositions, playerPosition):"""Return a list of (x, y) tuples of new robot positions after theyhave tried to move toward the player."""playerx, playery = playerPositionnextRobotPositions = []while len(robotPositions) > 0:robotx, roboty = robotPositions[0]# Determine the direction the robot moves.if robotx < playerx:movex = 1  # Move right.elif robotx > playerx:movex = -1  # Move left.elif robotx == playerx:movex = 0  # Don't move horizontally.if roboty < playery:movey = 1  # Move up.elif roboty > playery:movey = -1  # Move down.elif roboty == playery:movey = 0  # Don't move vertically.# Check if the robot would run into a wall, and adjust course:if board[(robotx + movex, roboty + movey)] == WALL:# Robot would run into a wall, so come up with a new move:if board[(robotx + movex, roboty)] == EMPTY_SPACE:movey = 0  # Robot can't move horizontally.elif board[(robotx, roboty + movey)] == EMPTY_SPACE:movex = 0  # Robot can't move vertically.else:# Robot can't move.movex = 0movey = 0newRobotx = robotx + movexnewRoboty = roboty + moveyif (board[(robotx, roboty)] == DEAD_ROBOTor board[(newRobotx, newRoboty)] == DEAD_ROBOT):# Robot is at a crash site, remove it.del robotPositions[0]continue# Check if it moves into a robot, then destroy both robots:if (newRobotx, newRoboty) in nextRobotPositions:board[(newRobotx, newRoboty)] = DEAD_ROBOTnextRobotPositions.remove((newRobotx, newRoboty))else:nextRobotPositions.append((newRobotx, newRoboty))# Remove robots from robotPositions as they move.del robotPositions[0]return nextRobotPositions# If this program was run (instead of imported), run the game:
if __name__ == '__main__':main() 

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

  • 创造两种不同的机器人:只能沿对角线移动的机器人和只能沿基本方向移动的机器人。
  • 给玩家一定数量的陷阱,他们可以留下来阻止任何机器人踩到陷阱。
  • 给玩家有限数量的“瞬间墙”,他们可以建立自己的防御。

探索程序

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

  1. 如果把第 22 行的WALL = chr(9617)改成WALL = 'R'会怎么样?
  2. 如果把 237 行的return nextRobotPositions改成return robotPositions会怎么样?
  3. 如果删除或注释掉第 44 行的displayBoard(board, robots, playerPosition)会发生什么?
  4. 如果删除或注释掉第 53 行的robots = moveRobots(board, robots, playerPosition)会发生什么?

三十八、我控诉

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

你就是举世闻名的大侦探玛蒂尔德·加缪。猫佐菲不见了,你必须筛选线索。嫌疑人要么总是说谎,要么总是说真话。你会及时找到猫佐菲并指控有罪的一方吗?

在这个游戏中,你乘出租车到城市的不同地点。每个地方都有一个嫌疑犯和一件物品。可以向嫌疑人询问其他嫌疑人和物品的情况,将他们的回答与自己的探索笔记进行对比,确定他们是在说谎还是在说真话。有些人会知道谁绑架了佐菲(或者她在哪里,或者在绑架者的位置发现了什么物品),但是你必须确定你是否能相信他们。你有五分钟时间找到罪犯,但是如果你三次指控错误,你就输了。这款游戏的灵感来源于 Homestar Runner 的“鸡蛋在哪里?”游戏。

运行示例

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

J'ACCUSE! (a mystery game)
`--snip--`
Time left: 5 min, 0 secYou are in your TAXI. Where do you want to go?
(A)LBINO ALLIGATOR PIT
(B)OWLING ALLEY
(C)ITY HALL
(D)UCK POND
(H)IPSTER CAFE
(O)LD BARN
(U)NIVERSITY LIBRARY
(V)IDEO GAME MUSEUM
(Z)OO
> aTime left: 4 min, 48 secYou are at the ALBINO ALLIGATOR PIT.ESPRESSA TOFFEEPOT with the ONE COWBOY BOOT is here.(J) "J'ACCUSE!" (3 accusations left)
(Z) Ask if they know where ZOPHIE THE CAT is.
(T) Go back to the TAXI.
(1) Ask about ESPRESSA TOFFEEPOT
(2) Ask about ONE COWBOY BOOT
> zThey give you this clue: "DUKE HAUTDOG"
Press Enter to continue...
`--snip--`

工作原理

要完全理解这个程序,您应该密切关注clues字典,它位于第 51 行到第 109 行。您可以取消对第 151 到 154 行的注释,以便在屏幕上显示它。这个字典有来自SUSPECTS列表的字符串作为键,有“线索字典”作为值。每个线索字典都包含来自SUSPECTSITEMS的字符串。当被问及另一个嫌疑人或物品时,最初的嫌疑人会用这些字符串回答。例如,如果clues['DUKE HAUTDOG']['CANDLESTICK']设定为'DUCK POND',那么当玩家向杜克·豪特多格询问烛台时,他们会说它在鸭塘。每次玩游戏时,嫌疑人、物品、地点和罪犯都会被洗牌。

这个程序的代码围绕着这个数据结构,所以理解它对于理解程序的其余部分是必要的。

"""J'ACCUSE!, by Al Sweigart email@protected
A mystery game of intrigue and a missing cat.
This code is available at https://nostarch.com/big-book-small-python-programming
Tags: extra-large, game, humor, puzzle"""# Play the original Flash game at:
# https://homestarrunner.com/videlectrix/wheresanegg.html
# More info at: http://www.hrwiki.org/wiki/Where's_an_Egg%3Fimport time, random, sys# Set up the constants:
SUSPECTS = ['DUKE HAUTDOG', 'MAXIMUM POWERS', 'BILL MONOPOLIS', 'SENATOR SCHMEAR', 'MRS. FEATHERTOSS', 'DR. JEAN SPLICER', 'RAFFLES THE CLOWN', 'ESPRESSA TOFFEEPOT', 'CECIL EDGAR VANDERTON']
ITEMS = ['FLASHLIGHT', 'CANDLESTICK', 'RAINBOW FLAG', 'HAMSTER WHEEL', 'ANIME VHS TAPE', 'JAR OF PICKLES', 'ONE COWBOY BOOT', 'CLEAN UNDERPANTS', '5 DOLLAR GIFT CARD']
PLACES = ['ZOO', 'OLD BARN', 'DUCK POND', 'CITY HALL', 'HIPSTER CAFE', 'BOWLING ALLEY', 'VIDEO GAME MUSEUM', 'UNIVERSITY LIBRARY', 'ALBINO ALLIGATOR PIT']
TIME_TO_SOLVE = 300  # 300 seconds (5 minutes) to solve the game.# First letters and longest length of places are needed for menu display:
PLACE_FIRST_LETTERS = {}
LONGEST_PLACE_NAME_LENGTH = 0
for place in PLACES:PLACE_FIRST_LETTERS[place[0]] = placeif len(place) > LONGEST_PLACE_NAME_LENGTH:LONGEST_PLACE_NAME_LENGTH = len(place)# Basic sanity checks of the constants:
assert len(SUSPECTS) == 9
assert len(ITEMS) == 9
assert len(PLACES) == 9
# First letters must be unique:
assert len(PLACE_FIRST_LETTERS.keys()) == len(PLACES)knownSuspectsAndItems = []
# visitedPlaces: Keys=places, values=strings of the suspect & item there.
visitedPlaces = {}
currentLocation = 'TAXI'  # Start the game at the taxi.
accusedSuspects = []  # Accused suspects won't offer clues.
liars = random.sample(SUSPECTS, random.randint(3, 4))
accusationsLeft = 3  # You can accuse up to 3 people.
culprit = random.choice(SUSPECTS)# Common indexes link these; e.g. SUSPECTS[0] and ITEMS[0] are at PLACES[0].
random.shuffle(SUSPECTS)
random.shuffle(ITEMS)
random.shuffle(PLACES)# Create data structures for clues the truth-tellers give about each
# item and suspect.
# clues: Keys=suspects being asked for a clue, value="clue dictionary".
clues = {}
for i, interviewee in enumerate(SUSPECTS):if interviewee in liars:continue  # Skip the liars for now.# This "clue dictionary" has keys=items & suspects,# value=the clue given.clues[interviewee] = {}clues[interviewee]['debug_liar'] = False  # Useful for debugging.for item in ITEMS:  # Select clue about each item.if random.randint(0, 1) == 0:  # Tells where the item is:clues[interviewee][item] = PLACES[ITEMS.index(item)]else:  # Tells who has the item:clues[interviewee][item] = SUSPECTS[ITEMS.index(item)]for suspect in SUSPECTS:  # Select clue about each suspect.if random.randint(0, 1) == 0:  # Tells where the suspect is:clues[interviewee][suspect] = PLACES[SUSPECTS.index(suspect)]else:  # Tells what item the suspect has:clues[interviewee][suspect] = ITEMS[SUSPECTS.index(suspect)]# Create data structures for clues the liars give about each item
# and suspect:
for i, interviewee in enumerate(SUSPECTS):if interviewee not in liars:continue  # We've already handled the truth-tellers.# This "clue dictionary" has keys=items & suspects,# value=the clue given:clues[interviewee] = {}clues[interviewee]['debug_liar'] = True  # Useful for debugging.# This interviewee is a liar and gives wrong clues:for item in ITEMS:if random.randint(0, 1) == 0:while True:  # Select a random (wrong) place clue.# Lies about where the item is.clues[interviewee][item] = random.choice(PLACES)if clues[interviewee][item] != PLACES[ITEMS.index(item)]:# Break out of the loop when wrong clue is selected.breakelse:while True:  # Select a random (wrong) suspect clue.clues[interviewee][item] = random.choice(SUSPECTS)if clues[interviewee][item] != SUSPECTS[ITEMS.index(item)]:# Break out of the loop when wrong clue is selected.breakfor suspect in SUSPECTS:if random.randint(0, 1) == 0:while True:  # Select a random (wrong) place clue.clues[interviewee][suspect] = random.choice(PLACES)if clues[interviewee][suspect] != PLACES[ITEMS.index(item)]:# Break out of the loop when wrong clue is selected.breakelse:while True:  # Select a random (wrong) item clue.clues[interviewee][suspect] = random.choice(ITEMS)if clues[interviewee][suspect] != ITEMS[SUSPECTS.index(suspect)]:# Break out of the loop when wrong clue is selected.break# Create the data structures for clues given when asked about Zophie:
zophieClues = {}
for interviewee in random.sample(SUSPECTS, random.randint(3, 4)):kindOfClue = random.randint(1, 3)if kindOfClue == 1:if interviewee not in liars:# They tell you who has Zophie.zophieClues[interviewee] = culpritelif interviewee in liars:while True:# Select a (wrong) suspect clue.zophieClues[interviewee] = random.choice(SUSPECTS)if zophieClues[interviewee] != culprit:# Break out of the loop when wrong clue is selected.breakelif kindOfClue == 2:if interviewee not in liars:# They tell you where Zophie is.zophieClues[interviewee] = PLACES[SUSPECTS.index(culprit)]elif interviewee in liars:while True:# Select a (wrong) place clue.zophieClues[interviewee] = random.choice(PLACES)if zophieClues[interviewee] != PLACES[SUSPECTS.index(culprit)]:# Break out of the loop when wrong clue is selected.breakelif kindOfClue == 3:if interviewee not in liars:# They tell you what item Zophie is near.zophieClues[interviewee] = ITEMS[SUSPECTS.index(culprit)]elif interviewee in liars:while True:# Select a (wrong) item clue.zophieClues[interviewee] = random.choice(ITEMS)if zophieClues[interviewee] != ITEMS[SUSPECTS.index(culprit)]:# Break out of the loop when wrong clue is selected.break# EXPERIMENT: Uncomment this code to view the clue data structures:
#import pprint
#pprint.pprint(clues)
#pprint.pprint(zophieClues)
#print('culprit =', culprit)# START OF THE GAME
print("""J'ACCUSE! (a mystery game)")
By Al Sweigart email@protected
Inspired by Homestar Runner\'s "Where\'s an Egg?" gameYou are the world-famous detective, Mathilde Camus.
ZOPHIE THE CAT has gone missing, and you must sift through the clues.
Suspects either always tell lies, or always tell the truth. Ask them
about other people, places, and items to see if the details they give are
truthful and consistent with your observations. Then you will know if
their clue about ZOPHIE THE CAT is true or not. Will you find ZOPHIE THE
CAT in time and accuse the guilty party?
""")
input('Press Enter to begin...')startTime = time.time()
endTime = startTime + TIME_TO_SOLVEwhile True:  # Main game loop.if time.time() > endTime or accusationsLeft == 0:# Handle "game over" condition:if time.time() > endTime:print('You have run out of time!')elif accusationsLeft == 0:print('You have accused too many innocent people!')culpritIndex = SUSPECTS.index(culprit)print('It was {} at the {} with the {} who catnapped her!'.format(culprit, PLACES[culpritIndex], ITEMS[culpritIndex]))print('Better luck next time, Detective.')sys.exit()print()minutesLeft = int(endTime - time.time()) // 60secondsLeft = int(endTime - time.time()) % 60print('Time left: {} min, {} sec'.format(minutesLeft, secondsLeft))if currentLocation == 'TAXI':print('  You are in your TAXI. Where do you want to go?')for place in sorted(PLACES):placeInfo = ''if place in visitedPlaces:placeInfo = visitedPlaces[place]nameLabel = '(' + place[0] + ')' + place[1:]spacing = " " * (LONGEST_PLACE_NAME_LENGTH - len(place))print('{}  {}{}'.format(nameLabel, spacing, placeInfo))print('(Q)UIT GAME')while True:  # Keep asking until a valid response is given.response = input('> ').upper()if response == '':continue  # Ask again.if response == 'Q':print('Thanks for playing!')sys.exit()if response in PLACE_FIRST_LETTERS.keys():breakcurrentLocation = PLACE_FIRST_LETTERS[response]continue  # Go back to the start of the main game loop.# At a place; player can ask for clues.print('  You are at the {}.'.format(currentLocation))currentLocationIndex = PLACES.index(currentLocation)thePersonHere = SUSPECTS[currentLocationIndex]theItemHere = ITEMS[currentLocationIndex]print(' {} with the {} is here.'.format(thePersonHere, theItemHere))# Add the suspect and item at this place to our list of known# suspects and items:if thePersonHere not in knownSuspectsAndItems:knownSuspectsAndItems.append(thePersonHere)if ITEMS[currentLocationIndex] not in knownSuspectsAndItems:knownSuspectsAndItems.append(ITEMS[currentLocationIndex])if currentLocation not in visitedPlaces.keys():visitedPlaces[currentLocation] = '({}, {})'.format(thePersonHere.lower(), theItemHere.lower())# If the player has accused this person wrongly before, they# won't give clues:if thePersonHere in accusedSuspects:print('They are offended that you accused them,')print('and will not help with your investigation.')print('You go back to your TAXI.')print()input('Press Enter to continue...')currentLocation = 'TAXI'continue  # Go back to the start of the main game loop.# Display menu of known suspects & items to ask about:print()print('(J) "J\'ACCUSE!" ({} accusations left)'.format(accusationsLeft))print('(Z) Ask if they know where ZOPHIE THE CAT is.')print('(T) Go back to the TAXI.')for i, suspectOrItem in enumerate(knownSuspectsAndItems):print('({}) Ask about {}'.format(i + 1, suspectOrItem))while True:  # Keep asking until a valid response is given.response = input('> ').upper()if response in 'JZT' or (response.isdecimal() and 0 < int(response) <= len(knownSuspectsAndItems)):breakif response == 'J':  # Player accuses this suspect.accusationsLeft -= 1  # Use up an accusation.if thePersonHere == culprit:# You've accused the correct suspect.print('You\'ve cracked the case, Detective!')print('It was {} who had catnapped ZOPHIE THE CAT.'.format(culprit))minutesTaken = int(time.time() - startTime) // 60secondsTaken = int(time.time() - startTime) % 60print('Good job! You solved it in {} min, {} sec.'.format(minutesTaken, secondsTaken))sys.exit()else:# You've accused the wrong suspect.accusedSuspects.append(thePersonHere)print('You have accused the wrong person, Detective!')print('They will not help you with anymore clues.')print('You go back to your TAXI.')currentLocation = 'TAXI'elif response == 'Z':  # Player asks about Zophie.if thePersonHere not in zophieClues:print('"I don\'t know anything about ZOPHIE THE CAT."')elif thePersonHere in zophieClues:print('  They give you this clue: "{}"'.format(zophieClues[thePersonHere]))# Add non-place clues to the list of known things:if zophieClues[thePersonHere] not in knownSuspectsAndItems and zophieClues[thePersonHere] not in PLACES:knownSuspectsAndItems.append(zophieClues[thePersonHere])elif response == 'T':  # Player goes back to the taxi.currentLocation = 'TAXI'continue  # Go back to the start of the main game loop.else:  # Player asks about a suspect or item.thingBeingAskedAbout = knownSuspectsAndItems[int(response) - 1]if thingBeingAskedAbout in (thePersonHere, theItemHere):print('  They give you this clue: "No comment."')else:print('  They give you this clue: "{}"'.format(clues[thePersonHere][thingBeingAskedAbout]))# Add non-place clues to the list of known things:if clues[thePersonHere][thingBeingAskedAbout] not in knownSuspectsAndItems and clues[thePersonHere][thingBeingAskedAbout] not in PLACES:knownSuspectsAndItems.append(clues[thePersonHere][thingBeingAskedAbout])input('Press Enter to continue...') 

探索程序

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

  1. 如果把第 16 行的TIME_TO_SOLVE = 300改成TIME_TO_SOLVE = 0会怎么样?
  2. 如果把 176 行的time.time() > endTime or accusationsLeft == 0改成time.time() > endTime and accusationsLeft == 0会怎么样?
  3. 如果把 198 行的place[1:]改成place会怎么样?
  4. 如果把 173 行的startTime + TIME_TO_SOLVE改成startTime * TIME_TO_SOLVE会怎么样?

三十九、兰顿的蚂蚁

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

兰顿的蚂蚁是二维网格上的元胞自动机模拟,类似于项目 13“康威的生命游戏”。在模拟中,一只“蚂蚁”从两种颜色之一的正方形开始。如果空间是第一种颜色,蚂蚁将它切换到第二种颜色,向右旋转 90 度,并向前移动一个空间。如果空间是第二种颜色,蚂蚁将它切换到第一种颜色,向左旋转 90 度,并向前移动一个空间。尽管规则非常简单,但模拟显示了复杂的突发行为。模拟可以在同一个空间中展示多只蚂蚁,当它们彼此相遇时,会产生有趣的互动。兰顿的蚂蚁是计算机科学家克里斯·兰顿在 1986 年发明的。更多关于兰顿蚂蚁的信息可以在en.wikipedia.org/wiki/Langton%27s_ant找到。

运行示例

图 39-1 显示了运行langtonsant.py时的输出。

f39001

:兰顿蚂蚁细胞自动机的催眠输出

工作原理

这个程序使用了两种“方向”的含义一方面,代表每只蚂蚁的字典存储了基本方向:北、南、东、西。然而,向左或向右(或逆时针和顺时针,因为我们是从上面看蚂蚁)是一个旋转方向。蚂蚁应该根据它们所站的瓷砖向左转或向右转,所以第 78 到 100 行根据蚂蚁当前的基本方向和它们转向的方向设置了一个新的基本方向。

"""Langton's Ant, by Al Sweigart email@protected
A cellular automata animation. Press Ctrl-C to stop.
More info: https://en.wikipedia.org/wiki/Langton%27s_ant
This code is available at https://nostarch.com/big-book-small-python-programming
Tags: large, artistic, bext, simulation"""import copy, random, sys, timetry: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
HEIGHT -= 1  # Adjustment for the quit message at the bottom.NUMBER_OF_ANTS = 10  # (!) Try changing this to 1 or 50.
PAUSE_AMOUNT = 0.1  # (!) Try changing this to 1.0 or 0.0.# (!) Try changing these to make the ants look different:
ANT_UP = '^'
ANT_DOWN = 'v'
ANT_LEFT = '<'
ANT_RIGHT = '>'# (!) Try changing these colors to one of 'black', 'red', 'green',
# 'yellow', 'blue', 'purple', 'cyan', or 'white'. (These are the only
# colors that the bext module supports.)
ANT_COLOR = 'red'
BLACK_TILE = 'black'
WHITE_TILE = 'white'NORTH = 'north'
SOUTH = 'south'
EAST = 'east'
WEST = 'west'def main():bext.fg(ANT_COLOR)  # The ants' color is the foreground color.bext.bg(WHITE_TILE)  # Set the background to white to start.bext.clear()# Create a new board data structure:board = {'width': WIDTH, 'height': HEIGHT}# Create ant data structures:ants = []for i in range(NUMBER_OF_ANTS):ant = {'x': random.randint(0, WIDTH - 1),'y': random.randint(0, HEIGHT - 1),'direction': random.choice([NORTH, SOUTH, EAST, WEST]),}ants.append(ant)# Keep track of which tiles have changed and need to be redrawn on# the screen:changedTiles = []while True:  # Main program loop.displayBoard(board, ants, changedTiles)changedTiles = []# nextBoard is what the board will look like on the next step in# the simulation. Start with a copy of the current step's board:nextBoard = copy.copy(board)# Run a single simulation step for each ant:for ant in ants:if board.get((ant['x'], ant['y']), False) == True:nextBoard[(ant['x'], ant['y'])] = False# Turn clockwise:if ant['direction'] == NORTH:ant['direction'] = EASTelif ant['direction'] == EAST:ant['direction'] = SOUTHelif ant['direction'] == SOUTH:ant['direction'] = WESTelif ant['direction'] == WEST:ant['direction'] = NORTHelse:nextBoard[(ant['x'], ant['y'])] = True# Turn counter clockwise:if ant['direction'] == NORTH:ant['direction'] = WESTelif ant['direction'] == WEST:ant['direction'] = SOUTHelif ant['direction'] == SOUTH:ant['direction'] = EASTelif ant['direction'] == EAST:ant['direction'] = NORTHchangedTiles.append((ant['x'], ant['y']))# Move the ant forward in whatever direction it's facing:if ant['direction'] == NORTH:ant['y'] -= 1if ant['direction'] == SOUTH:ant['y'] += 1if ant['direction'] == WEST:ant['x'] -= 1if ant['direction'] == EAST:ant['x'] += 1# If the ant goes past the edge of the screen,# it should wrap around to other side.ant['x'] = ant['x'] % WIDTHant['y'] = ant['y'] % HEIGHTchangedTiles.append((ant['x'], ant['y']))board = nextBoarddef displayBoard(board, ants, changedTiles):"""Displays the board and ants on the screen. The changedTilesargument is a list of (x, y) tuples for tiles on the screen thathave changed and need to be redrawn."""# Draw the board data structure:for x, y in changedTiles:bext.goto(x, y)if board.get((x, y), False):bext.bg(BLACK_TILE)else:bext.bg(WHITE_TILE)antIsHere = Falsefor ant in ants:if (x, y) == (ant['x'], ant['y']):antIsHere = Trueif ant['direction'] == NORTH:print(ANT_UP, end='')elif ant['direction'] == SOUTH:print(ANT_DOWN, end='')elif ant['direction'] == EAST:print(ANT_LEFT, end='')elif ant['direction'] == WEST:print(ANT_RIGHT, end='')breakif not antIsHere:print(' ', end='')# Display the quit message at the bottom of the screen:bext.goto(0, HEIGHT)bext.bg(WHITE_TILE)print('Press Ctrl-C to quit.', end='')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("Langton's Ant, by Al Sweigart email@protected")sys.exit()  # When Ctrl-C is pressed, end the program. 

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

  • 让玩家从文本文件中加载并保存棋盘的状态。
  • 使用新的移动规则创建额外的平铺状态,看看会出现什么行为。
  • 为兰顿的蚂蚁实现维基百科文章中建议的一些想法。

探索程序

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

  1. 如果把 149 行的print(' ', end='')改成print('.', end='')会怎么样?
  2. 如果把 106 行的ant['y'] += 1改成ant['y'] -= 1会怎么样?
  3. 如果把第 79 行的nextBoard[(ant['x'], ant['y'])] = False改成nextBoard[(ant['x'], ant['y'])] = True会怎么样?
  4. 如果把第 21 行的WIDTH -= 1改成WIDTH -= 40会怎么样?
  5. 如果把 119 行的board = nextBoard改成board = board会怎么样?

四十、黑客语

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

没有比用数字替换文本中的字母更好的方法来展示您疯狂的黑客技能了:m4d h4x0r 5k1llz!!!这个单词程序自动将普通英语转换成黑客语,这是最酷的在线交谈方式。或者至少是在 1993 年。

这需要一段时间来适应,但经过一些练习,你最终会流利地阅读黑客语。比如1t email@protected]<3s 4 w|-|1le +o g37 |_|s3|) 70, b|_|+ y0u (an 3\/3nt|_|/-\lly r3a|) l33t$peak phl|_|3n+ly。黑客语可能一开始很难读懂,但程序本身很简单,对初学者来说很好。更多关于黑客语的信息可以在en.wikipedia.org/wiki/Leet找到。

运行示例

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

L3375P34]< (leetspeek)
By Al Sweigart email@protectedEnter your leet message:
> I am a leet hacker. Fear my mad skills. The 90s were over two decades ago.! @m a l33t email@protected(]<er. email@protected my m4|) $k|ll$. +h3 90s w3r3 0ver tw0 d3(ad3$ 4g0.
(Copied leetspeak to clipboard.)

工作原理

第 36 行的charMapping变量中的字典将普通英语字符映射到黑客语字符。然而,由于可能有多个可能的黑客语字符(例如字母't''7''+'),charMapping字典中的每个值都是一个字符串列表。当创建新的黑客语字符串时,程序有 30%的机会简单地使用原始英文消息中的字符,有 70%的机会使用黑客语字符之一。这意味着同一个英语信息有多种可能的翻译。

"""Leetspeak, by Al Sweigart email@protected
Translates English messages into l33t5p34]<.
This code is available at https://nostarch.com/big-book-small-python-programming
Tags: tiny, beginner, word"""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.def main():print('''L3375P34]< (leetspeek)
By Al Sweigart email@protectedEnter your leet message:''')english = input('> ')print()leetspeak = englishToLeetspeak(english)print(leetspeak)try:# Trying to use pyperclip will raise a NameError exception if# it wasn't imported:pyperclip.copy(leetspeak)print('(Copied leetspeak to clipboard.)')except NameError:pass  # Do nothing if pyperclip wasn't installed.def englishToLeetspeak(message):"""Convert the English string in message and return leetspeak."""# Make sure all the keys in `charMapping` are lowercase.charMapping = {'a': ['4', '@', '/-\\'], 'c': ['('], 'd': ['|)'], 'e': ['3'],'f': ['ph'], 'h': [']-[', '|-|'], 'i': ['1', '!', '|'], 'k': [']<'],'o': ['0'], 's': ['$', '5'], 't': ['7', '+'], 'u': ['|_|'],'v': ['\\/']}leetspeak = ''for char in message:  # Check each character:# There is a 70% chance we change the character to leetspeak.if char.lower() in charMapping and random.random() <= 0.70:possibleLeetReplacements = charMapping[char.lower()]leetReplacement = random.choice(possibleLeetReplacements)leetspeak = leetspeak + leetReplacementelse:# Don't translate this character:leetspeak = leetspeak + charreturn leetspeak# If this program was run (instead of imported), run the game:
if __name__ == '__main__':main() 

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

  • 修改charMapping字典,使其支持新的黑客语字符。
  • 添加一个功能,可以将黑客语转换回简单的英语。

探索程序

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

  1. 如果把 51 行的return leetspeak改成return message会怎么样?
  2. 如果把第 44 行的char.lower()改成char会怎么样?
  3. 如果把第 44 行的char.lower()改成char.upper()会怎么样?
  4. 如果把第 47 行的leetspeak = leetspeak + leetReplacement改成leetspeak = leetReplacement会怎么样?

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

相关文章

7 年 Python 的我,总结了这 90 条写 Python 程序的建议

本文于网络整理&#xff0c;版权归原作者所有 自己写 Python 也有四五年了&#xff0c;一直是用自己的“强迫症”在维持自己代码的质量。都有去看Google的Python代码规范&#xff0c;对这几年的工作经验&#xff0c;做个简单的笔记&#xff0c;如果你也在学pythpn&#xff0c;准…

pot lib:optimal transport python库

文章目录 transport1. [计算最优传输&#xff08;Computational Optimal Transport&#xff09;](https://zhuanlan.zhihu.com/p/94978686)2. 离散测度 (Discrete measures), 蒙日(Monge)问题, Kantorovich Relaxation (松弛的蒙日问题)3. scipy.stats.wasserstein_distance 距…

Python 小型项目大全 46~50

# 四十六、百万骰子投掷统计模拟器 原文&#xff1a;http://inventwithpython.com/bigbookpython/project46.html 当你掷出两个六面骰子时&#xff0c;有 17%的机会掷出 7。这比掷出 2 的几率好得多&#xff1a;只有 3%。这是因为只有一种掷骰子的组合给你 2&#xff08;当两个…

在 Python 中完成的一些大型项目有哪些?

在本文中&#xff0c;我们将了解一些在 Python 中完成的大型项目。 Python是目前最流行的编程语言之一。这一趋势似乎将在 2022 年及以后继续下去。所以&#xff0c;如果你刚刚开始使用Python&#xff0c;你能做的最好的事情就是研究一些现实世界的Python项目想法。 Python 是…

PBL Python 学习——第0天

一个月PBL Python学习 第一章 Python环境的基本搭建 文章目录 一个月PBL Python学习前言一、Python下载二、Pycharm下载和配置1.Pycharm下载macOS查看方法第一步第二步第三步 Windows 2.Pycharm配置macOSWindows 总结 前言 本人是一位中学生&#xff0c;python新手&#xff0…

Python 小型项目大全 61~65

六十一、ROT13 密码 原文&#xff1a;http://inventwithpython.com/bigbookpython/project61.html ROT13 密码是最简单的加密算法之一&#xff0c;代表“旋转 13 个空格”密码将字母A到Z表示为数字 0 到 25&#xff0c;加密后的字母距离明文字母 13 个空格&#xff1a; A变成N&…

7个Python实战项目代码,让你分分钟晋级大老

关于Python有一句名言&#xff1a;不要重复造轮子。 但是问题有三个&#xff1a; 1、你不知道已经有哪些轮子已经造好了&#xff0c;哪个适合你用。有名有姓的的著名轮子就400多个&#xff0c;更别说没名没姓自己在制造中的轮子。 2、确实没重复造轮子&#xff0c;但是在重复…

Python 小型项目大全 76~81

七十六、井字棋 原文&#xff1a;http://inventwithpython.com/bigbookpython/project76.html 井字棋是一种在3 3网格上玩的经典纸笔游戏。玩家轮流放置 X 或 O 标记&#xff0c;试图连续获得三个。大多数井字棋都以平局告终&#xff0c;但如果你的对手不小心&#xff0c;你也…

Python 小型项目大全 66~70

六十六、简单替换密码 原文&#xff1a;http://inventwithpython.com/bigbookpython/project66.html 简单替换密码用一个字母代替另一个字母。由于字母A有 26 种可能的替换&#xff0c;B有 25 种可能的替换&#xff0c;C有 24 种可能的替换&#xff0c;等等&#xff0c;所以可能…

河北软件职业技术学院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;薪资都从之…