【Dison夏令营 Day 07】用 Python 和 Rich 制作 Wordle克隆(下篇)

在大流行期间,Wordle 在 Twitter 上还算比较流行的一款基于网络的益智游戏,要求玩家每天在六次或更短时间内猜出一个新的五个字母的单词,每个人得到的单词都是一样的。

在本教程中,你将在终端上创建自己的 Wordle 克隆。自 2021 年 10 月 Josh Wardle 推出 Wordle 以来,已有数百万人玩过这款游戏。虽然您可以在网络上玩原版游戏,但您将以命令行应用程序的形式创建自己的版本,然后使用 Rich 库使其看起来更漂亮。

在这里插入图片描述
书接上回

第 5 步:添加验证和用户反馈

在上一步中,您添加了 Rich 并重写了您的游戏,使用颜色来更好地展示游戏。接下来,您将在此基础上,在用户做错事情时显示一些警告:

在这里插入图片描述
请注意,如果您的猜测不是五个字母,或者您重复了之前的猜测,就会收到警告。

在这一步中,您将添加一些功能,以便在用户做出意外举动时为他们提供指导,从而使您的游戏更加人性化。
确保单词表不是空的

理论上,您可以使用任何文本文件作为单词表。如果单词表不包含任何五个字母的单词,那么 get_random_word() 将会失败。但您的用户会看到哪条消息呢?

打开您的 REPL,尝试从一个空单词表中获取一个随机单词:

>>> import wyrdl
>>> wyrdl.get_random_word([])
Traceback (most recent call last):
  ...
IndexError: Cannot choose from an empty sequence

您看到的是回溯和 IndexError。如果没有其他上下文,用户可能不会意识到问题出在单词表上。

单词列表中没有任何有效单词是很难恢复的,但你至少可以提供一个更明确和可操作的错误信息。更新 get_random_word(),检查有效单词列表是否为空:

# wyrdl.py

# ...

def get_random_word(word_list):
    if words := [
        word.upper()
        for word in word_list
        if len(word) == 5 and all(letter in ascii_letters for letter in word)
    ]:
        return random.choice(words)
    else:
        console.print("No words of length 5 in the word list", style="warning")
        raise SystemExit()

# ...

您可以使用 walrus 运算符 (:=) 创建有效单词列表,并检查其中是否至少包含一个单词。使用 walrus 运算符时,您要编写一个赋值表达式,作为表达式的一部分进行赋值。

在这种情况下,您会像以前一样将单词列表赋值给单词。但是,现在您会立即在 if 测试中使用该列表来检查它是否为空。如果列表为空,则在 else 子句中打印警告,明确说明问题所在:

>>> import wyrdl
>>> wyrdl.get_random_word(["one", "four", "eleven"])
No words of length 5 in the word list

这样,用户就不会看到回溯。取而代之的是提供可操作的反馈,用户可以利用这些反馈来解决问题。

注意,你在调用 console.print() 时添加了 style=“warning”。这使用的是您之前在自定义主题中初始化控制台时定义的警告样式。

由于你的游戏需要一个密语,你将通过引发 SystemExit 来结束程序。接下来,您将考虑可以恢复的问题。例如,用户猜到的单词不是五个字母。不过首先要考虑哪些单词可以作为有效猜测。

考虑接受哪些词语

原始 Wordle 游戏的挑战之一是,您的猜测必须是字典中的实际单词。目前,您还没有在您的 Wordle 克隆中实施同样的限制。任何字母组合都是有效的猜测。

您可以要求猜测的单词也在您现有的单词列表中。但是,如果你使用的单词列表有限,这可能会让用户感到沮丧,因为他们最终需要先弄清楚单词列表中到底有哪些单词。

更好的办法可能是在检查猜测是否有效时使用第二个全面的单词表。重要的是,任何合理的单词都应被视为有效。在没有广泛字典的情况下,允许五个字母的任意组合可能是更好的用户体验。

在本教程中,您将不会处理为验证猜测而添加第二个单词表的问题。不过,你可以尝试一下。这是一个很好的尝试练习!

验证用户猜测的单词

虽然您不会根据单词表检查用户的猜测,但您应该进行一些验证,并在用户做错事情时提醒他们。在本节中,您将改进在用户猜词时提供的用户反馈。

目前,您在以下代码行中处理用户输入:

guesses[idx] = input("\nGuess word: ").upper()

要改进对猜测的处理,首先要将其重构为一个单独的函数。首先,在文件中添加 guess_word():

# wyrdl.py

# ...

def guess_word(previous_guesses):
    guess = console.input("\nGuess word: ").upper()
    return guess

# ...

Rich Console 包含一个 .input() 方法,该方法与输入()函数类似,但允许您为输入提示添加丰富的格式。虽然我们没有利用这一功能,但为了保持一致性,在这里使用 console 也是不错的。

您还将 previous_guesses 作为一个参数,因为您很快就会用它来检查用户是否重复猜测。不过在执行任何检查之前,请更新 main() 以调用新函数:

# wyrdl.py

# ...

def main():
    # Pre-process
    words_path = pathlib.Path(__file__).parent / "wordlist.txt"
    word = get_random_word(words_path.read_text(encoding="utf-8").split("\n"))
    guesses = ["_" * 5] * 6

    # Process (main loop)
    for idx in range(6):
        refresh_page(headline=f"Guess {idx + 1}")
        show_guesses(guesses, word)

        guesses[idx] = guess_word(previous_guesses=guesses[:idx])
        if guesses[idx] == word:
            break

    # Post-process
    game_over(guesses, word, guessed_correctly=guesses[idx] == word)

# ...

您可以创建一个先前猜测的列表,只包含猜测中已经填入的元素。然后将此列表传递给 guess_word()。

现在,使用 previous_guesses 检查用户是否两次做出相同的猜测。如果出现这种情况,就会向用户发出警告,并让他们再次猜测。您可以通过下面的 if 测试来实现:

# wyrdl.py

# ...

def guess_word(previous_guesses):
    guess = console.input("\nGuess word: ").upper()

    if guess in previous_guesses:
        console.print(f"You've already guessed {guess}.", style="warning")
        return guess_word(previous_guesses)

    return guess

# ...

使用之前定义的警告样式,您将向用户打印一条信息,告知他们已经猜出了单词。为了让用户进行新的猜测,您将再次调用 guess_word(),并返回该猜测。

注意:正如您在本教程前面学到的,递归调用通常不是在 Python 中创建循环的最佳方式。然而,在本例中,它却非常优雅。典型的缺点并不重要。例如,与用户输入猜测的时间相比,调用函数所花费的时间可以忽略不计。

既然所有的单词都是五个字母,那么您也应该检查所有的猜测是否都是五个字母。为此,您可以添加第二个条件:

# wyrdl.py

# ...

def guess_word(previous_guesses):
    guess = console.input("\nGuess word: ").upper()

    if guess in previous_guesses:
        console.print(f"You've already guessed {guess}.", style="warning")
        return guess_word(previous_guesses)

    if len(guess) != 5:
        console.print("Your guess must be 5 letters.", style="warning")
        return guess_word(previous_guesses)

    return guess

# ...

本测试的结构与上一测试相同。您要检查猜测中是否有五个字母。如果没有,则打印警告并让用户进行第二次猜测。

最后,您可以引导用户只使用英文字母。在这种情况下,if 测试要复杂一些,因为您需要检查用户猜测中的每个字母:

# wyrdl.py

# ...

def guess_word(previous_guesses):
    guess = console.input("\nGuess word: ").upper()

    if guess in previous_guesses:
        console.print(f"You've already guessed {guess}.", style="warning")
        return guess_word(previous_guesses)

    if len(guess) != 5:
        console.print("Your guess must be 5 letters.", style="warning")
        return guess_word(previous_guesses)

    if any((invalid := letter) not in ascii_letters for letter in guess):
        console.print(
            f"Invalid letter: '{invalid}'. Please use English letters.",
            style="warning",
        )
        return guess_word(previous_guesses)

    return guess

# ...

any()表达式检查猜测中是否有字母不在 ascii_letters 中,ascii_letters 是一个内置的小写和大写字母列表,从 A 到 Z。

注意:如果您添加了自己的单词列表,其中包含使用不同字母的单词,则需要更新此检查以允许用户使用所有字母。

您可以在 any() 中使用 walrus 运算符来收集无效字符的示例。如果用户的猜测中出现了无效字母,那么就像往常一样用 console.print() 报告,并给用户一次新的尝试。

注意:在 any() 中使用 := 功能强大,但其作用可能并不明显。您可以关于此结构的内容,了解详情。

运行您的游戏,并尝试通过不同类型的用户错误来刺激您的代码。当您猜测四个字母的单词或在猜测中包含数字时,您会得到有用的反馈吗?

虽然游戏的核心内容和以前一样,但您的程序现在更加稳固,并会在用户出错时为他们提供指导。如前所述,您可以通过扩展以下部分查看完整的源代码:

# wyrdl.py

import pathlib
import random
from string import ascii_letters

from rich.console import Console
from rich.theme import Theme

console = Console(width=40, theme=Theme({"warning": "red on yellow"}))

def main():
    # Pre-process
    words_path = pathlib.Path(__file__).parent / "wordlist.txt"
    word = get_random_word(words_path.read_text(encoding="utf-8").split("\n"))
    guesses = ["_" * 5] * 6

    # Process (main loop)
    for idx in range(6):
        refresh_page(headline=f"Guess {idx + 1}")
        show_guesses(guesses, word)

        guesses[idx] = guess_word(previous_guesses=guesses[:idx])
        if guesses[idx] == word:
            break

    # Post-process
    game_over(guesses, word, guessed_correctly=guesses[idx] == word)

def refresh_page(headline):
    console.clear()
    console.rule(f"[bold blue]:leafy_green: {headline} :leafy_green:[/]\n")

def get_random_word(word_list):
    if words := [
        word.upper()
        for word in word_list
        if len(word) == 5 and all(letter in ascii_letters for letter in word)
    ]:
        return random.choice(words)
    else:
        console.print("No words of length 5 in the word list", style="warning")
        raise SystemExit()

def show_guesses(guesses, word):
    for guess in guesses:
        styled_guess = []
        for letter, correct in zip(guess, word):
            if letter == correct:
                style = "bold white on green"
            elif letter in word:
                style = "bold white on yellow"
            elif letter in ascii_letters:
                style = "white on #666666"
            else:
                style = "dim"
            styled_guess.append(f"[{style}]{letter}[/]")

        console.print("".join(styled_guess), justify="center")

def guess_word(previous_guesses):
    guess = console.input("\nGuess word: ").upper()

    if guess in previous_guesses:
        console.print(f"You've already guessed {guess}.", style="warning")
        return guess_word(previous_guesses)

    if len(guess) != 5:
        console.print("Your guess must be 5 letters.", style="warning")
        return guess_word(previous_guesses)

    if any((invalid := letter) not in ascii_letters for letter in guess):
        console.print(
            f"Invalid letter: '{invalid}'. Please use English letters.",
            style="warning",
        )
        return guess_word(previous_guesses)

    return guess

def game_over(guesses, word, guessed_correctly):
    refresh_page(headline="Game Over")
    show_guesses(guesses, word)

    if guessed_correctly:
        console.print(f"\n[bold white on green]Correct, the word is {word}[/]")
    else:
        console.print(f"\n[bold white on red]Sorry, the word was {word}[/]")

if __name__ == "__main__":
    main()

您已经很好地实现了 Wordle 克隆。在结束本教程之前,您将在这里和那里调整您的代码,磨平一些尖锐的边缘。

第 6 步:清理游戏和代码

在第 5 步中,您通过添加一些信息来改善用户体验,这些信息可以在用户做错任何事情时提供帮助。在最后一步中,您将添加一个可以帮助用户的功能,即所有字母及其状态的列表:

猜测表下方的字母列表显示了每个字母的当前状态。与往常一样,绿色的字母是正确的,黄色的字母是错误的,灰色的字母是错误的。

好了,最后的调整时间到了。
使用常量为概念命名

魔法值通常会降低代码的可读性。魔力值是一个值,通常是一个数字,在程序中出现时没有任何上下文。例如,请看下面这行代码:

guesses = ["_" * 5] * 6

这里的 "5 "和 "6 "是什么意思?由于您目前正沉浸在游戏中,您可能会立即指出 5 表示单词中的字母数,而 6 指的是允许猜测的次数。不过,如果你几天不碰代码,这一点可能就不再那么明显了。

魔法值的另一个问题是难以更改。假如你想改变一下游戏规则,改猜七个字母的单词。这既麻烦又容易出错。

一个好的做法是用正确命名的常量来替换神奇值。例如,可以定义 NUM_LETTERS = 5,然后用 NUM_LETTERS 替换所有 5 的出现。

注意:Python 对常量没有任何特殊支持。从技术上讲,常量只是一个不改变其值的变量。然而,约定俗成的做法是使用大写字母来表示常量变量的名称。

在代码文件顶部添加几个描述性常量:

# wyrdl.py

import pathlib
import random
from string import ascii_letters

from rich.console import Console
from rich.theme import Theme

console = Console(width=40, theme=Theme({"warning": "red on yellow"}))

NUM_LETTERS = 5
NUM_GUESSES = 6
WORDS_PATH = pathlib.Path(__file__).parent / "wordlist.txt"

# ...

有了这些常量,你就可以开始用这些常量替换你的神奇值了。例如,你现在可以将猜测的初始化写成这样:

guesses = ["_" * NUM_LETTERS] * NUM_GUESSES

常量可以帮助您理解代码的作用。继续在代码中添加常量。您可以展开以下部分,查看您可以做出的所有更改:

# wyrdl.py

import pathlib
import random
from string import ascii_letters

from rich.console import Console
from rich.theme import Theme

console = Console(width=40, theme=Theme({"warning": "red on yellow"}))

NUM_LETTERS = 5
NUM_GUESSES = 6
WORDS_PATH = pathlib.Path(__file__).parent / "wordlist.txt"

def main():
    # Pre-process
    word = get_random_word(WORDS_PATH.read_text(encoding="utf-8").split("\n"))
    guesses = ["_" * NUM_LETTERS] * NUM_GUESSES

    # Process (main loop)
    for idx in range(NUM_GUESSES):
        refresh_page(headline=f"Guess {idx + 1}")
        show_guesses(guesses, word)

        guesses[idx] = guess_word(previous_guesses=guesses[:idx])
        if guesses[idx] == word:
            break

    # Post-process
    game_over(guesses, word, guessed_correctly=guesses[idx] == word)

def refresh_page(headline):
    console.clear()
    console.rule(f"[bold blue]:leafy_green: {headline} :leafy_green:[/]\n")

def get_random_word(word_list):
    if words := [
        word.upper()
        for word in word_list
        if len(word) == NUM_LETTERS
        and all(letter in ascii_letters for letter in word)
    ]:
        return random.choice(words)
    else:
        console.print(
            f"No words of length {NUM_LETTERS} in the word list",
            style="warning",
        )
        raise SystemExit()

def show_guesses(guesses, word):
    for guess in guesses:
        styled_guess = []
        for letter, correct in zip(guess, word):
            if letter == correct:
                style = "bold white on green"
            elif letter in word:
                style = "bold white on yellow"
            elif letter in ascii_letters:
                style = "white on #666666"
            else:
                style = "dim"
            styled_guess.append(f"[{style}]{letter}[/]")

        console.print("".join(styled_guess), justify="center")

def guess_word(previous_guesses):
    guess = console.input("\nGuess word: ").upper()

    if guess in previous_guesses:
        console.print(f"You've already guessed {guess}.", style="warning")
        return guess_word(previous_guesses)

    if len(guess) != NUM_LETTERS:
        console.print(
            f"Your guess must be {NUM_LETTERS} letters.", style="warning"
        )
        return guess_word(previous_guesses)

    if any((invalid := letter) not in ascii_letters for letter in guess):
        console.print(
            f"Invalid letter: '{invalid}'. Please use English letters.",
            style="warning",
        )
        return guess_word(previous_guesses)

    return guess

def game_over(guesses, word, guessed_correctly):
    refresh_page(headline="Game Over")
    show_guesses(guesses, word)

    if guessed_correctly:
        console.print(f"\n[bold white on green]Correct, the word is {word}[/]")
    else:
        console.print(f"\n[bold white on red]Sorry, the word was {word}[/]")

if __name__ == "__main__":
    main()

检查是否替换了所有 5 的方法之一是更改 NUM_LETTERS 的值。如果你猜了 8 次才猜出一个 6 个字母的单词,你的程序还能运行吗?如果没有,那就是漏掉了一个字母。

添加已用字母概览

Rich 提供的颜色为用户提供了很好的线索,让他们知道自己猜对了哪些字母。但是,要一眼看出用户已经猜出了哪些字母并不容易。为了帮助用户,您可以添加一行,显示字母表中每个字母的状态:

您已经在 show_guesses() 中获得了必要的信息,因此您将扩展该函数以显示单个字母的状态:

# wyrdl.py

import pathlib
import random
from string import ascii_letters, ascii_uppercase

# ...

def show_guesses(guesses, word):
    letter_status = {letter: letter for letter in ascii_uppercase}
    for guess in guesses:
        styled_guess = []
        for letter, correct in zip(guess, word):
            if letter == correct:
                style = "bold white on green"
            elif letter in word:
                style = "bold white on yellow"
            elif letter in ascii_letters:
                style = "white on #666666"
            else:
                style = "dim"
            styled_guess.append(f"[{style}]{letter}[/]")
            if letter != "_":
                letter_status[letter] = f"[{style}]{letter}[/]"

        console.print("".join(styled_guess), justify="center")
    console.print("\n" + "".join(letter_status.values()), justify="center")

# ...

您可以使用 dictionary letter_status 来跟踪每个字母的状态。首先,用所有大写字母初始化字典。然后,在处理每个猜测的每个字母时,用正确样式的字母更新 letter_status。处理完毕后,将所有字母连接起来,并以各自的样式打印出来。

将这些信息呈现在用户面前,会让游戏玩起来更轻松愉快。

干净利落地退出游戏

早些时候,您确保用户不会在单词列表为空的情况下看到难以理解的回溯。随着游戏的不断改进,用户接触到 Python 错误信息的可能性越来越小。

但仍然存在的一种可能性是,他们可以按 Ctrl+C 来提前结束游戏。您不想让他们失去退出游戏的能力。不过,在这种情况下,您可以让游戏干净利落地退出。

当用户键入 Ctrl+C 时,Python 会引发一个 KeyboardInterupt 异常。这是一个异常,您可以用 try … except 块捕获它。但在这种情况下,您不需要对异常进行任何特殊处理。因此,您可以使用 contextlib.suppress()。

通过在主循环外添加上下文管理器,可以确保 Ctrl+C 跳出主循环,运行后处理代码:

# wyrdl.py

import contextlib
import pathlib
import random
from string import ascii_letters, ascii_uppercase

# ...

def main():
    # Pre-process
    word = get_random_word(WORDS_PATH.read_text(encoding="utf-8").split("\n"))
    guesses = ["_" * NUM_LETTERS] * NUM_GUESSES

    # Process (main loop)
    with contextlib.suppress(KeyboardInterrupt):
        for idx in range(NUM_GUESSES):
            refresh_page(headline=f"Guess {idx + 1}")
            show_guesses(guesses, word)

            guesses[idx] = guess_word(previous_guesses=guesses[:idx])
            if guesses[idx] == word:
                break

    # Post-process
    game_over(guesses, word, guessed_correctly=guesses[idx] == word)

# ...

请注意,你要在 suppress() 上下文管理器内缩进整个主循环。如果在循环内发生 KeyboardInterrupt(键盘中断),控制权将立即传出循环,并调用 game_over()。

这样做的效果是,游戏将在向用户显示密语后结束。

这就是本教程的最后一项调整。如果你想查看完整的源代码,请查看下面:

# wyrdl.py

import contextlib
import pathlib
import random
from string import ascii_letters, ascii_uppercase

from rich.console import Console
from rich.theme import Theme

console = Console(width=40, theme=Theme({"warning": "red on yellow"}))

NUM_LETTERS = 5
NUM_GUESSES = 6
WORDS_PATH = pathlib.Path(__file__).parent / "wordlist.txt"

def main():
    # Pre-process
    word = get_random_word(WORDS_PATH.read_text(encoding="utf-8").split("\n"))
    guesses = ["_" * NUM_LETTERS] * NUM_GUESSES

    # Process (main loop)
    with contextlib.suppress(KeyboardInterrupt):
        for idx in range(NUM_GUESSES):
            refresh_page(headline=f"Guess {idx + 1}")
            show_guesses(guesses, word)

            guesses[idx] = guess_word(previous_guesses=guesses[:idx])
            if guesses[idx] == word:
                break

    # Post-process
    game_over(guesses, word, guessed_correctly=guesses[idx] == word)

def refresh_page(headline):
    console.clear()
    console.rule(f"[bold blue]:leafy_green: {headline} :leafy_green:[/]\n")

def get_random_word(word_list):
    if words := [
        word.upper()
        for word in word_list
        if len(word) == NUM_LETTERS
        and all(letter in ascii_letters for letter in word)
    ]:
        return random.choice(words)
    else:
        console.print(
            f"No words of length {NUM_LETTERS} in the word list",
            style="warning",
        )
        raise SystemExit()

def show_guesses(guesses, word):
    letter_status = {letter: letter for letter in ascii_uppercase}
    for guess in guesses:
        styled_guess = []
        for letter, correct in zip(guess, word):
            if letter == correct:
                style = "bold white on green"
            elif letter in word:
                style = "bold white on yellow"
            elif letter in ascii_letters:
                style = "white on #666666"
            else:
                style = "dim"
            styled_guess.append(f"[{style}]{letter}[/]")
            if letter != "_":
                letter_status[letter] = f"[{style}]{letter}[/]"

        console.print("".join(styled_guess), justify="center")
    console.print("\n" + "".join(letter_status.values()), justify="center")

def guess_word(previous_guesses):
    guess = console.input("\nGuess word: ").upper()

    if guess in previous_guesses:
        console.print(f"You've already guessed {guess}.", style="warning")
        return guess_word(previous_guesses)

    if len(guess) != NUM_LETTERS:
        console.print(
            f"Your guess must be {NUM_LETTERS} letters.", style="warning"
        )
        return guess_word(previous_guesses)

    if any((invalid := letter) not in ascii_letters for letter in guess):
        console.print(
            f"Invalid letter: '{invalid}'. Please use English letters.",
            style="warning",
        )
        return guess_word(previous_guesses)

    return guess

def game_over(guesses, word, guessed_correctly):
    refresh_page(headline="Game Over")
    show_guesses(guesses, word)

    if guessed_correctly:
        console.print(f"\n[bold white on green]Correct, the word is {word}[/]")
    else:
        console.print(f"\n[bold white on red]Sorry, the word was {word}[/]")

if __name__ == "__main__":
    main()

你已经写了不少代码。通过一步步构建 Wordle 克隆,你看到了每个部分是如何融入整体的。像这样以迭代的方式实现代码,是保持对程序所有操作的了解的好方法。

结束语

恭喜你 您已经创建了一个功能丰富的 Wordle 克隆,您可以自己玩,也可以与您所有的朋友–至少是那些知道如何在终端运行 Python 程序的朋友–分享。

一路走来,你已经熟悉了 Rich,并学会了如何使用该库为终端应用程序添加色彩和风格。

在这个循序渐进的项目中,你将学会:

  • 拥有迭代创建命令行应用程序的良好策略
  • 使用 Rich 的控制台在终端创建美观的用户界面
  • 读取并验证用户输入
  • 处理以字符串、列表和字典表示的数据
  • 处理存储在文本文件中的数据

接下来,挑战一下自己的 Wordle 克隆能力吧!您还可以寻找继续开发游戏的方法。请在下面的讨论区分享您的经验。

下一步

虽然您的 Wordle 克隆已经具备了最重要的功能,但您仍有许多方法可以更改或改进项目。您已经在教程中注意到了其中一些:

  • 只允许从有效单词列表中猜词: 这将使游戏更具挑战性,因为你不能随便把一些字母扔到一起,检查它们是否出现在密语中。要实现这一点,你需要一个全面的单词列表。

  • 创建主题 Wordle 克隆: 本教程中下载的单词表是基于教程本身的单词。根据您感兴趣的主题创建一个单词表可能会更有趣。也许你可以创建一个编程术语、人名或莎士比亚戏剧的列表。

  • 添加闪屏: 闪屏或介绍屏幕是让用户做好准备的好方法。为了让您的应用程序更容易使用,您还可以添加一些游戏内说明–例如,解释游戏的目的和不同颜色代表的含义。

尽情探索你自己的 Wordle 变体吧。另外,请记住,在创建其他命令行应用程序时,您可以使用本教程中学到的大部分原理。那么,你下一步要做什么呢?

感谢大家花时间阅读我的文章,你们的支持是我不断前进的动力。期望未来能为大家带来更多有价值的内容,请多多关注我的动态!

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

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

相关文章

分享一款Type C接口USB转2路485模块【带完整原理图】

大家好,我是『芯知识学堂』的SingleYork,今天给大家分享一款很实用的工具–基于Type C接口的USB转2路485模块。 这款模块主芯片采用南京沁恒的CH342F这款芯片,芯片特性如下: 该系列芯片有QFN24和ESSOP10 这2种封装,…

深度网络现代实践 - 深度前馈网络之结构设计篇

序言 深度网络结构设计作为人工智能领域的基石,正引领着技术创新的浪潮。通过模拟人脑神经元间的复杂连接,深度神经网络展现了卓越的特征学习与模式识别能力。随着大数据与计算能力的提升,设计高效、精准且泛化能力强的深度网络结构成为研究…

深度探索“目录名称无效“:原因、解决方案与最佳实践

目录名称无效:现象背后的秘密 在日常使用电脑或移动设备时,我们时常会遇到“目录名称无效”的错误提示,这一提示仿佛是一道无形的屏障,阻断了我们与重要数据的联系。从本质上讲,“目录名称无效”意味着系统无法识别或…

基于正点原子FreeRTOS学习笔记——时间片调度实验

目录 一、时间片调度介绍 二、实验演示 1、宏修改 1.1、滴答定时器宏 1.2、调度器宏 2、实验程序 2.1.1、任务1,任务2不加临界区程序 2.1.2 实验现象 2.2.1、任务1,任务2加临界区程序 2.2.2 实验现象 一、时间片调度介绍 时间片:同…

Golang中defer和return顺序

在Golang中,defer 和 return 的执行顺序是一个重要的特性,它们的执行顺序如下: return语句不是一条单独的语句,实际上,它是由赋值和返回两部分组成的。赋值步骤会先执行,这一步会计算return语句中的表达式…

【后端面试题】【中间件】【NoSQL】MongoDB的配置服务器、复制机制、写入语义和面试准备

MongoDB的配置服务器 引入了分片机制之后,MongoDB启用了配置服务器(config server) 来存储元数据,这些元数据包括分片信息、权限控制信息,用来控制分布式锁。其中分片信息还会被负责执行查询mongos使用。 MongoDB的配置服务器有一个很大的优…

【C语言】const 关键字

在C语言中,const关键字用于定义常量,使得变量的值在其声明之后无法被修改。这可以帮助防止意外修改数据,提高代码的安全性和可读性。以下是有关const关键字的一些详细说明: 基本用法 const int max_value 100;在这个例子中&…

Zynq系列FPGA实现SDI视频编解码+图像缩放,基于GTX高速接口,提供4套工程源码和技术支持

目录 1、前言工程概述免责声明 2、相关方案推荐本博已有的 SDI 编解码方案本博已有的FPGA图像缩放方案本方案的无缩放应用本方案在Xilinx--Kintex系列FPGA上的应用 3、详细设计方案设计原理框图SDI 输入设备Gv8601a 均衡器GTX 解串与串化SMPTE SD/HD/3G SDI IP核BT1120转RGB纯V…

FastApi中的常见请求类型

FastApi中的常见请求类型 后端开发语言中,我钟情于node,高效的异步处理真是让我眼前一亮,同时,简单易懂的语法也让我非常倾心 但是但是,因为考虑要写一个深度学习算法的后端接口,所以不得不选用python作为…

容器安全:等保合规性的基石

随着云计算和微服务架构的蓬勃发展,容器技术已经成为现代IT基础设施不可或缺的一部分。在网络安全等级保护制度(等保)的框架下,容器安全的要求日益凸显,成为等保合规性的基石。本文将深入探讨容器安全在等保中的重要性…

nginx的配置文件

nginx.conf 1、全局模块 worker_processes 1; 工作进程数,设置成服务器内核数的2倍(一般不超过8个,超过8个反正会降低性能,4个 1-2个 ) 处理进程的过程必然涉及配置文件和展示页面,也就是涉及打开文件的…

让围绕数据库构建大模型应用更简单方便--DB-GPT

DB-GPT的目的是构建大模型领域的基础设施,通过开发多模型管理(SMMF)、Text2SQL效果优化、RAG框架以及优化、Multi-Agents框架协作、AWEL(智能体工作流编排)等多种技术能力,让围绕数据库构建大模型应用更简单,更方便。 1 处理流程 DB-GPT系…

问题集锦1

01.inner中使用JwtTokenUtil.getUserCode() 前端调用上传(java),上传使用加购 Overridepublic Boolean insertShoppingCart(InsertShoppingCartParamsDto dto) {// 通过userCode,itemCode和supplierCode来判断当前加购人添加到购物车的商品是…

美术馆预约小程序的设计

管理员账户功能包括:系统首页,个人中心,展品信息管理,管理员管理,用户管理,美术馆管理,基础数据管理,论坛管理 微信端账号功能包括:系统首页,美术馆&#xff…

工业路由器与家用路由器的区别

在现代网络环境中,路由器扮演着至关重要的角色。无论是在家庭网络还是在工业网络,选择合适的路由器都至关重要。本文将从多个角度,对工业路由器与家用路由器进行详细比较,帮助您更好地理解二者的区别。 1、安全性 工业路由器&…

API接口测试/Swgger-ui未授权访问

目录 API接口 接口文档 接口测试的方法 单流程 多流程 Swgger-ui未授权访问 在之间的一次面试中面试官问到了API接口测试,我回答的不好,因为自己确实不太会,后面才下去学习了,这里复习和练习一下 API接口 API(…

背景图的动效,非常的炫酷,非一般的感觉。

我们都知道在一些展示型项目中,背景图加上动效后,可以立马让整个设计档次提升了,这次带来了一批背景图的动效图,大家看一下。

震惊!张宇强化36讲1200页,暑期强化高效利用指南!

特别喜欢张宇老师的讲课风格 如果你打算跟张宇老师,那么基础——>强化——>冲刺,你应该这么买书! 张宇老师25版课程大改版,其中,36讲的变动是最大的,张宇老师25版课程把以往的强化课程前移&#xff0…

基于多视点编码光场的全景三维重建方法

欢迎关注GZH《光场视觉》 摘要:在基于光场的一系列应用中,目标的三维重建是基础且关键的任务。普通光场只能重建单一视角而无法重建全景,并且在纹理特征匮乏的区域也无法生成准确的三维信息。针对以上问题,提出一种基于多视点编码…

视频字幕提取在线工具有哪些?总结5个字幕提取工具

平时在沉浸式追剧的时候,我们常常都会被影视剧中的各种金句爆梗而逗得开怀大笑~而真正要用到时候却总是一片头脑空白。其实要记住它们最好的办法便是将其提取留档下来,每次有需要的时候打开就能一下子回顾到~ 今天就来带大家盘一盘视频字幕提取的软件好…