爐石傳說 C# 開發筆記

 

最近在大連的同事強力推薦我玩 爐石傳說,一個卡牌遊戲。加上五一放一個很長很長的假期,爲了磨練本身,決定嘗試開發一個C#的爐石傳說。node

這件事情有人已經幹過了,開發了一個網頁版的爐石,可是貌似不能玩。。。。git

http://cnodejs.org/topic/529c1366a6957a0809485f3dgithub

若是這位同志看到這篇文章,請必定和我聯繫!!編程

rudermail@qq.com或Q我377372779瀏覽器

第一天服務器

開始學習爐石傳說的玩法,最好的方法是不停的玩遊戲。網絡

一個應用是否邏輯清晰,取決於你對於業務的瞭解程度,通常到開發後期發現有些邏輯內聚和耦合發生問題,每每都是前期對於業務的理解不夠透徹。工具

不少開發都每每是隨着業務邏輯的瞭解,進行不停的重構,固然,這個也是一個必然的過程,可是若是可以在前期就瞭解業務的話,則能夠節約後期大量的時間。學習

因爲長期作對日軟件的緣故,式樣書,設計書先行是根深蒂固的思想。全部設想都先以文字或者僞代碼的形式寫下來,進行一些假想的驗證。測試

整個項目的平衡感,脈絡,各個模塊,層次結構都在這個時候定下來。這個時候是修改爲本最低的階段,等到後期這些模塊再從新劃分,風險就高了。

 經過第一天的學(you)習(xi),大概整理除了一個脈絡:

(文字版本的不是很好看,下面的Excel版本,瀏覽器也看不到。。)

 

卡牌基礎

  法術卡牌

    熟讀各類法術牌,講法術牌分類

  隨從卡牌

    各類特性的整理,能夠參考各類網絡上的資料

  武器卡牌

    比較簡單的類型

遊戲環境

  英雄

    生命值

    基本技能

    武器

  牌堆

    套牌

  手牌

    手裏的牌  

  戰場

    7個位置的隨從

  法力水晶

    因爲某些卡牌會改變水晶,也爲了細化系統,法力水晶升級爲一個獨立的類

 次日

  開始進行Coding。因爲英語不是很好,有一些單詞不知道,而後開始中英文夾雜編碼。

  好久前,也討論過中文編程的問題,其實不少變量,用中文仍是英語徹底沒有限制。

  寫代碼只要能讓本身和維護的人讀得懂就能夠了。畢竟即便你用英語變量,你的註釋仍是中文的。。。

  固然,若是你想讓代碼可以國際化,特別是開源項目,能用標準的英語來寫代碼是極好的。

  NUnit用的不是很好,因此,本身寫了一些GUI的界面來作一些簡單的UT測試。

第三天

  代碼的重構,設計書和代碼的同步。

  不少項目,在一開始的時候還有設計書,而後在開發的時候,每每重構好代碼後,設計書仍是重構以前的樣子。

  IDE能夠自動重構代碼,可是不能自動重構設計書。。。。

  國內項目不注重文檔,因此這種狀況很常見。日系的開發,設計書則至關重要,一個是爲了往後維護能有個依據,二是爲了可以明確責任。

  這個地方爲何要修改,對於總體項目有什麼影響,都能從設計書的修改履歷中看出端倪。

  代碼和設計書同步的時候,也是一個反思的機會,看看現階段寫的代碼,是否是很乾淨優雅,

    每每將代碼轉換爲設計書的時候,能夠看到代碼的問題。特別是代碼的一致性上,散落在不一樣地方的代碼,通過整理,用#region概括後,能夠看到不少問題。

第四天

  爐石C#版本不是短期內能夠完成的,在完成整個爐石以前,能夠考慮用當前的代碼,先製做一些小的工具。

  一來能夠拉攏人氣,隔一段時間有個小的能夠檢證的成果物,不至於半途而廢;

  二來,小工具的製做也是爲了爐石服務的,有些小工具的代碼也能夠反饋到爐石主體代碼。

  我向來反對一開始就要作個了不得的東西,或者只開發了不得的東西,忘記了留下二次開發的接口或者周邊產品的接口。

  魔法的定義

    魔法類型
        攻擊
        回覆
        召喚
        卡牌    奧術智慧
        變形    變羊術
        水晶    幸運幣
        奧祕

    魔法關係
        或者    抉擇系:例如:抉擇: 對一個隨從形成3點傷害;或者形成1點傷害並抽一張牌。
        而且    有反作用的魔法,例如:形成4點傷害,隨機棄一張牌。

    目標選擇模式
        隨機
        全體
        指定

    目標選擇方向
        本方
        對方
        無限制

    目標選擇角色
        隨從
        英雄
        全體

    標準效果點數
        傷害效果點數、治療效果點數、抽牌數

    實際效果點數
        因爲某些卡牌效果會影響效果點數

    效果回數
        例如:奧術飛彈是3次1點傷害

    附加信息
        難以用上面的規則的卡牌,特殊的附加信息

奧術智慧的定義:
  1.有一個效果:抽兩張牌
  2.成本是1點
  3.對象時本方
        /// <summary>
        /// 初始化奧術智慧
        /// </summary>
        /// <returns></returns>
        public static Card.MagicCard Get奧術智慧()
        {
            Card.MagicCard 奧術智慧 = new Card.MagicCard();
            奧術智慧.SN = "M000002";
            奧術智慧.Name = "奧術智慧";
            奧術智慧.Description = "隨機抽兩張牌。";
            奧術智慧.Rare = Card.CardBasicInfo.稀有程度.綠色;
            //使用成本
            奧術智慧.ActualCostPoint = 1;
            奧術智慧.StandardCostPoint = 1;
            奧術智慧.JoinType = Card.MagicCard.EffectJoinType.None;

            //隨機抽兩張牌
            Card.MagicCardStockEffect cardStockEffect = new Card.MagicCardStockEffect();
            cardStockEffect.StandardEffectPoint = 2;
            cardStockEffect.EffectCount = 1;
            cardStockEffect.EffectTargetSelectDirect = Card.CardUtility.TargetSelectDirectEnum.本方;
            奧術智慧.FirstMagicDefine = cardStockEffect;
            return 奧術智慧;
        }

 

 

第五天

  我一直在考慮,AI是否是能代替人。

  爐石這樣的遊戲,有許多經常使用的套路,只要組好了套牌,而後可以將不少經常使用的卡牌組合,優先策略教授給AI,應該能夠作到和人對戰。

  和國際象棋,圍棋比起來,爐石這樣的遊戲,勝利無非是:運氣好,套牌組的合理,正確衡量場面上各類對方卡牌的威脅程度,熟練使用各類套路,有耐心,不犯低級錯誤。

  運氣好,套牌組的合理,這個事情,前者人和AI都同樣,套牌能夠人組好後直接給AI使用。

  正確衡量場面上各類對方卡牌的威脅程度:這個也不難,其實卡牌的使用成本已是一個能夠量化的威脅度指標了。

  熟練使用各類套路:對方出了一個 10/10 (合理的閥值)的傢伙,若是有變羊術,就變掉;對手一大堆血量3,4的隨從,就用清場的牌,這些套路也很直觀

  有耐心,不犯低級錯誤:這個是AI的長處,AI絕對不會忘記還有魔法能夠直接 打臉,還有可使用的隨從去 打臉

  固然,對於頂級高手AI還不是能夠簡單的取勝,審時度勢,及時調整戰略的能力,人仍是有着無可比擬的優點。

 第六天

  看看客戶端和服務器端分工如何:

  順便提一句,平常文檔的編寫,WPS不比Office差,支持國貨

 

  核心庫 Card.DLL 還有客戶端,服務器,之間要鏈接起來

客戶端-服務器-核心庫


    核心庫:委託形式

            /// <summary>
            /// 抽牌委託
            /// </summary>
            /// <param name="IsFirst">前後手區分</param>
            /// <param name="magic">法術定義</param>
            public delegate List<CardBasicInfo> delegateDrawCard(Boolean IsFirst, int DrawCount);
            /// <summary>
            /// 抽牌魔法(服務器方法)
            /// </summary>
            public static delegateDrawCard DrawCard;


    客戶端:實現委託

            /// <summary>
            /// 初始化
            /// </summary>
            public static void Init() {
                //抽牌的具體方法
                CardUtility.DrawCard += DrawCardAtServer;
            }

            /// <summary>
            /// 抽牌(服務器方法)
            /// </summary>
            /// <returns></returns>
            public static List<String> DrawCardAtServer(Boolean IsFirst, int Count)
            {
                //向服務器提出請求,得到牌
                return GameStatus.DrawCard(IsFirst,Count);
            }

    服務器端:實際操做牌堆

            /// <summary>
            /// 抽牌
            /// </summary>
            /// <param name="IsFirst"></param>
            /// <param name="Count"></param>
            /// <returns></returns>
            public static List<String> DrawCard(Boolean IsFirst, int Count)
            {
                var targetStock = IsFirst ? FirstCardStock : SecondCardStock;
                return targetStock.DrawCard(Count);
            }

    (調用Card核心庫方法)

            /// <summary>
            /// 抽卡
            /// </summary>
            /// <param name="CardCount"></param>
            /// <returns></returns>
            public List<String> DrawCard(int CardCount)
            {
                List<String> newList = new List<String>();
                for (int i = 0; i < CardCount; i++)
                {
                    if (CardList.Count == 0) break;
                    newList.Add(CardList.Pop());
                }
                return newList;
            }

 

 第七天

 

考慮服務器和客戶端的開發。

客戶端-服務器通訊

    TCP協議,相似於網站那樣的短鏈接。

        玩家A                    服務器消息區            玩家B
            回合開始                STARTTURN
            使用卡牌A,形成結果B                USE:A|EFFECT:B            每隔5秒從服務器端讀一次A的行爲,改變當前戰場狀態,知道讀取到ENDTRUN消息
            使用卡牌C,形成結果D                USE:C|EFFECT:D
            回合結束                ENDTURN

                            STARTTURN            回合開始
            每隔5秒從服務器端讀一次B的行爲,改變當前戰場狀態,知道讀取到ENDTRUN消息                USE:A|EFFECT:B            使用卡牌A,形成結果B
                            USE:C|EFFECT:D            使用卡牌C,形成結果D
                            ENDTURN            回合結束


    請求分類    (3位)

        遊戲
            新建一個遊戲        新建一個遊戲
            加入一個遊戲        加入一個遊戲
            認輸        認輸,退出一個遊戲
            等待遊戲列表        獲取等待加入者遊戲的列表
            確認遊戲啓動狀態        確認遊戲是否處於啓動狀態
            是否爲先手        是否爲先手

        動做
            抽牌        抽牌
            回合結束        回合結束
            行動        改變戰場的動做

 

 

下面這個連接是OneDriver上共享的設計書,有些圖形對象沒法在瀏覽器中顯示,不知道能不能經過下載的方式保存到本地,而後打開。

點擊這裏查看 onlne Excel 版本的 設計書

代碼在GitHub上面,不過爲了幫MongoDB的項目拉人氣,因此,將代碼放到了MongoDB的解決方案裏面了。

你們下載代碼的時候,順手點個贊吧 Star 一下

https://github.com/magicdict/MagicMongoDBTool

相關文章
相關標籤/搜索