首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

C# 網路版鬥地主:地主權限傳遞邏輯實作 (第一部分) - 隨機選定與權限啟動流程

     編輯:關於C語言

地主權限傳遞總體設計與啟動流程

本系列第一部分,建立地主權限傳遞的核心邏輯框架:隨機選定預設地主、權限傳遞順序圖、Server 啟動權限分發、Client 接收處理迴圈。

權限傳遞順序圖

權限傳遞順序圖

三種隨機起始順序 (LandLordNum):

  • 1 (Server):Server → Client2 → Client1
  • 2 (Client1):Client1 → Server → Client2
  • 3 (Client2):Client2 → Client1 → Server

若傳遞至最後一人仍「不叫」 → Restart() 重新發牌。

Server 端啟動權限分發

public void SendOrder(int num) {
    switch (num) {
        case 1: DConsole.Player1.AreYouLandLord = true; break; // 自己
        case 2: SendDataForClient("AreYouLandLord", 1); break; // 給 Client1
        case 3: SendDataForClient("AreYouLandLord", 2); break; // 給 Client2
    }
}

此方法在發牌完成後呼叫,num 為 Random.Next(1,4) 結果。

Client 端接收迴圈 (AcceptServerData 核心節錄)

public void AcceptServerData() {
    var ns = _client.GetStream();
    while (true) {
        byte[] buffer = new byte[108];
        ns.Read(buffer, 0, buffer.Length);
        string msg = Encoding.Default.GetString(buffer);
        
        if (msg.StartsWith("AreYouLandLord")) {
            DConsole.Player1.AreYouLandLord = true; // Timer 偵測顯示按鈕
            continue;
        }
        if (msg.StartsWith("LandLordPokers")) {
            // 解析地主三張牌
            DConsole.LandLordPokers = ParsePokers(msg.Replace("LandLordPokers", ""));
            DConsole.Player1.SelectLandLordEnd(); // 顯示並加入手牌(若是地主)
            continue;
        }
        if (msg.StartsWith("ClientIsLandLord")) { /* 標記另一 Client 為地主 */ }
        if (msg.StartsWith("ServerIsLandLord")) { /* 標記 Server 為地主 */ }
    }
}

關鍵狀態變數

架構缺陷預警

  1. 靜態上帝類別 DConsole:集中管理 UI 控制項、遊戲狀態、網路物件,違反單一職責原則,極難測試。
  2. Timer 輪詢 UI 狀態:AreYouLandLord 由 Timer 檢測觸發按鈕顯示,效率低且有競態條件風險。
  3. 固定 108 bytes 緩衝區:地主牌序列化可能超長導致截斷。
  4. Encoding.Default:跨平台 (Linux/Mono) 會導致編碼不一致,應明確指定 UTF-8。

現代化重構起點

// 訊息定義 (DTO)
public abstract class GameMessage { public string Type { get; } }
public class AskLandLordMessage : GameMessage { public AskLandLordMessage() => Type = "AskLandLord"; }
public class LandLordPokersMessage : GameMessage { 
    public LandLordPokersMessage(PokerGroup pokers) { Type = "LandLordPokers"; Pokers = pokers; }
    public PokerGroup Pokers { get; }
}
// 統一發送/接收
await _stream.WriteAsync(Serialize(msg), token);
var msg = Deserialize(await ReadMessageAsync(stream, token));
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
變數所在類別用途
LandLordNumDConsole隨機決定起始權限者 (1/2/3)
AreYouLandLordPlayer當前輪到該玩家決定叫/不叫
IsLandLordPlayer確認該玩家為地主
HaveOrderPlayer出牌權限標記
IsBiggestPlayer上一輪出牌最大,下家皆過