」工欲善其事,必先利其器。「—孔子《論語.錄靈公》
首頁 > 程式設計 > 石頭、剪刀、布,戰鬥!

石頭、剪刀、布,戰鬥!

發佈於2024-11-08
瀏覽:799

Rock, paper, scissors, fight!

Rock, paper, scissors is a great game. Simple to grasp, yet surprisingly complex in terms of strategy. It's an ideal coding challenge to write a computer player capable of consistently winning the game. First though, we need a way to play the game.

Representing the game

We start with two players:

PLAYER1 = 1
PLAYER2 = 2

We then have three choices to play each round:

ROCK = 3
PAPER = 4
SCISSORS = 5

And a set of possible outcomes:

WIN = 6
LOSE = 7
DRAW = 8

With these symbols in place we can model the game state. That is, every possible way a round can end. Let us do this using a Python dictionary, mapping the two player choices (as a tuple) to the game outcome.

GAME_STATES = {
    (ROCK, PAPER): LOSE,
    (ROCK, SCISSORS): WIN,
    (ROCK, ROCK): DRAW
    (PAPER, SCISSORS): LOSE,
    (PAPER, ROCK): WIN,
    (PAPER, PAPER): DRAW,
    (SCISSORS, ROCK): LOSE,
    (SCISSORS, PAPER): WIN,
    (SCISSORS, SCISSORS): DRAW
}

Now we can write a simple function to play one round of the game. We are going to assume each player is an instance of a class that we will define later. For now it is enough to know how this class is called, if not how it will be implemented.

def play_round(p1, p2):
    """ Play one round of the game with the two supplied players. """
    p1_choice = p1.pick()
    p2_choice = p2.pick()
    p1_outcome = GAME_STATES[(p1_choice, p2_choice)]
    p2_outcome = GAME_STATES[(p2_choice, p1_choice)]
    p1.record((p1_choice, p2_choice, p1_outcome))
    p2.record((p2_choice, p1_choice, p2_outcome))
    winner = 0
    if p1_outcome == WIN:
        winner = PLAYER1
    elif p2_outcome == WIN:
        winner = PLAYER2
    return winner

The game round is very simple. We ask each player object to pick a choice to play. We then lookup the result for each player in the GAME_STATES dictionary. We ask each player object to record the result of the game. Finally we return the winner to the caller, or zero if there was a draw.

So what does a player look like? First we define a base class to perform some common initialisation, and recording of the game round data.

class Player:
    """ Base class for a player of the game. """
    def __init__(self, name):
        self.name = name
        self.history = []


    def pick(self):
        """Return one of the three choices: ROCK, PAPER, SCISSORS."""
        raise NotImplementedError()


    def record(self, game_details):
        """Record the details of the round."""
        self.history.append(game_details)

Next we can inherit from this class and implement our picking strategy. Here we have a player that always plays ROCK:

class AlwaysRockPlayer(Player):
    """ Player who always chooses ROCK. """
    def pick(self):
        return ROCK

Not a great strategy I'm sure you'll agree, but we start with the simplest thing we can do. Let's write a slightly more complex player for our rock steady one to go up against:

class RandomPlayer(Player):
    """ Player who always makes a random choice. """
    def pick(self):
        import random
        random.seed()
        return random.randint(ROCK, SCISSORS)

That at least gives us some variety in proceedings! It's still a very simple player though, as it ignores the game history completely. Let's pit these two players against each other in a few rounds.

>>> p1 = AlwaysRockPlayer("The Rock")
>>> p2 = RandomPlayer("Random Rick")
>>> play_round(p1, p2)
0
>>> play_round(p1, p2)
1
>>> play_round(p1, p2)
2
>>> play_round(p1, p2)
2
>>> play_round(p1, p2)
1

OK, so things are working. But to really get a feel for how they perform we need to run them for longer. Let's write a quick loop to run a 100 rounds between these two fearsome opponents:

>>> results = []
>>> for i in range(1,101):
...     results.append(play_round(p1, p2))
...     print(results[i-1], end='')
...     if i % 10 == 0:
...             print()
...
0102201112
0112202100
0121012101
1211200212
0110021121
0000120222
0102000202
2020021110
1112010101
1121020010

Better. A quick tot up of the results shows that... player 1 is the winner! Who'd have thought always playing ROCK was a viable game strategy? OK, so the rock's random opponent is a little dumb in this regard. A human player would soon spot the pattern and counter it consistently. We need better players, and a proper arena for them to duel it out in.

New Arena

The new arena will play a game over several rounds between two players. It will print the game statistics at the end, so we can easily see how well each player has performed. The new code makes use of our existing play_round function, and the code is given below:

def play_game(p1, p2, rounds=100):
    """ Play several rounds of the game, reporting statistics at the end. """
    print(f"{p1.name} vs {p2.name}")
    results = []
    for i in range(rounds):
        results.append(play_round(p1, p2))
        print(".", end="")
    p1_total = len([x for x in results if x == PLAYER1])
    p2_total = len([x for x in results if x == PLAYER2])
    no_total = len([x for x in results if x == 0])
    total = float(len(results))
    print("")
    print(f"{p1.name}: {(p1_total / total) * 100}%")
    print(f"{p2.name}: {(p2_total / total) * 100}%")
    print(f"Drawn games: {(no_total / total) * 100}%")

Let's pit our two players against each other in this new arena and see if The Rock can retain its crown.

>>> p1 = AlwaysRockPlayer("The Rock")
>>> p2 = RandomPlayer("Random Rick")
>>> play_game(p1, p2)
The Rock vs Random Rick
....................................................................................................
The Rock: 39.0%
Random Rick: 31.0%
Drawn games: 30.0%
>>>

A more even spread this time. Let's try running for a 1000 rounds and see if that makes a difference.

>>> play_game(p1, p2, 1000)
The Rock vs Random Rick
........................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................
The Rock: 34.300000000000004%
Random Rick: 34.5%
Drawn games: 31.2%
>>>

Huh, a much more even spread. In fact this is what we should have expected. With The Rock always picking, well, ROCK, the variation we are seeing is solely down to Random Rick. If the PRNG (pseudo random number generator) in Python is any good, it'll be picking each choice roughly equally. The more rounds we play, the closer to an even split we would get.

No two ways about it, we still need a smarter player.

Remembering

We need a player that can learn from history without becoming predictable. But how to do that? Instead of picking a choice at random, the player picks an entry from its history at random. Then it plays whatever would have beaten its opponent in that round. In theory, if the opponent is playing one choice more than the others, this should give us the edge.

Let's see what that looks like in code:

class RandomHistoryPlayer(Player):
    """ Player who picks at random from historical options of their opponent. """
    BEATEN_BY = {
        ROCK: PAPER,
        PAPER: SCISSORS,
        SCISSORS: ROCK
    }

    def pick(self):
        import random
        random.seed()
        total_rounds = len(self.history)
        if total_rounds == 0:    
            choice = random.randint(ROCK, SCISSORS)
        else:
            idx = random.randint(0, len(self.history) - 1)
            opponents_choice = self.history[idx][1]
            choice = self.__class__.BEATEN_BY[opponents_choice]
        return choice

When playing the first round, we don't have any history to work from, so we fallback to playing at random.

OK, moment of truth. Hoe does it perform?

>>> p1 = RandomHistoryPlayer("Historical Henry")
>>> p2 = AlwaysRockPlayer("The Rock")
>>> play_game(p1, p2)
Historical Henry vs The Rock
....................................................................................................
Historical Henry: 99.0%
The Rock: 0.0%
Drawn games: 1.0%
>>>

It obliterates The Rock. With the exception of the random choice it makes first round, it won every other game. How does it perform against Random Rick?

>>> p1 = RandomHistoryPlayer("Historic Henry")
>>> p2 = RandomPlayer("Random Rick")
>>> play_game(p1, p2)
Historic Henry vs Random Rick
....................................................................................................
Historic Henry: 32.0%
Random Rick: 41.0%
Drawn games: 27.0%
>>>

Oh dear. Best of three? So it fails against a purely random opponent. Surely we can do better?

Forgetting

The trouble with remembering everything is you can get stuck in old ways of thinking. We humans have learnt to forget, or at least discount, things that happened in the dim distant past. What we need is a way to weight the historical results, so that more recent games have a greater influence. Yes, that ought to do it. I'm sure this will give us the intelligent player we seek.

class WeightedHistoryPlayer(Player):
    """ Computer player that linearly weights the past opponents choices. """
    BEATEN_BY = {
        ROCK: PAPER,
        PAPER: SCISSORS,
        SCISSORS: ROCK
    }


    def pick(self):
        import random
        random.seed()
        total_rounds = len(self.history)
        if total_rounds == 0:
            choice = random.randint(ROCK, SCISSORS)
        else:
            weighted_outcomes = [(i / total_rounds, o) for i, o in enumerate(self.history)]
            totals = { ROCK: 0, PAPER: 0, SCISSORS: 0 }
            totals[ROCK] = sum([w for (w,o) in weighted_outcomes if o[1] == ROCK])
            totals[PAPER] = sum([w for (w,o) in weighted_outcomes if o[1] == PAPER])
            totals[SCISSORS] = sum([w for (w,o) in weighted_outcomes if o[1] == SCISSORS])
            opponents_choice = max(totals, key=totals.get)
            choice = self.__class__.BEATEN_BY[opponents_choice]
        return choice

Is it better than Historical Henry?

>>> p1 = WeightedHistoryPlayer("Forgetful Fiona")
>>> p2 = RandomHistoryPlayer("Historical Henry")
>>> play_game(p1, p2)
Forgetful Fiona vs Historical Henry
....................................................................................................
Forgetful Fiona: 43.0%
Historical Henry: 43.0%
Drawn games: 14.000000000000002%
>>>

A dead heat! How about taking on the current champion Random Rick?

>>> p1 = WeightedHistoryPlayer("Forgetful Fiona")
>>> p2 = RandomPlayer("Random Rick")
>>> play_game(p1, p2)
Forgetful Fiona vs Random Rick
....................................................................................................
Forgetful Fiona: 35.0%
Random Rick: 38.0%
Drawn games: 27.0%
>>>

Drat! Random Rick still retains his crown. We need something else.

Looking for patterns

There must be a pattern in Random Rick that we can exploit. Despite his seemingly random nature, I suspect he is harbouring predictable patterns. How can we write a player to take advantage of them?

N-grams can allow us to look for recurring sequences of symbols. Think of it as a sliding window over the opponents choices. We look at n choices, and then record what the n 1 choice was. Lets show an example using trigrams (n-grams of size 3).

Sequence of opponents moves:

ROCK ROCK PAPER SCISSORS ROCK ROCK ROCK PAPER SCISSORS ROCK ROCK PAPAER

Trigrams:

    ROCK ROCK PAPER     -> SCISSORS
    ROCK PAPER SCISSORS -> ROCK
    PAPER SCISSORS ROCK -> ROCK
    SCISSORS ROCK ROCK  -> ROCK
    ROCK ROCK ROCK      -> PAPER
    ROCK ROCK PAPER     -> SCISSORS
    ROCK PAPER SCISSORS -> ROCK
    PAPER SCISSORS ROCK -> ROCK
    SCISSORS ROCK ROCK  -> PAPER

To predict the next move the opponent makes given the example above, we would look at the latest trigram in the sequence - ROCK ROCK PAPER, look it up in the list of trigrams, and see what has previously come next - SCISSORS. We would play whatever beats that choice, in this case ROCK.

Lets look at some code for this strategy:

class TrigramPlayer(Player):
    """ Computer player that uses trigrams to look for patterns in the opponents choices. """
    BEATEN_BY = {
        ROCK: PAPER,
        PAPER: SCISSORS,
        SCISSORS: ROCK
    }


    def __init__(self, id):
        super().__init__(id)
        self.trigrams = {}


    def pick(self):
        import random
        random.seed()
        total_rounds = len(self.history)
        if total_rounds  1:
                idx = random.randint(0, len(previous_choices) - 1)
                choice = previous_choices[idx]
            else:
                choice = random.randint(ROCK, SCISSORS)
        return choice


    def record(self, game_details):
        super().record(game_details)
        round_num = len(self.history)
        if round_num > 3:
            sequence = [x[1] for x in self.history]
            trigram = tuple(sequence[-4:-1])
            choice = sequence[-1]
            targets = self.trigrams.get(trigram, [])
            targets.append(choice)
            self.trigrams[trigram] = targets

We allow some randomness to creep in here:

  • When we have more than one match for our current trigram.
  • Before round 4, as there simply isn't enough data to build a trigram entry.
  • If we don't find a match in the trigram dictionary.

OK, in at the deep end. How does it perform against Random Rick?

>>> p1 = TrigramPlayer("Trigram Tracy")
>>> p2 = RandomPlayer("Random Rick")
>>> play_game(p1, p2)
Trigram Tracy vs Random Rick
....................................................................................................
Trigram Tracy: 31.0%
Random Rick: 34.0%
Drawn games: 35.0%
>>>

I give up. It seems that as far as rock, paper, scissors goes, randomness is the winning strategy.

Only human

So looking for patterns in the choices of Random Rick failed. But can Trigram Tracy find subconscious patterns in the pinnacle of intellect? Not ChatGPT, a human.

Let us write a human player class to interactively prompt for input.

class HumanPlayer(Player):
    """ Human player at a keyboard. """
    CHAR_2_INT = { "r": ROCK, "p": PAPER, "s": SCISSORS }


    def pick(self):
        choice = ""
        while choice not in ['r', 'p', 's']:
            choice = input("(r)ock, (p)aper, or (s)cissors? ")
        return self.__class__.CHAR_2_INT[choice]

Lets see who will win:

>>> p1 = HumanPlayer("Human Rob")
>>> p2 = TrigramPlayer("Trigram Tracy")
>>> play_game(p1, p2)
Human Rob vs Trigram Tracy

... cut lots of prompts for choices ...

Human Rob: 32.0%
Trigram Tracy: 32.0%
Drawn games: 36.0%

Well there you have it. I'm officially as intelligent as a short Python script when it comes to playing Rock, Paper, Scissors. Hardly a ringing endorsement of our AI either.

What have we learnt

There are a lot of possible strategies for playing rock, paper, scissors. Some simple, some more complex. We have learnt that a player picking at random can defeat a more sophisticated artificial intelligence, by virtue of being unpredictable.

Out of curiosity let's ask the font of all modern knowledge - ChatGPT - what it thinks is the best strategy to adopt for playing Rock, Paper, Scissors:

The best strategy for playing Rock, Paper, Scissors against a computer opponent is to play as randomly as possible. This is because computer programs often build strategies based on your play patterns or draw techniques from a massive database of previously recorded rounds. By picking your answer blindly, you render the program’s collected patterns about your behavior useless, and should be able to tie the machine in the long run.

Sometimes being clever is over rated!

Complete program listing

#! /usr/bin/env python3


# Players.
PLAYER1 = 1
PLAYER2 = 2


# Choices.
ROCK = 3
PAPER = 4
SCISSORS = 5


# Outcomes.
WIN = 6
LOSE = 7
DRAW = 8


# All possible game states.
GAME_STATES = {
    (ROCK, PAPER) : LOSE,
    (ROCK, SCISSORS) : WIN,
    (ROCK, ROCK) : DRAW,
    (PAPER, SCISSORS) : LOSE,
    (PAPER, ROCK) : WIN,
    (PAPER, PAPER) : DRAW,
    (SCISSORS, ROCK) : LOSE,
    (SCISSORS, PAPER) : WIN,
    (SCISSORS, SCISSORS) : DRAW
}


class Player:
    """ Base class for a player of the game. """
    def __init__(self, name):
        self.name = name
        self.history = []


    def pick(self):
        """Return one of the three choices: ROCK, PAPER, SCISSORS."""
        raise NotImplementedError()


    def record(self, game_details):
        """Record the details of the round."""
        self.history.append(game_details)


class AlwaysRockPlayer(Player):
    """ Player who always chooses ROCK. """
    def pick(self):
        return ROCK


class RandomPlayer(Player):
    """ Player who always makes a random choice. """
    def pick(self):
        import random
        random.seed()
        return random.randint(ROCK, SCISSORS)


class RandomHistoryPlayer(Player):
    """ Player who picks at random from historical options of their opponent. """
    BEATEN_BY = {
        ROCK: PAPER,
        PAPER: SCISSORS,
        SCISSORS: ROCK
    }


    def pick(self):
        import random
        random.seed()
        total_rounds = len(self.history)
        if total_rounds == 0:    
            choice = random.randint(ROCK, SCISSORS)
        else:
            idx = random.randint(0, len(self.history) - 1)
            opponents_choice = self.history[idx][1]
            choice = self.__class__.BEATEN_BY[opponents_choice]
        return choice


class WeightedHistoryPlayer(Player):
    """ Computer player that linearly weights the past opponents choices. """
    BEATEN_BY = {
        ROCK: PAPER,
        PAPER: SCISSORS,
        SCISSORS: ROCK
    }


    def pick(self):
        import random
        random.seed()
        total_rounds = len(self.history)
        if total_rounds == 0:
            choice = random.randint(ROCK, SCISSORS)
        else:
            weighted_outcomes = [(i / total_rounds, o) for i, o in enumerate(self.history)]
            totals = { ROCK: 0, PAPER: 0, SCISSORS: 0 }
            totals[ROCK] = sum([w for (w,o) in weighted_outcomes if o[1] == ROCK])
            totals[PAPER] = sum([w for (w,o) in weighted_outcomes if o[1] == PAPER])
            totals[SCISSORS] = sum([w for (w,o) in weighted_outcomes if o[1] == SCISSORS])
            opponents_choice = max(totals, key=totals.get)
            choice = self.__class__.BEATEN_BY[opponents_choice]
        return choice


class TrigramPlayer(Player):
    """ Computer player that uses trigrams to look for patterns in the opponents choices. """
    BEATEN_BY = {
        ROCK: PAPER,
        PAPER: SCISSORS,
        SCISSORS: ROCK
    }


    def __init__(self, id):
        super().__init__(id)
        self.trigrams = {}


    def pick(self):
        import random
        random.seed()
        total_rounds = len(self.history)
        if total_rounds  1:
                idx = random.randint(0, len(previous_choices) - 1)
                choice = previous_choices[idx]
            else:
                choice = random.randint(ROCK, SCISSORS)
        return choice


    def record(self, game_details):
        super().record(game_details)
        round_num = len(self.history)
        if round_num > 3:
            sequence = [x[1] for x in self.history]
            trigram = tuple(sequence[-4:-1])
            choice = sequence[-1]
            targets = self.trigrams.get(trigram, [])
            targets.append(choice)
            self.trigrams[trigram] = targets


class HumanPlayer(Player):
    """ Human player at a keyboard. """
    CHAR_2_INT = { "r": ROCK, "p": PAPER, "s": SCISSORS }


    def pick(self):
        choice = ""
        while choice not in ['r', 'p', 's']:
            choice = input("(r)ock, (p)aper, or (s)cissors? ")
        return self.__class__.CHAR_2_INT[choice]


def play_round(p1, p2):
    """ Play one round of the game with the two supplied players. """
    p1_choice = p1.pick()
    p2_choice = p2.pick()
    p1_outcome = GAME_STATES[(p1_choice, p2_choice)]
    p2_outcome = GAME_STATES[(p2_choice, p1_choice)]
    p1.record((p1_choice, p2_choice, p1_outcome))
    p2.record((p2_choice, p1_choice, p2_outcome))
    winner = 0
    if p1_outcome == WIN:
        winner = PLAYER1
    elif p2_outcome == WIN:
        winner = PLAYER2
    return winner


def play_game(p1, p2, rounds=100):
    """ Play several rounds of the game, reporting statistics at the end. """
    print(f"{p1.name} vs {p2.name}")
    results = []
    for i in range(rounds):
        results.append(play_round(p1, p2))
        print(".", end="")
    p1_total = len([x for x in results if x == PLAYER1])
    p2_total = len([x for x in results if x == PLAYER2])
    no_total = len([x for x in results if x == 0])
    total = float(len(results))
    print("")
    print(f"{p1.name}: {(p1_total / total) * 100}%")
    print(f"{p2.name}: {(p2_total / total) * 100}%")
    print(f"Drawn games: {(no_total / total) * 100}%")
版本聲明 本文轉載於:https://dev.to/robc79/rock-paper-scissors-fight-26ci?1如有侵犯,請洽[email protected]刪除
最新教學 更多>
  • 如何使用 JavaScript 從 iFrame 重新導向父視窗?
    如何使用 JavaScript 從 iFrame 重新導向父視窗?
    從iFrame 重定向父視窗如果父視窗中嵌入了iFrame,則可能需要重定向父視窗視窗的位置更改為新的URL。為了實現這一點,JavaScript 提供了一個簡單的解決方案。 使用JavaScript 重新導向父視窗在iFrame 的JavaScript 程式碼中,您可以使用以下方法: 重定向最頂層...
    程式設計 發佈於2024-11-09
  • 使用 JavaScript 的日期建構函式時,是什麼導致 Internet Explorer 中出現 NaN 錯誤?
    使用 JavaScript 的日期建構函式時,是什麼導致 Internet Explorer 中出現 NaN 錯誤?
    IE 中的日期建構函式故障:跨瀏覽器比較在Web 開發領域,JavaScript 的日期建構函式已被證明是一個尋求操縱日期的開發人員的可靠盟友。然而,在主流瀏覽器中使用這個建構函式時,觀察到了一個奇怪的現象。雖然 Firefox 和 Chrome 很高興地接受了 Date 的功能,但 Interne...
    程式設計 發佈於2024-11-09
  • 如何在 JavaScript 中使用代理實作屬性的無此類方法行為?
    如何在 JavaScript 中使用代理實作屬性的無此類方法行為?
    為屬性實現基於代理的noSuchMethodJavaScript 中的noSuchMethod 函數允許攔截對不存在方法的調用。然而,是否有類似的屬性機制? ES6 代理來救援ES6 代理程式提供了自訂屬性存取的能力。我們可以利用它來模擬屬性的類似 __noSuchMethod__ 的行為:func...
    程式設計 發佈於2024-11-09
  • 何時以及如何在 JavaScript 的 parseInt() 函數中使用 Radix?
    何時以及如何在 JavaScript 的 parseInt() 函數中使用 Radix?
    了解 parseInt 中對基數的需求JavaScript 中的 parseInt() 函數可讓您將表示數字的字串轉換為整數。但是,您可能不會總是希望將整數解析為以 10 為基數的數字。這就是基數參數發揮作用的地方。 什麼是基數? 基數是指在數字系統中單一數字可以表示的值的數量。例如,我們常用的十進...
    程式設計 發佈於2024-11-09
  • 如何在 CSS 中設定表格單元寬度:為什麼最小寬度和最大寬度不起作用?
    如何在 CSS 中設定表格單元寬度:為什麼最小寬度和最大寬度不起作用?
    使用表格單元格的寬度屬性儘管如此,最小寬度和最大寬度屬性不適用於表格單元格。根據 CSS 規範,它們對表格單元格的影響未定義。 替代解決方案要定義表格單元格的寬度,請改用 width 屬性。它有效地設定表格單元格的最小和最大寬度。 範例:td { width: 100px; }表格佈局為了進...
    程式設計 發佈於2024-11-09
  • 使用 Node.js 流進行高效能資料處理
    使用 Node.js 流進行高效能資料處理
    在本文中,我们将深入研究 Node.js Streams 并了解它们如何帮助高效处理大量数据。流提供了一种处理大型数据集的优雅方式,例如读取大型文件、通过网络传输数据或处理实时信息。与一次性读取或写入整个数据的传统 I/O 操作不同,流将数据分解为可管理的块并逐块处理它们,从而实现高效的内存使用。 ...
    程式設計 發佈於2024-11-09
  • 如何使用分塊有效檢索大型 MySQL 選擇?
    如何使用分塊有效檢索大型 MySQL 選擇?
    透過分塊高效檢索大型 MySQL 選擇在 MySQL 中處理大型資料集通常會導致資料擷取期間出現記憶體問題。為了解決這個問題,分塊提供了一個有效的解決方案。 分塊技術分塊涉及將大型選擇查詢拆分為較小的子集。透過這樣做,您可以在可管理的部分中處理數據,從而防止記憶體限制。 考慮以下範例:SELECT ...
    程式設計 發佈於2024-11-09
  • 為什麼在一行上宣告多個物件指標會導致 C++ 中的編譯器錯誤?
    為什麼在一行上宣告多個物件指標會導致 C++ 中的編譯器錯誤?
    在一行上宣告多個物件指標:解決編譯器錯誤在同一行宣告多個物件指標時,開發人員經常遇到一個常見問題,可能會導致編譯器錯誤。了解此問題的根本原因對於確保正確執行程式碼至關重要。 考慮以下類別聲明:public: Entity() { re_sprite_eyes = ne...
    程式設計 發佈於2024-11-09
  • 如何使用 CSS 剪輯路徑和 JavaScript 實現反轉文字顏色懸停效果?
    如何使用 CSS 剪輯路徑和 JavaScript 實現反轉文字顏色懸停效果?
    使用CSS 和JavaScript 反轉滑鼠懸停時的文字顏色實現所需的懸停效果,其中黑色文字反轉為白色,同時保持出現黑色遊標時,我們可以將CSS 剪輯路徑的功能與JavaScript 事件處理結合。 此方法包括建立兩層文字:主文本層和反轉的文字層。倒置文字圖層位於主文字圖層後面,並將其文字顏色設為白...
    程式設計 發佈於2024-11-09
  • 量子計算:它將如何重新定義技術
    量子計算:它將如何重新定義技術
    量子计算代表了 21 世纪最深刻的技术进步之一。与使用位来处理 0 或 1 信息的经典计算机不同,量子计算机使用可以同时存在于多种状态的量子位或量子位。计算领域的这一根本性转变有望重新定义技术,推动各个领域的突破并解决目前经典系统难以解决的问题。 在本文中,我们将探讨量子计算的工作原理、其潜在应用以...
    程式設計 發佈於2024-11-09
  • 如何增加 PHP 最大 POST 變數限制?
    如何增加 PHP 最大 POST 變數限制?
    PHP最大POST變數限制處理具有大量輸入欄位的POST請求時,當變數數量超過預設值時,會出現常見問題PHP 中的限制。例如,超過 1000 個欄位的表單可能只會公開 $_POST 陣列中的前 1001 個變數。 要解決此問題,需要調整 PHP 允許的 POST 變數的最大數量。在版本 5.3.9 ...
    程式設計 發佈於2024-11-09
  • 如何垂直對齊 a 內部?
    如何垂直對齊 a 內部?
    在 內垂直對齊考慮以下情況:您有一個 嵌套在< div> ,如這段程式碼所示:&lt;div id="theMainDiv" style=" border:solid 1px gray; cursor:text; width:4...
    程式設計 發佈於2024-11-09
  • 如何在PHP中儲存和恢復數組以實現高效的離線存取?
    如何在PHP中儲存和恢復數組以實現高效的離線存取?
    在PHP 中儲存和恢復數組以供本地訪問您已從遠端API 獲取數組並希望將其存儲在本地以供離線使用操縱。為了實現這一目標,您可以在不影響效能或檔案大小的情況下利用 JSON 序列化。 JSON 序列化:編碼和解碼PHP 為JSON 序列化提供了兩個關鍵函數:json_encode 將陣列轉換為人類可讀...
    程式設計 發佈於2024-11-09
  • 如何使用 Docker 部署 Go 應用程式
    如何使用 Docker 部署 Go 應用程式
    Docker is a containerization platform that simplifies applications’ packaging, distribution, and deployment. You can harness the benefits of Go and Do...
    程式設計 發佈於2024-11-09
  • 使用 JavaScript Web 元件和 LIT 建置可重複使用元件
    使用 JavaScript Web 元件和 LIT 建置可重複使用元件
    在當今快節奏的 Web 開發環境中,建立可重複使用和可維護的元件是關鍵。 JavaScript Web 元件 提供了一種原生方法來建立跨框架工作的獨立、模組化元素。然而,手動建立這些組件可能既乏味又複雜。這就是 LIT 發揮作用的地方! LIT 簡化了建立 Web 元件的過程,使管理狀態、反應性和...
    程式設計 發佈於2024-11-09

免責聲明: 提供的所有資源部分來自互聯網,如果有侵犯您的版權或其他權益,請說明詳細緣由並提供版權或權益證明然後發到郵箱:[email protected] 我們會在第一時間內為您處理。

Copyright© 2022 湘ICP备2022001581号-3