Cvičení – logika hry

Dokončeno

V tomto cvičení přidáme do naší aplikace logiku hry, abychom zajistili, že skončíme plně funkční hrou.

Abychom vám pomohli udržet tento kurz na téma s výukou o Blazoru, poskytujeme třídu s názvem GameState , která obsahuje logiku pro správu hry.

Přidání stavu hry

Pojďme do projektu přidat GameState třídu a pak ji zpřístupnit komponentám jako jednoúčelovou službu prostřednictvím injektáže závislostí.

  1. Zkopírujte soubor GameState.cs do kořenového adresáře projektu.

  2. Otevřete soubor Program.cs v kořenovém adresáři projektu a přidejte tento příkaz, který se ve vaší aplikaci konfiguruje GameState jako jednoúčelová služba:

    builder.Services.AddSingleton<GameState>();
    

    Teď můžeme do naší Board komponenty vložit instanci GameState třídy.

  3. Na začátek souboru Board.razor přidejte následující @inject direktivu. směrnice vloží aktuální stav hry do komponenty:

    @inject GameState State
    

    Teď můžeme začít připojovat naši Board komponentu ke stavu hry.

Resetování stavu

Začněme resetováním stavu hry, když Board je komponenta poprvé namalována na obrazovce. Přidejte kód pro resetování stavu hry při inicializaci komponenty.

  1. Přidejte metodu s voláním OnInitialized ResetBoard, uvnitř @code bloku v dolní části souboru Board.razor , například takto:

    @code {
        protected override void OnInitialized()
        {
            State.ResetBoard();
        }
    }
    

    Když se panel poprvé zobrazí uživateli, stav se obnoví na začátek hry.

Vytváření herních kousků

V dalším kroku přidělme možné 42 herních kusů, které by se daly hrát. Herní části můžeme reprezentovat jako pole odkazované 42 prvky HTML na panelu. Tyto části můžeme přesunout a umístit tak, že přiřadíme sadu tříd CSS s pozicemi sloupců a řádků.

  1. Abychom mohli uchovávat herní kousky, definujeme pole pole řetězců v bloku kódu:

    private string[] pieces = new string[42];
    
  2. Do oddílu HTML přidejte kód, který vytvoří 42 span značek, jeden pro každou část hry ve stejné komponentě:

    @for (var i = 0; i < 42; i++)
    {
       <span class="@pieces[i]"></span>
    }
    

    Celý kód by měl vypadat takto:

    <div>
        <div class="board">
        @for (var i = 0; i < 42; i++)
        {
            <span class="container">
                <span></span>
            </span>
        }
        </div>
        @for (var i = 0; i < 42; i++)
        {
           <span class="@pieces[i]"></span>
        }
    </div>
    @code {
        private string[] pieces = new string[42];
    
        protected override void OnInitialized()
        {
            State.ResetBoard();
        }
    }
    

    Tím se přiřadí prázdný řetězec třídě CSS každého herního rozsahu. Prázdný řetězec pro třídu CSS zabraňuje zobrazení herních částí na obrazovce, protože na ně není použit žádný styl.

Zpracování umístění herního kusu

Pojďme přidat metodu pro zpracování, když hráč umístí kus do sloupce. Třída GameState ví, jak přiřadit správný řádek pro herní kus a hlásí řádek, ve které se dostane. Tyto informace můžeme použít k přiřazení tříd CSS představujících barvu hráče, konečné umístění kusu a animaci pro přetažení CSS.

Tuto metodu PlayPiecenazýváme a přijímá vstupní parametr, který určuje sloupec, který hráč zvolí.

  1. Přidejte tento kód pod pieces pole, které jsme definovali v předchozím kroku.

    private void PlayPiece(byte col)
    {
        var player = State.PlayerTurn;
        var turn = State.CurrentTurn;
        var landingRow = State.PlayPiece(col);
        pieces[turn] = $"player{player} col{col} drop{landingRow}";
    }
    

PlayPiece Kód dělá takto:

  1. Řekneme stavu hry, aby hrál kus v odeslaném sloupci volané col a zachytit řádek, do který kus přistál.
  2. Pak můžeme definovat tři třídy CSS, které se mají přiřadit k herní části, abychom identifikovali, který hráč právě působí, sloupec, do kterého byla část umístěna, a cílový řádek.
  3. Poslední řádek metody přiřadí tyto třídy k této hře v pieces poli.

Pokud se podíváte do zadaného Board.razor.css, najdete třídy CSS odpovídající sloupec, řádek a hráč otočit.

Výsledným efektem je, že herní kus je umístěn ve sloupci a animovaný, aby se při zavolání této metody dostal do dolního řádku nejvíce.

Výběr sloupce

Dále musíme umístit některé ovládací prvky, které hráčům umožňují vybrat sloupec a volat novou PlayPiece metodu. Pomocí znaku "🔽" označujeme, že můžete v tomto sloupci vložit kus.

  1. Nad počáteční <div> značku přidejte řádek tlačítek, na která můžete kliknout:

    <nav>
        @for (byte i = 0; i < 7; i++)
        {
            var col = i;
            <span title="Click to play a piece" @onclick="() => PlayPiece(col)">🔽</span>
        }
    </nav>
    

    Atribut @onclick určuje obslužnou rutinu události události pro událost kliknutí. Aby bylo možné zpracovávat události uživatelského rozhraní, musí se komponenta Blazor vykreslit pomocí interaktivního režimu vykreslování. Ve výchozím nastavení se komponenty Blazor vykreslují staticky ze serveru. Interaktivní režim vykreslování můžeme použít u komponenty pomocí atributu @rendermode .

  2. Aktualizujte komponentu Board Home na stránce tak, aby používala InteractiveServer režim vykreslování.

    <Board @rendermode="InteractiveServer" />
    

    Režim InteractiveServer vykreslování zpracovává události uživatelského rozhraní pro komponenty ze serveru přes připojení WebSocket s prohlížečem.

  3. Spusťte aplikaci s těmito změnami. Teď by měl vypadat takto:

    Snímek obrazovky s panelem Connect Four

    Ještě lepší je, že když vybereme jedno z tlačítek pro přetažení v horní části, můžete pozorovat následující chování:

    Snímek obrazovky s animací Připojit čtyři

Pěkně jste pokročili! Teď můžeme přidat kusy na desku. Objekt GameState je dostatečně chytrý, aby se mezi těmito dvěma hráči otočil dopředu a zpět. Pokračujte a vyberte další tlačítka pro vkládání a podívejte se na výsledky.

Vítězné zpracování a zpracování chyb

Pokud hru hrajete v aktuální konfiguraci, zjistíte, že při pokusu o vložení příliš mnoho kusů do stejného sloupce a když jeden hráč vyhraje hru.

Pojďme zjasnit aktuální stav naší hry přidáním některých indikátorů zpracování chyb a indikátorů na náš panel. Přidejte nad panel a pod tlačítka pro vkládání stavovou oblast.

  1. Za prvek vložte následující kód nav :

    <article>
        @winnerMessage  <button style="@ResetStyle" @onclick="ResetGame">Reset the game</button>
        <br />
        <span class="alert-danger">@errorMessage</span>
        <span class="alert-info">@CurrentTurn</span>
    </article>
    

    Tento kód nám umožňuje zobrazit indikátory pro:

    • Oznámení vítěze hry
    • Tlačítko, které nám umožňuje restartovat hru
    • Chybové zprávy
    • Otočení aktuálního hráče

    Teď vyplníme určitou logiku, která tyto hodnoty nastaví.

  2. Za pole částí přidejte následující kód:

    private string[] pieces = new string[42];
    private string winnerMessage = string.Empty;
    private string errorMessage = string.Empty;
    
    private string CurrentTurn => (winnerMessage == string.Empty) ? $"Player {State.PlayerTurn}'s Turn" : "";
    private string ResetStyle => (winnerMessage == string.Empty) ? "display: none;" : "";
    
    • Vlastnost CurrentTurn se automaticky vypočítá na základě stavu winnerMessage a PlayerTurn vlastnosti objektu GameState.
    • Vypočítá se ResetStyle na základě obsahu WinnerMessage. Pokud se winnerMessageobjeví tlačítko pro resetování, zobrazí se na obrazovce.
  3. Pojďme zpracovat chybovou zprávu při přehrávání kusu. Přidejte řádek pro vymazání chybové zprávy a pak kód v PlayPiece metodě zabalte blokem try...catch , který nastaví errorMessage , pokud došlo k výjimce:

    errorMessage = string.Empty;
    try
    {
        var player = State.PlayerTurn;
        var turn = State.CurrentTurn;
        var landingRow = State.PlayPiece(col);
        pieces[turn] = $"player{player} col{col} drop{landingRow}";
    }
    catch (ArgumentException ex)
    {
        errorMessage = ex.Message;
    }
    

    Náš indikátor obslužné rutiny chyby je jednoduchý a používá architekturu CSS bootstrap k zobrazení chyby v režimu nebezpečí.

    Snímek obrazovky vaší hry s deskou a kusy

  4. V dalším kroku přidáme metodu ResetGame , kterou naše tlačítko aktivuje k restartování hry. Jediným způsobem, jak restartovat hru, je v současné době aktualizovat stránku. Tento kód nám umožňuje zůstat na stejné stránce.

    void ResetGame()
    {
        State.ResetBoard();
        winnerMessage = string.Empty;
        errorMessage = string.Empty;
        pieces = new string[42];
    }
    

    Naše ResetGame metoda teď má následující logiku:

    • Resetujte stav panelu.
    • Skryjte naše indikátory.
    • Obnovte pole částí na prázdnou matici 42 řetězců.

    Tato aktualizace by nám měla umožnit hrát hru znovu, a teď vidíme indikátor přímo nad deskou deklarující otočení hráče a nakonec dokončení hry.

    Snímek obrazovky zobrazující hru

    Stále máme situaci, kdy nemůžeme vybrat tlačítko resetování. Pojďme do metody přidat nějakou logiku PlayPiece , která detekuje konec hry.

  5. Pojďme zjistit, jestli je ve hře vítěz, a to přidáním výrazu switch za blok try...catch v PlayPiecesouboru .

    winnerMessage = State.CheckForWin() switch
    {
        GameState.WinState.Player1_Wins => "Player 1 Wins!",
        GameState.WinState.Player2_Wins => "Player 2 Wins!",
        GameState.WinState.Tie => "It's a tie!",
        _ => ""
    };
    

    Metoda CheckForWin vrátí výčt, který hlásí, který hráč, pokud některý z hráčů vyhrál hru nebo pokud je hra vázaná. Tento výraz přepínače nastaví winnerMessage pole odpovídajícím způsobem, pokud dojde ke stavu hry.

    Když teď hrajeme a dostaneme se ke scénáři ukončení hry, zobrazí se tyto indikátory:

    Snímek obrazovky znázorňující resetování hry

Shrnutí

Dozvěděli jsme se hodně o Blazoru a vytvořili jsme čistou hru. Tady jsou některé dovednosti, které jsme se naučili:

  • Vytvoření komponenty
  • Přidání této komponenty na domovskou stránku
  • Použití injektáže závislostí ke správě stavu hry
  • Interaktivní hra s obslužnými rutinami událostí pro umístění kusů a resetování hry
  • Napsal(a) obslužnou rutinu chyby pro hlášení stavu hry.
  • Přidání parametrů do naší komponenty

Projekt, který jsme vytvořili, je jednoduchá hra a s ní můžete dělat mnohem víc. Hledáte nějaké výzvy ke zlepšení?

Výzvy

Vezměte v úvahu následující výzvy:

  • Pokud chcete aplikaci zmenšit, odeberte výchozí rozložení a další stránky.
  • Vylepšete parametry komponenty, abyste mohli předat libovolnou platnou Board hodnotu barvy CSS.
  • Vylepšete vzhled indikátorů pomocí některých rozložení CSS a HTML.
  • Představte si zvukové efekty.
  • Přidání vizuálního indikátoru a zabránění použití tlačítka pro přetažení, když je sloupec plný.
  • Přidejte síťové funkce, abyste mohli v prohlížeči přehrát přítele.
  • Vložte hru do .NET MAUI s aplikací Blazor a hrajte ji na telefonu nebo tabletu.

Šťastné kódování a bavte se!