国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 系統(tǒng) > Android > 正文

房卡麻將分析系列 "牌局回放" 之 數(shù)據(jù)設(shè)計(jì)詳解及實(shí)例

2019-12-12 03:27:04
字體:
供稿:網(wǎng)友

房卡麻將分析系列 "牌局回放" 之 數(shù)據(jù)設(shè)計(jì)                                                                   

             最近幾個(gè)月,”房卡“棋牌游戲成為了資本追逐的熱點(diǎn),基于微信的廣大用戶和社交屬性,”房卡”棋牌發(fā)展迅速。紅孩兒團(tuán)隊(duì)因?yàn)橹皫啄暧羞^相關(guān)項(xiàng)目的經(jīng)驗(yàn)積累,鑒于未來廣闊的地方棋牌市場和”開發(fā)間“機(jī)制的發(fā)展前景,也開始轉(zhuǎn)向基于”開房間“棋牌游戲的項(xiàng)目開發(fā)中。為了更好的與開發(fā)者進(jìn)行交流學(xué)習(xí),特開設(shè)”房卡麻將游戲分析系列“。

                                                                            紅孩兒團(tuán)隊(duì)研發(fā)的"大贏家"紅中麻將

           本套麻將分析基于網(wǎng)絡(luò)上流傳的“網(wǎng)狐”房卡麻將源碼做為基礎(chǔ),按照功能模塊分為"架設(shè)指南",”服務(wù)器框架","后臺系統(tǒng)","胡牌算法","客戶端界面",“防作弊功能”等等細(xì)節(jié)做一些分析和指導(dǎo),幫助廣大的棋牌游戲開發(fā)者迅速掌握“房卡”麻將的研發(fā)原理和技巧設(shè)計(jì)。也希望有興趣的朋友多多關(guān)注。

       第一次開公眾號,挑個(gè)簡單的下手,先來講一講房卡麻將中一個(gè)重要功能:“牌局回放”,我們都知道,棋牌類游戲注重公平真實(shí)不作弊,如果玩家感覺到游戲的過程有作弊,我相信他一定會對這款游戲失去興趣。但作弊與否,玩家并不容易進(jìn)行判斷。這時(shí)候提供一個(gè)“牌局回放”功能給玩家進(jìn)行分析就尤為重要。

       “網(wǎng)狐”等一些長期耕耘在棋牌領(lǐng)域的企業(yè),在這方面都有完整的經(jīng)驗(yàn)和框架,通過參考,我發(fā)現(xiàn)它是通過下面一套流程來完成”牌局回放“功能的。

        首先,在游戲服務(wù)器的房間類CTableFrameSink里需要有一個(gè)GameRecord結(jié)構(gòu),這個(gè)結(jié)構(gòu)對 玩家信息,手牌以及每一步的動作都可以進(jìn)行相應(yīng)的記錄:

struct GameRecordPlayer {   DWORD dwUserID;   std::string kHead;   std::string kNickName;   std::vector<BYTE> cbCardData;   void StreamValue(datastream& kData, bool bSend)   {     Stream_VALUE(dwUserID);     Stream_VALUE(kHead);     Stream_VALUE(kNickName);     Stream_VECTOR(cbCardData);   } };  struct GameRecordOperateResult {   enum Type   {     TYPE_NULL,     TYPE_OperateResult,     TYPE_SendCard,     TYPE_OutCard,     TYPE_ChiHu,   };    GameRecordOperateResult()   {     cbActionType = 0;     wOperateUser = 0;     wProvideUser = 0;     cbOperateCode = 0;     cbOperateCard = 0;   }    BYTE    cbActionType;   WORD    wOperateUser;            //操作用戶   WORD    wProvideUser;            //供應(yīng)用戶   BYTE    cbOperateCode;           //操作代碼   BYTE    cbOperateCard;           //操作撲克    void StreamValue(datastream& kData, bool bSend)   {     Stream_VALUE(cbActionType);     Stream_VALUE(wOperateUser);     Stream_VALUE(wProvideUser);     Stream_VALUE(cbOperateCode);     Stream_VALUE(cbOperateCard);   } };  struct GameRecord {   std::vector<GameRecordPlayer>   kPlayers;   std::vector<GameRecordOperateResult> kAction;      void StreamValue(datastream& kData, bool bSend)   {     StructVecotrMember(GameRecordPlayer, kPlayers);     StructVecotrMember(GameRecordOperateResult, kAction);   }    void CleanUp()   {     kPlayers.clear();     kAction.clear();   } }; 

          在datastream.h中,有一套set,get數(shù)據(jù)流的宏,能夠?qū)?shù)據(jù)放入到數(shù)據(jù)流中或從中拿出。

#define Stream_VALUE(Name) /   if(bSend)      / {              /   kData.pushValue(Name);/ }/ else/ {/   kData.popValue(Name);/ }/ 

          好了,有了這樣一個(gè)結(jié)構(gòu),在游戲開始的時(shí)候,我們就可以開始記錄本局了。

//游戲開始 void CTableFrameSink::GameStart() {     ...     //填充四個(gè)玩家的基礎(chǔ)信息   for (int i = 0; i < 4; i++)   {     GameRecordPlayer  tNewRecordPlayer;              tagUserInfo *  tpUserInfo = m_pITableFrame->GetTableUserItem(i)->GetUserInfo();     tNewRecordPlayer.dwUserID = tpUserInfo->dwUserID;     tNewRecordPlayer.kNickName = tpUserInfo->szNickName;              //取得手牌信息     BYTE cbCardData[MAX_COUNT];     m_GameLogic.SwitchAllToCardData(m_cbCardIndex[i], cbCardData);      for (int j = 0; j < MAX_COUNT ; j++)     {       tNewRecordPlayer.cbCardData.push_back(cbCardData[j]);     }         //存儲到當(dāng)前記錄結(jié)構(gòu)中的玩家信息容器。     m_sGameRecord.kPlayers.push_back(tNewRecordPlayer);   } } 

        然后我們開始記錄操作,分別在玩家出牌,以及玩家應(yīng)答吃,碰,杠,胡等操作時(shí)加入記錄。

//用戶出牌 bool CTableFrameSink::OnUserOutCard(WORD wChairID, BYTE cbCardData) {      ...   //記錄動作數(shù)據(jù)   GameRecordOperateResult  tNewRecordOperateResult;   tNewRecordOperateResult.cbActionType =    GameRecordOperateResult::TYPE_OutCard;   tNewRecordOperateResult.cbOperateCard = cbCardData;   tNewRecordOperateResult.cbOperateCode = WIK_NULL;   tNewRecordOperateResult.wOperateUser = wChairID;   tNewRecordOperateResult.wProvideUser = wChairID;   m_sGameRecord.kAction.push_back(tNewRecordOperateResult);      ... } 


//用戶操作 bool CTableFrameSink::OnUserOperateCard(WORD wChairID, BYTE cbOperateCode, BYTE cbOperateCard) {      ... //記錄動作數(shù)據(jù)     GameRecordOperateResult  tNewRecordOperateResult;       tNewRecordOperateResult.cbActionType = XZDDGameRecordOperateResult::TYPE_OperateResult;     tNewRecordOperateResult.cbOperateCard = cbOperateCard;     tNewRecordOperateResult.cbOperateCode = cbOperateCode;     tNewRecordOperateResult.wOperateUser = wChairID;     tNewRecordOperateResult.wProvideUser = m_wProvideUser;     m_sGameRecord.kAction.push_back(tNewRecordOperateResult);      ... } 

          就這樣,基本的操作記錄也完成了。最后當(dāng)牌局結(jié)束時(shí),我們需要將記錄提交到數(shù)據(jù)庫中。

//游戲結(jié)束 bool CTableFrameSink::OnEventGameConclude(WORD wChairID, IServerUserItem * pIServerUserItem, BYTE cbReason) {   switch (cbReason)   {   case GER_NORMAL:    //常規(guī)結(jié)束     {          ...             //將記錄轉(zhuǎn)化為數(shù)據(jù)流。       datastream kDataStream;       m_sGameRecord.StreamValue(kDataStream, true);              //除去寫分等處理,這里最后一個(gè)參數(shù)即是數(shù)據(jù)流。             m_pITableFrame->WriteTableScore(ScoreInfoArray, CountArray(ScoreInfoArray), kDataStream);           ...         }     } }  

           在私人場服務(wù)器中,會通過WriteTableScore這個(gè)函數(shù)調(diào)用PrivateTableInfo的writeSocre,它將將數(shù)的流記錄下來。

          并最終在牌局結(jié)束時(shí)DismissRoom(pTableInfo);發(fā)給了數(shù)據(jù)庫。

             數(shù)據(jù)庫最終會通過一個(gè)存儲過程的執(zhí)行完成將數(shù)據(jù)流入庫的工作。具體的代碼就不再展示了,大家可以參考

CDataBaseEngineSink::OnRequestPrivateGameRecord()。            

           這樣一套完整的回放數(shù)據(jù)流程就結(jié)束了。      

           好,今天的分析就到這里,紅孩兒歡迎大家下次繼續(xù)聽課哦~

感謝閱讀,希望能幫助到大家,謝謝大家對本站的支持!

發(fā)表評論 共有條評論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 兴安盟| 明星| 吉木乃县| 班玛县| 福鼎市| 阿克陶县| 华蓥市| 宁陕县| 大洼县| 通辽市| 古丈县| 西平县| 崇左市| 治县。| 奉新县| 三明市| 平谷区| 陕西省| 都昌县| 大洼县| 娄底市| 东乡族自治县| 高陵县| 漳州市| 彭山县| 边坝县| 澜沧| 江山市| 山东省| 石台县| 鄂州市| 新田县| 三亚市| 永新县| 鸡西市| 班戈县| 浦县| 陕西省| 浠水县| 舞阳县| 东乡县|