[原創]一步一步用C#編寫三國殺(三):設計流程

來源:互聯網
上載者:User

原創文章,轉載請保留作者署名!

 

前面已經說了牌堆的設計,那麼現在就正式進入流程,滿足我們在(一)中所說的需求。

 

由於在(二)中已經說了要維護擴充,因此對於之前定義的Scene,則需要定義一個所選擇的擴充包,代碼如下:

 

擴充包

        private readonly IPackage[] selectedPackages;

        /// <summary>
        /// 初始化新的<see cref="Scene"/>類的執行個體。
        /// </summary>
        /// <param name="packages">所要載入的包。</param>
        public Scene(IEnumerable<IPackage> packages)
        {
            players[currentToken].HasToken = true;
            selectedPackages = packages.ToArray();
        }

 

 

由於玩家是輪動的,因此設定一個令牌,只有持有令牌的玩家才能行動。

 

private int currentToken;

 

 

那麼定義一個Start方法,開始遊戲迴圈。

 

首先要根據選擇的擴充包產生遊戲牌堆。對於遊戲牌堆,由於我們之前已經定義好了牌堆基類,因此實現就比較簡單了,將擴充包中的遊戲牌載入並洗牌即可。

 

遊戲牌堆

    /// <summary>
    /// 表示遊戲牌牌堆。
    /// </summary>
    public sealed class GameCardHeap : CardHeap<GameCard>
    {
        /// <summary>
        /// 初始化新的<see cref="GameCardHeap"/>類的執行個體。
        /// </summary>
        /// <param name="packages">所要載入的擴充包。</param>
        public GameCardHeap(IEnumerable<IPackage> packages)
        {
            foreach (var package in packages)
            {
                ((List<GameCard>) Items).AddRange(package.GameCards);
            }
            Items.Shuffle();
        }
    }

 

 回頭看我們上面的Start方法,在牌堆建立後,就進入了流程迴圈,還是直接來代碼吧,注釋都寫的蠻清楚的

 

流程迴圈

        /// <summary>
        /// 開始遊戲。
        /// </summary>
        public void Start()
        {
            Player currentPlayer;
            GameCardHeap heap = new GameCardHeap(selectedPackages);  // 建立牌堆

            while(true)
            {
                currentPlayer = players[currentToken];  // 設定當前有令牌的玩家

                // 摸牌階段
                GameCard[] newCards = heap.Pop(2, true);
                currentPlayer.Draw(newCards);

                // 出牌階段
                while(currentPlayer.HasPlayableCard)
                {
                    // NOTE:為了簡單,先實現只殺下家,並只使用殺、閃、桃
                    int nextToken = currentToken == players.Length - 1 ? 0 : currentToken + 1;
                    currentPlayer.Play(players[nextToken], currentPlayer.FirstPlayableCard);

                    if (IsGameEnds())
                        goto label;
                }

                // 棄牌階段
                // NOTE:為了簡單,先實現只棄從頭開始的牌到當前體力值
                int disCardCount = currentPlayer.HandCards.Length - currentPlayer.Hp;
                if (disCardCount > 0)
                {
                    GameCard[] removeCards = currentPlayer.HandCards.Take(disCardCount).ToArray();
                    currentPlayer.Discard(removeCards);
                }

                // 將令牌給下一個人
                GiveTokenToNext();
            }
            label:
            Console.WriteLine("遊戲結束!");
        }

 

 

這裡使用了一個死迴圈,但在遊戲結束的時候使用goto語句跳出迴圈。所涉及到的一些方法如下:

 

一些輔助方法

        private void GiveTokenToNext()
        {
            if (currentToken == players.Length - 1)
                currentToken = 0;
            else
                currentToken++;

            players[currentToken].HasToken = true;
        }

        private bool IsGameEnds()
        {
            return players.Any(p => p.IsDead);  // 如果選擇到IsDead的Player,遊戲結束
        }

 

 

注意,流程的設計中,由於玩家是在遊戲邏輯邊界內的,因此採用了主動的做法來進行設計。這樣對於程式來說,我只要去考慮玩家的摸牌、出牌和棄牌所引起的各種變化即可。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.