Python 小型项目大全 76~81

七十六、井字棋

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

井字棋是一种在3 × 3网格上玩的经典纸笔游戏。玩家轮流放置 X 或 O 标记,试图连续获得三个。大多数井字棋都以平局告终,但如果你的对手不小心,你也有可能智胜他们。

运行示例

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

Welcome to Tic-Tac-Toe!

       | |   1 2 3
      -+-+-
       | |   4 5 6
      -+-+-
       | |   7 8 9
What is X's move? (1-9)
> 1

      X| |   1 2 3
      -+-+-
       | |   4 5 6
      -+-+-
       | |   7 8 9
What is O's move? (1-9)
`--snip--`
      X|O|X  1 2 3
      -+-+-
      X|O|O  4 5 6
      -+-+-
      O|X|X  7 8 9
The game is a tie!
Thanks for playing!

工作原理

为了在这个程序中表示井字棋棋盘,我们使用了一个字典,用键'1''9'来表示棋盘上的空格。数字空间的排列方式与手机键盘相同。本词典中的值是代表球员标记的字符串'X''O'和代表空白的' '

"""Tic-Tac-Toe, by Al Sweigart email@protected
The classic board game.
This code is available at https://nostarch.com/big-book-small-python-programming
Tags: short, board game, game, two-player"""

ALL_SPACES = ['1', '2', '3', '4', '5', '6', '7', '8', '9']
X, O, BLANK = 'X', 'O', ' '  # Constants for string values.


def main():
   print('Welcome to Tic-Tac-Toe!')
   gameBoard = getBlankBoard()  # Create a TTT board dictionary.
   currentPlayer, nextPlayer = X, O  # X goes first, O goes next.

   while True:  # Main game loop.
       # Display the board on the screen:
       print(getBoardStr(gameBoard))

       # Keep asking the player until they enter a number 1-9:
       move = None
       while not isValidSpace(gameBoard, move):
           print('What is {}\'s move? (1-9)'.format(currentPlayer))
           move = input('> ')
       updateBoard(gameBoard, move, currentPlayer)  # Make the move.

       # Check if the game is over:
       if isWinner(gameBoard, currentPlayer):  # Check for a winner.
           print(getBoardStr(gameBoard))
           print(currentPlayer + ' has won the game!')
           break
       elif isBoardFull(gameBoard):  # Check for a tie.
           print(getBoardStr(gameBoard))
           print('The game is a tie!')
           break
       # Switch turns to the next player:
       currentPlayer, nextPlayer = nextPlayer, currentPlayer
   print('Thanks for playing!')


def getBlankBoard():
   """Create a new, blank tic-tac-toe board."""
   # Map of space numbers: 1|2|3
   #                       -+-+-
   #                       4|5|6
   #                       -+-+-
   #                       7|8|9
   # Keys are 1 through 9, the values are X, O, or BLANK:
   board = {}
   for space in ALL_SPACES:
       board[space] = BLANK  # All spaces start as blank.
   return board


def getBoardStr(board):
   """Return a text-representation of the board."""
   return '''
{}|{}|{} 1 2 3
     -+-+-
{}|{}|{} 4 5 6
     -+-+-
{}|{}|{} 7 8 9'''.format(board['1'], board['2'], board['3'],
                               board['4'], board['5'], board['6'],
                               board['7'], board['8'], board['9'])

def isValidSpace(board, space):
   """Returns True if the space on the board is a valid space number
   and the space is blank."""
   return space in ALL_SPACES and board[space] == BLANK


def isWinner(board, player):
   """Return True if player is a winner on this TTTBoard."""
   # Shorter variable names used here for readablility:
   b, p = board, player
   # Check for 3 marks across 3 rows, 3 columns, and 2 diagonals.
   return ((b['1'] == b['2'] == b['3'] == p) or  # Across top
           (b['4'] == b['5'] == b['6'] == p) or  # Across middle
           (b['7'] == b['8'] == b['9'] == p) or  # Across bottom
           (b['1'] == b['4'] == b['7'] == p) or  # Down left
           (b['2'] == b['5'] == b['8'] == p) or  # Down middle
           (b['3'] == b['6'] == b['9'] == p) or  # Down right
           (b['3'] == b['5'] == b['7'] == p) or  # Diagonal
           (b['1'] == b['5'] == b['9'] == p))    # Diagonal

def isBoardFull(board):
   """Return True if every space on the board has been taken."""
   for space in ALL_SPACES:
       if board[space] == BLANK:
           return False  # If any space is blank, return False.
   return True  # No spaces are blank, so return True.


def updateBoard(board, space, mark):
   """Sets the space on the board to mark."""
   board[space] = mark


if __name__ == '__main__':
   main()  # Call main() if this module is run, but not when imported. 

探索程序

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

  1. 如果把第 7 行的X, O, BLANK = 'X', 'O', ' '改成X, O, BLANK = 'X', 'X', ' '会怎么样?
  2. 如果把第 95 行的board[space] = mark改成board[space] = X会怎么样?
  3. 如果把第 50 行的board[space] = BLANK改成board[space] = X会怎么样?

七十七、汉诺塔

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

汉诺塔是一款移动堆叠的益智游戏,有三根柱子,你可以在上面堆叠不同大小的圆盘。游戏的目标是将一个塔盘移到另一个柱子上。但是,一次只能移动一个磁盘,较大的磁盘不能放在较小的磁盘上。找出某种模式将有助于你解决这个难题。你能发现它吗?(提示:尝试将TOTAL_DISKS变量设置为34,以先解决一个更简单的版本。)

运行示例

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

The Tower of Hanoi, by Al Sweigart email@protected

Move the tower of disks, one disk at a time, to another tower. Larger
disks cannot rest on top of a smaller disk.

More info at https://en.wikipedia.org/wiki/Tower_of_Hanoi

     ||          ||          ||
    @email@protected         ||          ||
   @@email@protected@        ||          ||
  @@@email@protected@@       ||          ||
 @@@@email@protected@@@      ||          ||
@@@@@email@protected@@@@     ||          ||
      A           B           C

Enter the letters of "from" and "to" towers, or QUIT.
(e.g. AB to moves a disk from tower A to tower B.)
> ab
     ||          ||          ||
     ||          ||          ||
   @@email@protected@        ||          ||
  @@@email@protected@@       ||          ||
 @@@@email@protected@@@      ||          ||
@@@@@email@protected@@@@    @email@protected         ||
      A           B           C

Enter the letters of "from" and "to" towers, or QUIT.
(e.g. AB to moves a disk from tower A to tower B.)
`--snip--`

工作原理

表示塔的数据结构是一个整数列表。每个整数都是磁盘的大小。列表中的第一个整数代表底部磁盘,最后一个整数代表顶部磁盘。例如,[5, 4, 2]将代表以下塔:

 ||
     ||
   @@email@protected@
 @@@@email@protected@@@
@@@@@email@protected@@@@

Python 的append()pop()列表方法可以分别在列表末尾添加和删除值。正如someList[0]someList[1]允许我们访问列表中的第一个和第二个值一样,Python 允许我们使用负索引来访问列表末尾的值,使用像someList[-1]someList[-2]这样的表达式,它们分别访问列表中的最后一个和倒数第二个值。这对于查找当前位于塔顶的磁盘非常有用。

"""The Tower of Hanoi, by Al Sweigart email@protected
A stack-moving puzzle game.
This code is available at https://nostarch.com/big-book-small-python-programming
Tags: short, game, puzzle"""

import copy
import sys

TOTAL_DISKS = 5  # More disks means a more difficult puzzle.

# Start with all disks on tower A:
COMPLETE_TOWER = list(range(TOTAL_DISKS, 0, -1))


def main():
   print("""The Tower of Hanoi, by Al Sweigart email@protected

Move the tower of disks, one disk at a time, to another tower. Larger
disks cannot rest on top of a smaller disk.

More info at https://en.wikipedia.org/wiki/Tower_of_Hanoi
"""
   )

   # Set up the towers. The end of the list is the top of the tower.
   towers = {'A': copy.copy(COMPLETE_TOWER), 'B': [], 'C': []}

   while True:  # Run a single turn.
       # Display the towers and disks:
       displayTowers(towers)

       # Ask the user for a move:
       fromTower, toTower = askForPlayerMove(towers)

       # Move the top disk from fromTower to toTower:
       disk = towers[fromTower].pop()
       towers[toTower].append(disk)

       # Check if the user has solved the puzzle:
       if COMPLETE_TOWER in (towers['B'], towers['C']):
           displayTowers(towers)  # Display the towers one last time.
           print('You have solved the puzzle! Well done!')
           sys.exit()


def askForPlayerMove(towers):
   """Asks the player for a move. Returns (fromTower, toTower)."""

   while True:  # Keep asking player until they enter a valid move.
       print('Enter the letters of "from" and "to" towers, or QUIT.')
       print('(e.g. AB to moves a disk from tower A to tower B.)')
       response = input('> ').upper().strip()

       if response == 'QUIT':
           print('Thanks for playing!')
           sys.exit()

       # Make sure the user entered valid tower letters:
       if response not in ('AB', 'AC', 'BA', 'BC', 'CA', 'CB'):
           print('Enter one of AB, AC, BA, BC, CA, or CB.')
           continue  # Ask player again for their move.

       # Syntactic sugar - Use more descriptive variable names:
       fromTower, toTower = response[0], response[1]

       if len(towers[fromTower]) == 0:
           # The "from" tower cannot be an empty tower:
           print('You selected a tower with no disks.')
           continue  # Ask player again for their move.
       elif len(towers[toTower]) == 0:
           # Any disk can be moved onto an empty "to" tower:
           return fromTower, toTower
       elif towers[toTower][-1] < towers[fromTower][-1]:
           print('Can\'t put larger disks on top of smaller ones.')
           continue  # Ask player again for their move.
       else:
           # This is a valid move, so return the selected towers:
           return fromTower, toTower


def displayTowers(towers):
   """Display the current state."""

   # Display the three towers:
   for level in range(TOTAL_DISKS, -1, -1):
       for tower in (towers['A'], towers['B'], towers['C']):
           if level >= len(tower):
               displayDisk(0)  # Display the bare pole with no disk.
           else:
               displayDisk(tower[level])  # Display the disk.
       print()

   # Display the tower labels A, B, and C.
   emptySpace = ' ' * (TOTAL_DISKS)
   print('{0} A{0}{0} B{0}{0} C\n'.format(emptySpace))


def displayDisk(width):
   """Display a disk of the given width. A width of 0 means no disk."""
    emptySpace = ' ' * (TOTAL_DISKS - width)

    if width == 0:
        # Display a pole segment without a disk:
        print(emptySpace + '||' + emptySpace, end='')
    else:
        # Display the disk:
        disk = '@' * width
        numLabel = str(width).rjust(2, '_')
        print(emptySpace + disk + numLabel + disk + emptySpace, end='')


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

探索程序

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

  1. 如果删除或注释掉第 73、74 和 75 行会发生什么?
  2. 如果把第 100 行的emptySpace = ' ' * (TOTAL_DISKS - width)改成emptySpace = ' '会怎么样?
  3. 如果把 102 行的width == 0改成width != 0会怎么样?

七十八、脑筋急转弯

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

一块黄色的石头扔进蓝色的池塘会变成什么?英国有 7 月 4 日吗?医生怎么能 30 天不睡觉?不管你认为这些问题的答案是什么,你可能都错了。这个项目中的 54 个问题都是经过精心设计的,因此它们的答案简单、明显且容易误导人。找到真正的答案需要一些小聪明。

复制这本书的代码会破坏乐趣,因为你会看到答案,所以你可能想在看源代码之前下载并玩这个来自inventwithpython.com/trickquestions.py的游戏。

运行示例

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

Trick Questions, by Al Sweigart email@protected

Can you figure out the answers to these trick questions?
(Enter QUIT to quit at any time.)

Press Enter to begin...
`--snip--`
Question: 1
Score: 0 / 54
QUESTION: A 39 year old person was born on the 22nd of February. What year is their birthday?
  ANSWER: 1981
Incorrect! The answer is: Their birthday is on February 22nd of every year.
Press Enter for the next question...
`--snip--`
Question: 2
Score: 0 / 54
QUESTION: If there are ten apples and you take away two, how many do you have?
  ANSWER: Eight
Incorrect! The answer is: Two.
Press Enter for the next question...
`--snip--`

工作原理

QUESTIONS变量保存一个字典列表。每个字典代表一个单独的难题,并且有关键字'question''answer''accept''question''answer'的值分别是程序向玩家提出问题并给出答案时显示的字符串。'accept'键的值是一个字符串列表。如果玩家输入包含任何这些字符串的响应,它将被认为是正确的。这允许玩家输入自由格式的文本作为回复。该程序在检测他们何时提供了正确答案方面相当准确。

"""Trick Questions, by Al Sweigart email@protected
A quiz of several trick questions.
This code is available at https://nostarch.com/big-book-small-python-programming
Tags: large, humor"""

import random, sys

# QUESTIONS is a list of dictionaries, each dictionary represents a
# trick question and its answer. The dictionary has the keys 'question'
# (which holds the text of the question), 'answer' (which holds the text
# of the answer), and 'accept' (which holds a list of strings that, if
# the player's answer contains any of, they've answered correctly).
# (!) Try coming up with your own trick questions to add here:
QUESTIONS = [
{'question': "How many times can you take 2 apples from a pile of 10 apples?",
 'answer': "Once. Then you have a pile of 8 apples.",
 'accept': ['once', 'one', '1']},
{'question': 'What begins with "e" and ends with "e" but only has one letter in it?',
 'answer': "An envelope.",
 'accept': ['envelope']},
{'question': "Is it possible to draw a square with three sides?",
 'answer': "Yes. All squares have three sides. They also have a fourth side.",
 'accept': ['yes']},
{'question': "How many times can a piece of paper be folded in half by hand without unfolding?",
 'answer': "Once. Then you are folding it in quarters.",
 'accept': ['one', '1', 'once']},
{'question': "What does a towel get as it dries?",
 'answer': "Wet.",
 'accept': ['wet']},
{'question': "What does a towel get as it dries?",
 'answer': "Drier.",
 'accept': ['drier', 'dry']},
{'question': "Imagine you are in a haunted house full of evil ghosts. What do you have to do to stay safe?",
 'answer': "Nothing. You're only imagining it.",
 'accept': ['nothing', 'stop']},
{'question': "A taxi driver is going the wrong way down a one-way street. She passes ten cops but doesn't get a ticket. Why not?",
 'answer': "She was walking.",
 'accept': ['walk']},
{'question': "What does a yellow stone thrown into a blue pond become?",
 'answer': "Wet.",
 'accept': ['wet']},
{'question': "How many miles does must a cyclist bike to get to training?",
 'answer': "None. They're training as soon as they get on the bike.",
 'accept': ['none', 'zero', '0']},
{'question': "What building do people want to leave as soon as they enter?",
 'answer': "An airport.",
 'accept': ['airport', 'bus', 'port', 'train', 'station', 'stop']},
{'question': "If you're in the middle of a square house facing the west side with the south side to your left and the north side to your right, which side of the house are you next to?",
 'answer': "None. You're in the middle.",
 'accept': ['none', 'middle', 'not', 'any']},
{'question': "How much dirt is in a hole 3 meters wide, 3 meters long, and 3 meters deep?",
 'answer': "There is no dirt in a hole.",
 'accept': ['no', 'none', 'zero']},
{'question': "A girl mails a letter from America to Japan. How many miles did the stamp move?",
 'answer': "Zero. The stamp was in the same place on the envelope the whole time.",
 'accept': ['zero', '0', 'none', 'no']},
{'question': "What was the highest mountain on Earth the day before Mount Everest was discovered?",
 'answer': "Mount Everest was still the highest mountain of Earth the day before it was discovered.",
 'accept': ['everest']},
{'question': "How many fingers do most people have on their two hands?",
 'answer': "Eight. They also have two thumbs.",
 'accept': ['eight', '8']},
{'question': "The 4th of July is a holiday in America. Do they have a 4th of July in England?",
 'answer': "Yes. All countries have a 4th of July on their calendar.",
 'accept': ['yes']},
{'question': "Which letter of the alphabet makes honey?",
 'answer': "None. A bee is an insect, not a letter.",
 'accept': ['no', 'none', 'not']},
{'question': "How can a doctor go 30 days without sleep?",
 'answer': "By sleeping at night.",
 'accept': ['night', 'evening']},
{'question': "How many months have 28 days?",
 'answer': "12\. All months have 28 days. Some have more days as well.",
 'accept': ['12', 'twelve', 'all']},
{'question': "How many two cent stamps are in a dozen?",
 'answer': "A dozen.",
 'accept': ['12', 'twelve', 'dozen']},
{'question': "Why is it illegal for a person living in North Dakota to be buried in South Dakota?",
 'answer': "Because it is illegal to bury someone alive.",
 'accept': ['alive', 'living', 'live']},
{'question': "How many heads does a two-headed coin have?",
 'answer': "Zero. Coins are just circular pieces of metal. They don't have heads.",
 'accept': ['zero', 'none', 'no', '0']},
{'question': "What kind of vehicle has four wheels and flies?",
 'answer': "A garbage truck.",
 'accept': ['garbage', 'dump', 'trash']},
{'question': "What kind of vehicle has four wheels and flies?",
 'answer': "An airplane.",
 'accept': ['airplane', 'plane']},
{'question': "What five-letter word becomes shorter by adding two letters?",
 'answer': "Short.",
 'accept': ['short']},
{'question': "Gwen's mother has five daughters. Four are named Haha, Hehe, Hihi, and Hoho. What's the fifth daughter's name?",
 'answer': "Gwen.",
 'accept': ['gwen']},
{'question': "How long is a fence if there are three fence posts each one meter apart?",
 'answer': "Two meters long.",
 'accept': ['2', 'two']},
{'question': "How many legs does a dog have if you count its tail as a leg?",
  'answer': "Four. Calling a tail a leg doesn't make it one.",
  'accept': ['four', '4']},
 {'question': "How much more are 1976 pennies worth compared to 1975 pennies?",
  'answer': "One cent.",
  'accept': ['1', 'one']},
 {'question': "What two things can you never eat for breakfast?",
  'answer': "Lunch and dinner.",
  'accept': ['lunch', 'dinner', 'supper']},
 {'question': "How many birthdays does the average person have?",
  'answer': "One. You're only born once.",
  'accept': ['one', '1', 'once' 'born']},
 {'question': "Where was the United States Declaration of Independence signed?",
  'answer': "It was signed at the bottom.",
  'accept': ['bottom']},
 {'question': "A person puts two walnuts in their pocket but only has one thing in their pocket five minutes later. What is it?",
  'answer': "A hole.",
  'accept': ['hole']},
 {'question': "What did the sculptor make that no one could see?",
  'answer': "Noise.",
  'accept': ['noise']},
 {'question': "If you drop a raw egg on a concrete floor, will it crack?",
  'answer': "No. Concrete is very hard to crack.",
  'accept': ['no']},
 {'question': "If it takes ten people ten hours to build a fence, how many hours does it take five people to build it?",
  'answer': "Zero. It's already built.",
  'accept': ['zero', 'no', '0', 'already', 'built']},
 {'question': "Which is heavier, 100 pounds of rocks or 100 pounds of feathers?",
  'answer': "Neither. They weigh the same.",
  'accept': ['neither', 'none', 'no', 'same', 'even', 'balance']},
 {'question': "What do you have to do to survive being bitten by a poisonous snake?",
  'answer': "Nothing. Only venomous snakes are deadly.",
  'accept': ['nothing', 'anything']},
 {'question': "What three consecutive days don't include Sunday, Wednesday, or Friday?",
  'answer': "Yesterday, today, and tomorrow.",
  'accept': ['yesterday', 'today', 'tomorrow']},
 {'question': "If there are ten apples and you take away two, how many do you have?",
  'answer': "Two.",
  'accept': ['2', 'two']},
 {'question': "A 39 year old person was born on the 22nd of February. What year is their birthday?",
  'answer': "Their birthday is on February 22nd of every year.",
  'accept': ['every', 'each']},
 {'question': "How far can you walk in the woods?",
  'answer': "Halfway. Then you are walking out of the woods.",
  'accept': ['half', '1/2']},
 {'question': "Can a man marry his widow's sister?",
  'answer': "No, because he's dead.",
  'accept': ['no']},
 {'question': "What do you get if you divide one hundred by half?",
  'answer': "One hundred divided by half is two hundred. One hundred divided by two is fifty.",
  'accept': ['two', '200']},
 {'question': "What do you call someone who always knows where their spouse is?",
  'answer': "A widow or widower.",
  'accept': ['widow', 'widower']},
 {'question': "How can someone take a photo but not be a photographer?",
  'answer': "They can be a thief.",
  'accept': ['thief', 'steal', 'take', 'literal']},
 {'question': "An electric train leaves the windy city of Chicago at 4pm on a Monday heading south at 100 kilometers per hour. Which way does the smoke blow from the smokestack?",
  'answer': "Electric trains don't have smokestacks.",
  'accept': ["don't", "doesn't", 'not', 'no', 'none']},
 {'question': 'What is the only word that rhymes with "orange"?',
  'answer': "Orange.",
  'accept': ['orange']},
 {'question': "Who is the U.S. President if the U.S. Vice President dies?",
  'answer': "The current U.S. President.",
  'accept': ['president', 'current', 'already']},
 {'question': "A doctor gives you three pills with instructions to take one every half-hour. How long will the pills last?",
  'answer': "One hour.",
  'accept': ['1', 'one']},
 {'question': "Where is there an ocean with no water?",
  'answer': "On a map.",
  'accept': ['map']},
 {'question': "What is the size of a rhino but weighs nothing?",
  'answer': "A rhino's shadow.",
  'accept': ['shadow']},
 {'question': "The clerk at a butcher shop is exactly 177 centimeters tall. What do they weigh?",
  'answer': "The clerk weighs meat.",
  'accept': ['meat']}]

CORRECT_TEXT = ['Correct!', 'That is right.', "You're right.",
                    'You got it.', 'Righto!']
INCORRECT_TEXT = ['Incorrect!', "Nope, that isn't it.", 'Nope.',
                      'Not quite.', 'You missed it.']

print('''Trick Questions, by Al Sweigart email@protected

Can you figure out the answers to these trick questions?
(Enter QUIT to quit at any time.)
''')

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

random.shuffle(QUESTIONS)
score = 0

for questionNumber, qa in enumerate(QUESTIONS):  # Main program loop.
    print('\n' * 40)  # "Clear" the screen.
    print('Question:', questionNumber + 1)
    print('Score:', score, '/', len(QUESTIONS))
    print('QUESTION:', qa['question'])
    response = input('  ANSWER: ').lower()

    if response == 'quit':
        print('Thanks for playing!')
        sys.exit()

    correct = False
    for acceptanceWord in qa['accept']:
        if acceptanceWord in response:
            correct = True

    if correct:
        text = random.choice(CORRECT_TEXT)
        print(text, qa['answer'])
        score += 1
    else:
        text = random.choice(INCORRECT_TEXT)
        print(text, 'The answer is:', qa['answer'])
    response = input('Press Enter for the next question...').lower()

    if response == 'quit':
        print('Thanks for playing!')
        sys.exit()

print("That's all the questions. Thanks for playing!") 

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

探索程序

这是一个基础程序,所以没有太多的选项来定制它。相反,考虑一下问答节目的其他用途。

七十九、2048

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

网络开发者 Gabriele Cirulli 在一个周末就发明了游戏 2048。它的灵感来自于 Veewo 工作室的 1024 游戏,而这个游戏的灵感又来自于 Threes!,开发团队 Sirvo 的一款游戏。2048,你必须在一个4 × 4的板上合并数字,才能把它们从屏幕上清除。两个 2 合并成一个 4,两个 4 合并成一个 8,以此类推。每次合并时,游戏都会在棋盘上添加一个新的 2。目标是在整个董事会填满之前达到 2048。

运行示例

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

Twenty Forty-Eight, by Al Sweigart email@protected
`--snip--`
+-----+-----+-----+-----+
|     |     |     |     |
|     |     |  2  |  16 |
|     |     |     |     |
+-----+-----+-----+-----+
|     |     |     |     |
|     |  16 |  4  |  2  |
|     |     |     |     |
+-----+-----+-----+-----+
|     |     |     |     |
|  2  |     |  4  |  32 |
|     |     |     |     |
+-----+-----+-----+-----+
|     |     |     |     |
|     |     |     |  2  |
|     |     |     |     |
+-----+-----+-----+-----+

Score: 80
Enter move: (WASD or Q to quit)
`--snip--`

工作原理

这个程序使用“列”数据结构实现它的滑动行为,由四个字符串列表表示:BLANK(一个单空格字符串)、'2''4''8'等等。该列表中的第一个值表示列的底部,而最后一个值表示列的顶部。无论玩家向上、向下、向左或向右滑动牌,组合在一列中的数字总是向下滑动。想象一下重力将瓷砖拉向这些方向。例如,图 79-1 显示了一块向右滑动的棋盘。我们将创建四个列表来表示列:

  • ['2', '4', '8', ' ']
  • [' ', ' ', ' ', '4']
  • [' ', ' ', ' ', '2']
  • [' ', ' ', ' ', ' ']

combineTilesInColumn()函数接受一个列列表并返回另一个列列表,匹配的数字被组合并向底部移动。调用combineTilesInColumn()的代码负责在适当的方向创建列列表,并用返回的列表更新游戏板。

f79001

:游戏板向右滑动时的列(高亮显示)

"""Twenty Forty-Eight, by Al Sweigart email@protected
A sliding tile game to combine exponentially-increasing numbers.
Inspired by Gabriele Cirulli's 2048, which is a clone of Veewo Studios'
1024, which in turn is a clone of the Threes! game.
More info at https://en.wikipedia.org/wiki/2048_(video_game)
This code is available at https://nostarch.com/big-book-small-python-programming
Tags: large, game, puzzle"""

import random, sys

# Set up the constants:
BLANK = ''  # A value that represents a blank space on the board.


def main():
   print('''Twenty Forty-Eight, by Al Sweigart email@protected

Slide all the tiles on the board in one of four directions. Tiles with
like numbers will combine into larger-numbered tiles. A new 2 tile is
added to the board on each move. You win if you can create a 2048 tile.
You lose if the board fills up the tiles before then.''')
   input('Press Enter to begin...')

   gameBoard = getNewBoard()

   while True:  # Main game loop.
       drawBoard(gameBoard)
       print('Score:', getScore(gameBoard))
       playerMove = askForPlayerMove()
       gameBoard = makeMove(gameBoard, playerMove)
       addTwoToBoard(gameBoard)

       if isFull(gameBoard):
           drawBoard(gameBoard)
           print('Game Over - Thanks for playing!')
           sys.exit()


def getNewBoard():
   """Returns a new data structure that represents a board.

   It's a dictionary with keys of (x, y) tuples and values of the tile
   at that space. The tile is either a power-of-two integer or BLANK.
   The coordinates are laid out as:
      X0 1 2 3
     Y+-+-+-+-+
     0| | | | |
      +-+-+-+-+
     1| | | | |
      +-+-+-+-+
     2| | | | |
      +-+-+-+-+
     3| | | | |
      +-+-+-+-+"""

   newBoard = {}  # Contains the board data structure to be returned.
   # Loop over every possible space and set all the tiles to blank:
   for x in range(4):
       for y in range(4):
           newBoard[(x, y)] = BLANK

   # Pick two random spaces for the two starting 2's:
   startingTwosPlaced = 0  # The number of starting spaces picked.
   while startingTwosPlaced < 2:  # Repeat for duplicate spaces.
       randomSpace = (random.randint(0, 3), random.randint(0, 3))
       # Make sure the randomly selected space isn't already taken:
       if newBoard[randomSpace] == BLANK:
           newBoard[randomSpace] = 2
           startingTwosPlaced = startingTwosPlaced + 1

   return newBoard


def drawBoard(board):
   """Draws the board data structure on the screen."""

   # Go through each possible space left to right, top to bottom, and
   # create a list of what each space's label should be.
   labels = []  # A list of strings for the number/blank for that tile.
   for y in range(4):
       for x in range(4):
           tile = board[(x, y)]  # Get the tile at this space.
           # Make sure the label is 5 spaces long:
           labelForThisTile = str(tile).center(5)
           labels.append(labelForThisTile)

   # The {} are replaced with the label for that tile:
   print("""
+-----+-----+-----+-----+
|     |     |     |     |
|{}|{}|{}|{}|
|     |     |     |     |
+-----+-----+-----+-----+
|     |     |     |     |
|{}|{}|{}|{}|
|     |     |     |     |
+-----+-----+-----+-----+
|     |     |     |     |
|{}|{}|{}|{}|
|     |     |     |     |
+-----+-----+-----+-----+
|     |     |     |     |
|{}|{}|{}|{}|
|     |     |     |     |
+-----+-----+-----+-----+
""".format(*labels))


def getScore(board):
    """Returns the sum of all the tiles on the board data structure."""
    score = 0
    # Loop over every space and add the tile to the score:
    for x in range(4):
        for y in range(4):
            # Only add non-blank tiles to the score:
            if board[(x, y)] != BLANK:
                score = score + board[(x, y)]
    return score


def combineTilesInColumn(column):
    """The column is a list of four tile. Index 0 is the "bottom" of
    the column, and tiles are pulled "down" and combine if they are the
    same. For example, combineTilesInColumn([2, BLANK, 2, BLANK])
    returns [4, BLANK, BLANK, BLANK]."""

    # Copy only the numbers (not blanks) from column to combinedTiles
    combinedTiles = []  # A list of the non-blank tiles in column.
    for i in range(4):
        if column[i] != BLANK:
            combinedTiles.append(column[i])

    # Keep adding blanks until there are 4 tiles:
    while len(combinedTiles) < 4:
        combinedTiles.append(BLANK)

    # Combine numbers if the one "above" it is the same, and double it.
    for i in range(3):  # Skip index 3: it's the topmost space.
        if combinedTiles[i] == combinedTiles[i + 1]:
            combinedTiles[i] *= 2  # Double the number in the tile.
            # Move the tiles above it down one space:
            for aboveIndex in range(i + 1, 3):
                combinedTiles[aboveIndex] = combinedTiles[aboveIndex + 1]
            combinedTiles[3] = BLANK  # Topmost space is always BLANK.
    return combinedTiles


def makeMove(board, move):
    """Carries out the move on the board.

    The move argument is either 'W', 'A', 'S', or 'D' and the function
    returns the resulting board data structure."""

    # The board is split up into four columns, which are different
    # depending on the direction of the move:
    if move == 'W':
        allColumnsSpaces = [[(0, 0), (0, 1), (0, 2), (0, 3)],
                            [(1, 0), (1, 1), (1, 2), (1, 3)],
                            [(2, 0), (2, 1), (2, 2), (2, 3)],
                            [(3, 0), (3, 1), (3, 2), (3, 3)]]
    elif move == 'A':
        allColumnsSpaces = [[(0, 0), (1, 0), (2, 0), (3, 0)],
                            [(0, 1), (1, 1), (2, 1), (3, 1)],
                            [(0, 2), (1, 2), (2, 2), (3, 2)],
                            [(0, 3), (1, 3), (2, 3), (3, 3)]]
    elif move == 'S':
        allColumnsSpaces = [[(0, 3), (0, 2), (0, 1), (0, 0)],
                            [(1, 3), (1, 2), (1, 1), (1, 0)],
                            [(2, 3), (2, 2), (2, 1), (2, 0)],
                            [(3, 3), (3, 2), (3, 1), (3, 0)]]
    elif move == 'D':
        allColumnsSpaces = [[(3, 0), (2, 0), (1, 0), (0, 0)],
                            [(3, 1), (2, 1), (1, 1), (0, 1)],
                            [(3, 2), (2, 2), (1, 2), (0, 2)],
                            [(3, 3), (2, 3), (1, 3), (0, 3)]]

    # The board data structure after making the move:
    boardAfterMove = {}
    for columnSpaces in allColumnsSpaces:  # Loop over all 4 columns.
        # Get the tiles of this column (The first tile is the "bottom"
        # of the column):
        firstTileSpace = columnSpaces[0]
        secondTileSpace = columnSpaces[1]
        thirdTileSpace = columnSpaces[2]
        fourthTileSpace = columnSpaces[3]

        firstTile = board[firstTileSpace]
        secondTile = board[secondTileSpace]
        thirdTile = board[thirdTileSpace]
        fourthTile = board[fourthTileSpace]

        # Form the column and combine the tiles in it:
        column = [firstTile, secondTile, thirdTile, fourthTile]
        combinedTilesColumn = combineTilesInColumn(column)

        # Set up the new board data structure with the combined tiles:
        boardAfterMove[firstTileSpace] = combinedTilesColumn[0]
        boardAfterMove[secondTileSpace] = combinedTilesColumn[1]
        boardAfterMove[thirdTileSpace] = combinedTilesColumn[2]
        boardAfterMove[fourthTileSpace] = combinedTilesColumn[3]

    return boardAfterMove


def askForPlayerMove():
    """Asks the player for the direction of their next move (or quit).

    Ensures they enter a valid move: either 'W', 'A', 'S' or 'D'."""
    print('Enter move: (WASD or Q to quit)')
    while True:  # Keep looping until they enter a valid move.
        move = input('> ').upper()
        if move == 'Q':
            # End the program:
            print('Thanks for playing!')
            sys.exit()

        # Either return the valid move, or loop back and ask again:
        if move in ('W', 'A', 'S', 'D'):
            return move
        else:
            print('Enter one of "W", "A", "S", "D", or "Q".')


def addTwoToBoard(board):
    """Adds a new 2 tile randomly to the board."""
    while True:
        randomSpace = (random.randint(0, 3), random.randint(0, 3))
        if board[randomSpace] == BLANK:
            board[randomSpace] = 2
            return  # Return after finding one non-blank tile.


def isFull(board):
    """Returns True if the board data structure has no blanks."""
    # Loop over every space on the board:
    for x in range(4):
        for y in range(4):
            # If a space is blank, return False:
            if board[(x, y)] == BLANK:
                return False
    return True  # No space is blank, so return True.


# 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. 如果把 118 行的return score改成return 9999会怎么样?
  2. 如果把 229 行的board[randomSpace] = 2改成board[randomSpace] = 256会怎么样?

八十、维吉尼亚密码

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

被误认为是 19 世纪密码学家布莱斯·德·维吉尼亚(其他人早些时候独立发明了它)的维吉尼亚密码在数百年内都不可能被破解。它本质上是凯撒密码,除了它使用了多部分密钥。所谓的维吉尼亚密钥就是一个单词,甚至是一串随机的字母。每个字母代表一个数字,该数字代表消息中的字母移动: A代表消息中的字母移动 0,B代表 1,C代表 2,依此类推。

例如,如果一个维吉尼亚密钥是单词CAT,则C代表移位 2,A代表 0,T代表 19。消息的第一个字母移动 2,第二个字母移动 0,第三个字母移动 19。对于第四个字母,我们重复 2 的密钥。

这种多重凯撒密钥的使用赋予了维吉尼亚密码的力量。可能的组合数太大,无法暴力破解。同时,维吉尼亚密码不存在可以破解简单替换密码的频率分析弱点。几个世纪以来,维吉尼亚密码代表了密码学的最高水平。

你会注意到维吉尼亚和凯撒密码程序的代码之间有许多相似之处。更多关于维吉尼亚密码的信息可以在en.wikipedia.org/wiki/Vigen%C3%A8re_cipher找到。如果你想了解更多关于密码和密码破解的知识,你可以阅读我的书《Python 密码破解指南》(NoStarch 出版社,2018)。

运行示例

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

Vigenère Cipher, by Al Sweigart email@protected
The Vigenère cipher is a polyalphabetic substitution cipher that was
powerful enough to remain unbroken for centuries.
Do you want to (e)ncrypt or (d)ecrypt?
> e
Please specify the key to use.
It can be a word or any combination of letters:
> PIZZA
Enter the message to encrypt.
> Meet me by the rose bushes tonight.
Encrypted message:
Bmds mt jx sht znre qcrgeh bnmivps.
Full encrypted text copied to clipboard.

工作原理

因为加密和解密过程非常相似,translateMessage()函数处理这两个过程。encryptMessage()decryptMessage()函数仅仅是translateMessage()包装函数。换句话说,它们是调整参数的函数,将这些参数转发给另一个函数,然后返回该函数的返回值。这个程序使用这些包装函数,这样它们可以以类似于项目 66“简单替换密码”中的encryptMessage()decryptMessage()的方式被调用您可以将这些项目作为模块导入到其他程序中,以利用它们的加密代码,而不必将代码直接复制并粘贴到您的新程序中。

"""Vigenère Cipher, by Al Sweigart email@protected
The Vigenère cipher is a polyalphabetic substitution cipher that was
powerful enough to remain unbroken for centuries.
More info at: https://en.wikipedia.org/wiki/Vigen%C3%A8re_cipher
This code is available at https://nostarch.com/big-book-small-python-programming
Tags: short, cryptography, math"""

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

# Every possible symbol that can be encrypted/decrypted:
LETTERS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'


def main():
   print('''Vigenère Cipher, by Al Sweigart email@protected
The Viegenère cipher is a polyalphabetic substitution cipher that was
powerful enough to remain unbroken for centuries.''')

   # 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'
           break
       elif response.startswith('d'):
           myMode = 'decrypt'
           break
       print('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.')
       print('It can be a word or any combination of letters:')
       response = input('> ').upper()
       if response.isalpha():
           myKey = response
           break

   # 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)

   print('%sed message:' % (myMode.title()))
   print(translated)

   try:
       pyperclip.copy(translated)
       print('Full %sed text copied to clipboard.' % (myMode))
   except:
       pass  # Do nothing if pyperclip wasn't installed.


def 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 = []  # Stores the encrypted/decrypted message string.

   keyIndex = 0
   key = key.upper()

   for symbol in message:  # Loop through each character in message.
       num = LETTERS.find(symbol.upper())
       if num != -1:  # -1 means symbol.upper() was not in LETTERS.
           if mode == 'encrypt':
               # Add if encrypting:
               num += LETTERS.find(key[keyIndex])
           elif mode == 'decrypt':
               # Subtract if decrypting:
               num -= LETTERS.find(key[keyIndex])

           num %= len(LETTERS)  # Handle the potential wrap-around.

           # Add the encrypted/decrypted symbol to translated.
           if symbol.isupper():
               translated.append(LETTERS[num])
           elif symbol.islower():
               translated.append(LETTERS[num].lower())

           keyIndex += 1  # Move to the next letter in the key.
           if keyIndex == len(key):
                keyIndex = 0
        else:
            # Just add the symbol without encrypting/decrypting:
            translated.append(symbol)

    return ''.join(translated)


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

探索程序

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

  1. 用密钥'A'加密会怎么样?
  2. 删除或注释掉第 40 行的myKey = response会导致什么错误?

八十一、水桶谜题

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

在这个纸牌益智游戏中,您必须使用三个水桶(三升、五升和八升的水桶)在其中一个水桶中收集正好四升水。桶只能被清空、完全装满或倒入另一个桶中。例如,你可以装满一个 5 升的桶,然后把里面的东西倒入 3 升的桶,这样你就有了一个满满的 3 升桶,5 升桶里有 2 升水。

经过一些努力,你应该能解决这个难题。但是你能想出如何用最少的步数解决它吗?

运行示例

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

Water Bucket Puzzle, by Al Sweigart email@protected

Try to get 4L of water into one of these
buckets:

8|      |
7|      |
6|      |
5|      |  5|      |
4|      |  4|      |
3|      |  3|      |  3|      |
2|      |  2|      |  2|      |
1|      |  1|      |  1|      |
 +------+   +------+   +------+
    8L         5L         3L

You can:
  (F)ill the bucket
  (E)mpty the bucket
  (P)our one bucket into another
  (Q)uit
> f
Select a bucket 8, 5, 3, or QUIT:
> 5

Try to get 4L of water into one of these
buckets:

8|      |
7|      |
6|      |
5|      |  5|WWWWWW|
4|      |  4|WWWWWW|
3|      |  3|WWWWWW|  3|      |
2|      |  2|WWWWWW|  2|      |
1|      |  1|WWWWWW|  1|      |
 +------+   +------+   +------+
    8L         5L         3L
`--snip--`

工作原理

waterInBucket变量存储了一个代表水桶状态的字典。这个字典的关键字是字符串'8''5''3'(代表水桶),它们的值是整数(代表水桶中的水的公升数)。

第 48 到 59 行使用这个字典在屏幕上呈现水桶和水。waterDisplay列表包含'WWWWWW'(代表水)或' '(代表空气),并被传递给format()字符串方法。waterDisplay列表中的前八串填充八升桶,接下来的五串填充五升桶,最后的三串填充三升桶。

"""Water Bucket Puzzle, by Al Sweigart email@protected
A water pouring puzzle.
More info: https://en.wikipedia.org/wiki/Water_pouring_puzzle
This code is available at https://nostarch.com/big-book-small-python-programming
Tags: large, game, math, puzzle"""

import sys


print('Water Bucket Puzzle, by Al Sweigart email@protected')

GOAL = 4  # The exact amount of water to have in a bucket to win.
steps = 0  # Keep track of how many steps the player made to solve this.

# The amount of water in each bucket:
waterInBucket = {'8': 0, '5': 0, '3': 0}

while True:  # Main game loop.
   # Display the current state of the buckets:
   print()
   print('Try to get ' + str(GOAL) + 'L of water into one of these')
   print('buckets:')

   waterDisplay = []  # Contains strings for water or empty space.

   # Get the strings for the 8L bucket:
   for i in range(1, 9):
       if waterInBucket['8'] < i:
           waterDisplay.append('      ')  # Add empty space.
       else:
           waterDisplay.append('WWWWWW')  # Add water.

   # Get the strings for the 5L bucket:
   for i in range(1, 6):
       if waterInBucket['5'] < i:
           waterDisplay.append('      ')  # Add empty space.
       else:
           waterDisplay.append('WWWWWW')  # Add water.

   # Get the strings for the 3L bucket:
   for i in range(1, 4):
       if waterInBucket['3'] < i:
           waterDisplay.append('      ')  # Add empty space.
       else:
           waterDisplay.append('WWWWWW')  # Add water.

   # Display the buckets with the amount of water in each one:
   print('''
8|{7}|
7|{6}|
6|{5}|
5|{4}|  5|{12}|
4|{3}|  4|{11}|
3|{2}|  3|{10}|  3|{15}|
2|{1}|  2|{9}|  2|{14}|
1|{0}|  1|{8}|  1|{13}|
+------+   +------+   +------+
   8L         5L         3L
'''.format(*waterDisplay))

   # Check if any of the buckets has the goal amount of water:
   for waterAmount in waterInBucket.values():
       if waterAmount == GOAL:
           print('Good job! You solved it in', steps, 'steps!')
           sys.exit()

   # Let the player select an action to do with a bucket:
   print('You can:')
   print('  (F)ill the bucket')
   print('  (E)mpty the bucket')
   print('  (P)our one bucket into another')
   print('  (Q)uit')

   while True:  # Keep asking until the player enters a valid action.
       move = input('> ').upper()
       if move == 'QUIT' or move == 'Q':
           print('Thanks for playing!')
           sys.exit()

       if move in ('F', 'E', 'P'):
           break  # Player has selected a valid action.
       print('Enter F, E, P, or Q')

   # Let the player select a bucket:
   while True:  # Keep asking until valid bucket entered.
       print('Select a bucket 8, 5, 3, or QUIT:')
       srcBucket = input('> ').upper()

       if srcBucket == 'QUIT':
           print('Thanks for playing!')
           sys.exit()

       if srcBucket in ('8', '5', '3'):
           break  # Player has selected a valid bucket.

   # Carry out the selected action:
   if move == 'F':
       # Set the amount of water to the max size.
       srcBucketSize = int(srcBucket)
        waterInBucket[srcBucket] = srcBucketSize
        steps += 1

    elif move == 'E':
        waterInBucket[srcBucket] = 0  # Set water amount to nothing.
        steps += 1

    elif move == 'P':
        # Let the player select a bucket to pour into:
        while True:  # Keep asking until valid bucket entered.
            print('Select a bucket to pour into: 8, 5, or 3')
            dstBucket = input('> ').upper()
            if dstBucket in ('8', '5', '3'):
                break  # Player has selected a valid bucket.

        # Figure out the amount to pour:
        dstBucketSize = int(dstBucket)
        emptySpaceInDstBucket = dstBucketSize - waterInBucket[dstBucket]
        waterInSrcBucket = waterInBucket[srcBucket]
        amountToPour = min(emptySpaceInDstBucket, waterInSrcBucket)

        # Pour out water from this bucket:
        waterInBucket[srcBucket] -= amountToPour

        # Put the poured out water into the other bucket:
        waterInBucket[dstBucket] += amountToPour
        steps += 1

    elif move == 'C':
        pass  # If the player selected Cancel, do nothing. 

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

  • 通过使游戏可配置来增加多样性,这样你可以为三个桶指定任何大小,为目标数量指定任何数量。
  • 添加“提示”,检查每个水桶中的水量,并提供下一步要采取的措施。如果程序不知道下一步该做什么,它可以简单地显示“我不知道你下一步该做什么。也许重新开始?”

探索程序

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

  1. 如果把 104 行的waterInBucket[srcBucket] = 0改成waterInBucket[srcBucket] = 1会怎么样?
  2. 如果把第 16 行的{'8': 0, '5': 0, '3': 0}改成{'8': 0, '5': 4, '3': 0}会怎么样?
  3. 如果把第 16 行的{'8': 0, '5': 0, '3': 0}改成{'8': 9, '5': 0, '3': 0}会怎么样?

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

AI 时代,提示词便是生产力

作者&#xff1a;明明如月学长&#xff0c; CSDN 博客专家&#xff0c;蚂蚁集团高级 Java 工程师&#xff0c;《性能优化方法论》作者、《解锁大厂思维&#xff1a;剖析《阿里巴巴Java开发手册》》、《再学经典&#xff1a;《EffectiveJava》独家解析》专栏作者。 热门文章推荐…

瑞芯微RK3568核心板强在何处?

RK3568核心板产品简介 RK3568核心板是武汉万象奥科基于瑞芯微Rockchip的RK3568设计的一款高性能核心板。该处理器集成了最新的高性能CPU、GPU&#xff0c;并拥有丰富的接口&#xff0c;非常适用于工业自动化控制、人机界面、中小型医疗分析器、电力等多种行业应用。 HD-RK3568-…

项目8:用户注册和登录的前后端联调

项目8&#xff1a;用户注册和登录的前后端联调 1.前端项目使用 2.前端项目注册模块 3.后端完成项目注册 4.前端项目登录模块 5.后端完成项目登录 6.用户认证&#xff08;校验用户是否登录&#xff09; 项目8&#xff1a;用户注册和登录的前后端联调 1.前端项目使用 直接…

【iOS】iOS语音通话回音消除(AEC)技术实现

一、前言 在语音通话、互动直播、语音转文字类应用或者游戏中&#xff0c;需要采集用户的麦克风音频数据&#xff0c;然后将音频数据发送给其它终端或者语音识别服务。如果直接使用采集的麦克风数据&#xff0c;就会存在回音问题。所谓回音就是在语音通话过程中&#xff0c;如…

九龙证券|这一刻,资本市场进入全新时代!

2023年4月10日&#xff0c;第一批10家主板注册制企业上市鸣锣敲钟&#xff0c;奏响了触及本钱商场灵魂深处革新的序曲。 动能切换中的我国对于高效资源配置的渴望&#xff0c;与革新进行时的本钱商场对于全面注册制的探究&#xff0c;一起凝集成一股连绵有力之暖流&#xff0c;…

2023年最强手机远程控制横测:ToDesk、向日葵、Airdroid三款APP免Root版本

前言 随着远程办公和远程协作的日益普及&#xff0c;跨设备、系统互通的远程控制软件已经成为职场人士不可或缺的工具之一。在国内&#xff0c;向日葵和ToDesk是最著名的远程控制软件&#xff1b;而在国外&#xff0c;则有微软远程桌面、AirDroid、TeamViewer、AnyDesk、Parse…

【华为机试真题详解JAVA实现】—Sudoku

目录 一、题目描述 二、解题代码 一、题目描述 问题描述:数独(Sudoku)是一款大众喜爱的数字逻辑游戏。玩家需要根据9X9盘面上的已知数字,推算出所有剩余空格的数字,并且满足每一行、每一列、每一个3X3粗线宫内的数字均含1-9,并且不重复。 例如: 输入 输出

Faster-RCNN代码解读2:快速上手使用

Faster-RCNN代码解读2&#xff1a;快速上手使用 前言 ​ 因为最近打算尝试一下Faster-RCNN的复现&#xff0c;不要多想&#xff0c;我还没有厉害到可以一个人复现所有代码。所以&#xff0c;是参考别人的代码&#xff0c;进行自己的解读。 ​ 代码来自于B站的UP主&#xff08;…

汽车电子相关术语介绍

一、相关术语介绍 1、汽车OTA 全称“Over-The-Air technology ”&#xff0c;即空中下载技术&#xff0c;通过移动通信的接口实现对软件进行远程管理&#xff0c;传统的做法到4S店通过整车OBD对相应的ECU进行软件升级。OTA技术最早2000年出现在日本&#xff0c;目前通过OTA方式…

FusionCharts Suite XT v3.20.0 Crack

FusionCharts Suite XT v3.20.0 改进了仪表的径向条形图和调整大小功能。2023 年 4 月 11 日 - 9:37新版本特征 添加了一个新方法“_changeXAxisCoordinates”&#xff0c;它允许用户将 x 轴更改为在图例或数据交互时自动居中对齐。更新了 Angular 集成以支持 Angular 版本 14 …

【微信小程序-原生开发】添加自定义图标(以使用阿里图标库为例)

方式一 &#xff1a; 下载svg导入 优点&#xff1a;操作方便&#xff0c;支持多彩图标缺点&#xff1a;会增加源代码大小 下载 svg 格式的图标图片&#xff0c;放入源码中使用 小程序项目中的路径为 assets\icon\美食.svg 使用时-代码范例 <image class"imgIcon"…

前端开发工具-Visual Studio Code-插件下载-迁移到新电脑

背景 前端使用的开发工具一般是Visual Studio Code&#xff0c;很多辅助功能&#xff0c;比如字体高亮、单词拼写检查、预览图片等需要安装插件。但是插件在原来的电脑&#xff0c;不想下载或者自己是新人&#xff0c;想迁移同事的插件&#xff0c;或者新电脑没有外网。 以下…

图解HTTP阅读笔记:第4章 返回结果的HTTP状态码

《图解HTTP》第四章读书笔记 图解HTTP第4章&#xff1a;返回结果的HTTP状态码4.1 状态码告知从服务器端返回的请求结果4.2 2XX成功4.2.1 200 OK4.2.2 204 No Content4.2.3 206 Parital Content4.3 3XX重定向4.3.1 301 Moved Permanently4.3.2 302 Found4.3.3 303 See Other4.3.…

OK-3399-C ADB烧录

ADB烧写 一、OK3399用户资料工具目录附带了ADB工具的资料包路径&#xff1a; 二、将其解压在C:\User目录 三、将设备通过type-c线download口与电脑相连接&#xff0c;打开命令行&#xff0c;进入解压的目录&#xff0c;查看adb是否安装成功&#xff1a; 四、安装成功后&#x…

spring-boot怎么扫描不在启动类所在包路径下的bean

前言&#xff1a; 项目中有多个模块&#xff0c;其中有些模块的包路径不在启动类的子路径下&#xff0c;此时我们怎么处理才能加载到这些类&#xff1b; 1 使用SpringBootApplication 中的scanBasePackages 属性; SpringBootApplication(scanBasePackages {"com.xxx.xx…

在proteus中仿真arduino实现矩阵键盘程序

矩阵键盘是可以解决我们端口缺乏的问题&#xff0c;当然&#xff0c;如果我们使用芯片来实现矩阵键盘的输入端口缺乏的问题将更加划算了&#xff0c;本文暂时不使用芯片来解决问题&#xff0c;而使用纯朴的8根线来实现矩阵键盘&#xff0c;目的是使初学者掌握原理。想了解使用芯…

# 切削加工形貌的相关论文阅读【1】-球头铣刀铣削球面的表面形貌建模与仿真研究

切削加工形貌论文【1】-球头铣刀铣削球面的表面形貌建模与仿真研究1. 论文【2】-球头铣刀加工表面形貌建模与仿真1.1 切削加工形貌仿真-考虑的切削参数1.2 其他试验条件1.3 主要研究目的1.4 试验与分析结果1.5 面粗糙度的评价指标2. 论文【1】-球头铣刀加工球面&#xff08;曲面…

Vue3.0中的响应式原理

回顾Vue2的响应式原理 实现原理&#xff1a; - 对象类型&#xff1a;通过 Object.defineProperty()对属性的读取、修改进行拦截&#xff08;数据劫持&#xff09;。 - 数组类型&#xff1a;通过重写更新数组的一系列方法来实现拦截。&#xff08;对数组的变更方法进行了包裹&…

nacos源码服务注册

nacos服务注册序言1.源码环境搭建1.1idea运行源码1.2 登录nacos2.服务注册分析2.1 客户端2.1.1容器启动监听2.1.2注册前初始化2.1.3注册服务2.2 服务端2.2.1注册2.2.2重试机制3.注意事项序言 本文章是分析的是nacos版本2.2 这次版本是一次重大升级优化&#xff0c;由原来&#…

浅析DNS Rebinding

0x01 攻击简介 DNS Rebinding也叫做DNS重绑定攻击或者DNS重定向攻击。在这种攻击中&#xff0c;恶意网页会导致访问者运行客户端脚本&#xff0c;攻击网络上其他地方的计算机。 在介绍DNS Rebinding攻击机制之前我们先了解一下Web同源策略&#xff0c; Web同源策略 同源策略…