🔧 阿川の電商水電行
Shopify 顧問、維護與客製化
💡
小任務 / 單次支援方案
單次處理 Shopify 修正/微調
⭐️
維護方案
每月 Shopify 技術支援 + 小修改 + 諮詢
🚀
專案建置
Shopify 功能導入、培訓 + 分階段交付

前言

本文將帶您體驗在 「短短1小時」 內製作 Web 遊戲的過程。

🎯 推薦給以下人士

  • 平常寫 C#,但 Web 前端有點不擅長…
  • 雖然有過製作 Web 應用程式的經驗,但 從未接觸過 Blazor
  • 希望 盡量減少使用 JavaScript 和 AJAX

您只需具備基本的 HTML 和 CSS 知識,無需深入了解。
只要會寫 C# 就可以! 👍

🔷 另外,Blazor 是微軟開發的最新 Web 框架。
只需使用「伺服器端 C#」即可構建豐富的 Web 使用者界面。

接下來要製作的遊戲形象

image.png

實際遊玩是最容易理解的方式。
請務必親自操作看看!

👉 點擊這裡來玩示範應用

1. 在 Visual Studio 中創建新專案

image.png

選擇 Blazor Web 應用
image.png

輸入專案名稱(在此我們用 HakoiriMusume)
image.png

確認附加資訊(藍框內請保持一致)
image.png

重要設定 設定值 備註
認證類型 本次無需登入
互動型別 伺服器 ★ 極為重要
互動位置 全域

專案已生成
image.png

開始調試並確認功能
image.png

確認顯示預設頁面
image.png

2. 瞭解專案架構

image.png

標準專案架構

目錄 內容
wwwroot css 等
Components/Pages 各 Web 頁面

雖然有許多資料夾和檔案,但我們將專注於
「Components/Pages/Home.razor」。

Home.razor

這是初次執行時顯示頁面的程式碼

@page "/"
<PageTitle>Home</PageTitle>
<h1>Hello, world!</h1>
Welcome to your new app.

3. HTML 中可以寫 C# 的 Blazor

現在讓我們修改 Home.razor

@page "/"
@for (int i = 1; i < 4; i++)
{
    <p>第 @i 次迴圈</p>
}

在 HTML 中出現了

@for (int i = 1; i < 4; i++)

突如其來的 C# 程式碼。
※ 您可以在 HTML 中用「@」隨意編寫 C#。
(跟 Go 語言、JSP、PHP 等類似)

🔷 注意到 html 的 <p> 標籤中的 @i 也使用了 C# 的變數。

<p>第 @i 次迴圈</p>

執行看看
image.png

4. 製作遊戲的棋盤

首先製作棋子的背景棋盤

我們在 <style> 中定義了遊戲棋盤的外觀。
(一般來說應該將其分離到 CSS 檔案中,但這裡優先考量可讀性。)
HTML 負責「顯示內容」,而 <style> 負責「裝飾」。

對於 CSS(<style>)的詳細知識不必太過於擔心!
只需理解它是用來美化外觀的就可以了。

@page "/"

<style>
    .board {
        display: grid;
        grid-template-rows: repeat(7, 50px);
        grid-template-columns: repeat(8, 50px);
        position: relative;
    }
</style>

<div class="board">
    @for (int row = 0; row < 7; row++)
    {
        for (int col = 0; col < 8; col++)
        {
            // CSS 的網格是以 1 為基準
            var cssRow = row + 1;
            var cssCol = col + 1;

            <div class="cell" style="grid-area:@(cssRow) / @(cssCol);">
                □
            </div>
        }
    }
</div>

目前已製作出 7 行 × 8 列的簡易棋盤
image.png

由於過於簡單,因此將每個單元格的樣式設定為矩形繪製。

.cell {
    border: 1px solid #444;
    display: flex;
    justify-content: center;
    align-items: center;
}

現在已能看到邊框
image.png

接下來改為用變數來宣告 7 × 8。

<div class="board">
    @for (int row = 0; row < MaxRows; row++)
    {
        for (int col = 0; col < MaxCols; col++)
        {
            // CSS 的網格是以 1 為基準
            var cssRow = row + 1;
            var cssCol = col + 1;

            <div class="cell" style="grid-area:@(cssRow) / @(cssCol);">
                □
            </div>
        }
    }
</div>

@code {
    private const int MaxRows = 7;
    private const int MaxCols = 8;
}
  • 您可以用 @code 來集中編寫 C# 程式碼
  • @code 中宣告的變數 MaxRows 被用在 HTML 的 for 迴圈中

5. 製作棋盤(續篇)

從簡單的 7 × 8 開始,現在我們要能定義牆壁和出口。

@code {
    private const int MaxRows = 7;
    private const int MaxCols = 8;

    private int[,] Board = new int[MaxRows, MaxCols]
    {
        {1, 1, 1, 1, 1, 1, 1, 1},
        {1, 0, 0, 0, 0, 0, 0, 1},
        {1, 0, 0, 0, 0, 0, 0, 1},
        {1, 0, 0, 0, 0, 0, 0, 1},
        {1, 0, 0, 0, 0, 0, 0, 1},
        {1, 0, 0, 0, 0, 0, 0, 1},
        {1, 1, 1, 9, 9, 1, 1, 1},
    };
}

將 HTML 顯示與定義對應上

<div class="board">
    @for (int row = 0; row < MaxRows; row++)
    {
        for (int col = 0; col < MaxCols; col++)
        {
            // CSS 的網格是以 1 為基準
            var cssRow = row + 1;
            var cssCol = col + 1;

            int cell = Board[row, col];
            switch (cell)
            {
                case 0: // 空
                    <div class="cell empty" style="grid-area:@(cssRow) / @(cssCol);">
                        □
                    </div>
                    break;
                case 1: // 牆壁
                    <div class="cell wall" style="grid-area:@(cssRow) / @(cssCol);">
                        ■
                    </div>
                    break;
                case 9: // 出口
                    <div class="cell exit" style="grid-area:@(cssRow) / @(cssCol);">
                        玄關
                    </div>
                    break;
            }
        }
    }
</div>

執行確認看看
image.png

(棋盤看起來還算不錯)

強化樣式設定使外觀更佳,填充單元格的背景以表現棋盤。

.cell.wall {
    background: #444;
}

.cell.empty {
    background: #aaa;
}

.cell.exit {
    background: #eee;
    color: #333;
    display: flex;
    align-items: center;
    justify-content: center;
}

image.png

這樣棋盤就完成了!
接下來我們將開始擺放棋子。

6. 擺放棋子 - 將 C# 類別渲染到 HTML

棋盤在 HTML 中是固定定義的。
每次顯示頁面時都會畫出來。

棋子則不應固定,需另行繪製。

透過事件擺放棋子

先在頁面顯示時的事件 OnInitialized 中擺放棋子。

@code {
    private class Piece
    {
        public int Row { get; set; }
        public int Col { get; set; }
        public string? Label { get; set; }
    }

    private List<Piece> Pieces = new List<Piece>();

    protected override void OnInitialized()
    {
        // 初始配置
        Pieces.Add(new Piece { Row = 2, Col = 3, Label = "娘" });
    }
}

已使用 C# 定義棋子的類別,接下來在 HTML 中渲染。

@foreach (Piece p in Pieces)
{
    var cssPieceRow = p.Row + 1;
    var cssPieceCol = p.Col + 1;

    <div class="piece" style="grid-row:@cssPieceRow; grid-column:@cssPieceCol;">
        @p.Label
    </div>
}

使用樣式來裝飾棋子的外觀

.piece {
    background: red;
    color: white;
    font-weight: bold;
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 1;
}

執行查看結果
image.png

在第 2 列第 3 行(0 為起始)放置棋子「娘」。

由於source開始變得有些複雜,因此我們稍作整理,看看整體架構。
目前的整體程式碼看起來像這樣。

<details><summary><b>============================<br>   顯示總程式碼(可折疊)<br> =============================</b></summary><div>

@page "/"

<style>
    /* 整個遊戲棋盤 */
    .board {
        display: grid;
        grid-template-rows: repeat(7, 50px);
        grid-template-columns: repeat(8, 50px);
        position: relative;
    }

    /* 單元格的樣式 */
    .cell {
        border: 1px solid #444;
        display: flex;
        justify-content: center;
        align-items: center;
    }

    /* 牆壁 */
    .wall {
        background: #444;
    }

    /* 棋盤 */
    .empty {
        background: #aaa;
    }

    /* 玄關 */
    .exit {
        background: #eee;
        color: #333;
        display: flex;
        align-items: center;
        justify-content: center;
    }

    /* 棋子 */
    .piece {
        background: red;
        color: white;
        font-weight: bold;
        display: flex;
        align-items: center;
        justify-content: center;
        z-index: 1;
    }
</style>

<div class="board">
    @for (int row = 0; row < MaxRows; row++)
    {
        for (int col = 0; col < MaxCols; col++)
        {
            // CSS 的網格是以 1 為基準
            var cssRow = row + 1;
            var cssCol = col + 1;

            int cell = Board[row, col];
            switch (cell)
            {
                case 0: // 空
                    <div class="cell empty" style="grid-area:@(cssRow) / @(cssCol);">
                        □
                    </div>
                    break;
                case 1: // 牆壁
                    <div class="cell wall" style="grid-area:@(cssRow) / @(cssCol);">
                        ■
                    </div>
                    break;
                case 9: // 玄關
                    <div class="cell exit" style="grid-area:@(cssRow) / @(cssCol);">
                        玄關
                    </div>
                    break;
            }
        }
    }

    @foreach (Piece p in Pieces)
    {
        var cssPieceRow = p.Row + 1;
        var cssPieceCol = p.Col + 1;

        <div class="piece" style="grid-row:@cssPieceRow; grid-column:@cssPieceCol;">
            @p.Label
        </div>
    }
</div>

@code {
    private const int MaxRows = 7;
    private const int MaxCols = 8;

    private int[,] Board = new int[MaxRows, MaxCols]
    {
        {1, 1, 1, 1, 1, 1, 1, 1},
        {1, 0, 0, 0, 0, 0, 0, 1},
        {1, 0, 0, 0, 0, 0, 0, 1},
        {1, 0, 0, 0, 0, 0, 0, 1},
        {1, 0, 0, 0, 0, 0, 0, 1},
        {1, 0, 0, 0, 0, 0, 0, 1},
        {1, 1, 1, 9, 9, 1, 1, 1},
    };

    private class Piece
    {
        public int Row { get; set; }
        public int Col { get; set; }
        public string? Label { get; set; }
    }

    private List<Piece> Pieces = new List<Piece>();

    protected override void OnInitialized()
    {
        // 初始配置
        Pieces.Add(new Piece { Row = 2, Col = 3, Label = "娘" });
    }
}

</div></details>

修改後的畫面

image.png

棋子已成功實作。
錄製 2025-10-02 074705.gif

顯示消息的效果也很好。

完成的清理消息,請自己去確認😄

為了謹慎起見,將到目前為止的解決方案整體上傳到了 GitHub。

12. 希望擴展的人

您認為怎麼樣?
可以輕鬆地製作 Web 遊戲。

也有些人希望進一步發展遊戲。

🔼 想要不僅用滑鼠還能用手機進行觸控操作
🔼 希望更加強化外觀

由於這篇文章的主旨是「介紹面向初學者的 Blazor」,因此不再深入探討。請參考公開的示範版源代碼。

13. 最後

Blazor Server 是一個利用 WebSockets(網路套接字)的框架,這是它在遊戲製作中顯著的強項?

我相信只要運用本文所用的技術,就能輕鬆製作出相當豐富的使用者介面。
不僅僅是瀏覽器上的簡單按鈕點擊,還能根據需要捕捉滑鼠拖動等任意事件。

Blazor 在業務應用開發中也表現優秀!

這篇文章介紹了使用 Blazor 開發業務應用程式的案例。
如果您有興趣,請務必查看。

👉 關於 Blazor 業務應用的實例文章

【 参考图片 】
image.png
image.png


原文出處:https://qiita.com/masayahak/items/0e6c82497ad63c856e3f


精選技術文章翻譯,幫助開發者持續吸收新知。

共有 0 則留言


精選技術文章翻譯,幫助開發者持續吸收新知。
🏆 本月排行榜
🥇
站長阿川
📝19   💬9   ❤️5
726
🥈
我愛JS
📝4   💬14   ❤️7
249
🥉
御魂
💬1  
3
#5
2
評分標準:發文×10 + 留言×3 + 獲讚×5 + 點讚×1 + 瀏覽數÷10
本數據每小時更新一次
🔧 阿川の電商水電行
Shopify 顧問、維護與客製化
💡
小任務 / 單次支援方案
單次處理 Shopify 修正/微調
⭐️
維護方案
每月 Shopify 技術支援 + 小修改 + 諮詢
🚀
專案建置
Shopify 功能導入、培訓 + 分階段交付