#include "StdAfx.h" #include "ImmediateGroup.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif ////////////////////////////////////////////////////////////////////////// //常量定义 #define INVALID_VALUE 0xFFFF //无效值 //静态变量 WORD CImmediateGroup::m_wChairCount; //椅子数目 ////////////////////////////////////////////////////////////////////////// //构造函数 CImmediateGroup::CImmediateGroup(DWORD dwMatchNO, tagGameMatchOption * pGameMatchOption, IImmediateGroupSink *pIImmediateGroupSink) { //指针变量 m_pMatchOption = pGameMatchOption; m_pMatchSink = pIImmediateGroupSink; //状态变量 m_dwMatchNO = dwMatchNO; m_enMatchStatus = MatchStatus_Signup; m_dwCurBase = m_pMatchOption->MatchType.Immediate.dwInitalBase; //设置变量 ZeroMemory(&m_MatchStartTime, sizeof(m_MatchStartTime)); //移除元素 m_OnMatchUserMap.RemoveAll(); m_FreeUserArray.RemoveAll(); m_MatchTableArray.RemoveAll(); //设置变量 m_LoopTimer = 0; m_wAndroidUserCount = 0; } //析构函数 CImmediateGroup::~CImmediateGroup() { //杀死定时器 AllKillMatchTimer(); //设置状态 m_wAndroidUserCount = 0; m_enMatchStatus = MatchStatus_Null; //释放桌子 for (int i = 0; i < m_MatchTableArray.GetCount(); i++) { SafeDelete(m_MatchTableArray[i]); } //移除元素 m_MatchTableArray.RemoveAll(); m_OnMatchUserMap.RemoveAll(); m_FreeUserArray.RemoveAll(); } //接口查询 VOID* CImmediateGroup::QueryInterface(REFGUID Guid, DWORD dwQueryVer) { QUERYINTERFACE(IMatchEventSink, Guid, dwQueryVer); QUERYINTERFACE_IUNKNOWNEX(IMatchEventSink, Guid, dwQueryVer); return NULL; } //用户报名 bool CImmediateGroup::OnUserSignUpMatch(IServerUserItem * pUserItem) { //用户判断 ASSERT(pUserItem != NULL); if (pUserItem == NULL) return false; //查找用户 IServerUserItem * pIServerUserExist = NULL; m_OnMatchUserMap.Lookup(pUserItem->GetUserID(), pIServerUserExist); //用户判断 ASSERT(pIServerUserExist == NULL); if (pIServerUserExist != NULL) return false; //人数效验 ASSERT(m_OnMatchUserMap.GetCount() < m_pMatchOption->MatchType.Immediate.wStartUserCount); if (m_OnMatchUserMap.GetCount() >= m_pMatchOption->MatchType.Immediate.wStartUserCount) return false; //机器判断 if (pUserItem->IsAndroidUser() == true) { if (m_wAndroidUserCount >= m_pMatchOption->MatchType.Immediate.wAndroidUserCount) { return false; } m_wAndroidUserCount++; } //设置成绩 tagUserInfo *pUserScore = pUserItem->GetUserInfo(); pUserScore->dwWinCount = 0L; pUserScore->dwLostCount = 0L; pUserScore->dwFleeCount = 0L; pUserScore->dwDrawCount = 0L; pUserScore->lGrade = 0L; pUserScore->lScore = (SCORE)m_pMatchOption->MatchType.Immediate.dwInitalScore; //发送成绩 m_pMatchSink->SendGroupUserScore(pUserItem, NULL); //设置用户 m_OnMatchUserMap[pUserItem->GetUserID()] = pUserItem; //设置报名状态 pUserItem->SetSignUpStatus(MS_SIGNUP); //设置报名时间 pUserItem->SetSignUpTime(GetTickCount()); //发送报名状态 BYTE cbMatchStatus = MS_SIGNUP; m_pMatchSink->SendData(pUserItem, MDM_GR_MATCH, SUB_GR_MATCH_STATUS, &cbMatchStatus, sizeof(cbMatchStatus)); //报名人满 if (m_OnMatchUserMap.GetCount() >= m_pMatchOption->MatchType.Immediate.wStartUserCount) { //事件通知 ASSERT(m_pMatchSink != NULL); if (m_pMatchSink != NULL) m_pMatchSink->SendMatchInfo(NULL); EfficacyStartMatch(); } return true; } //比赛开始 void CImmediateGroup::EfficacyStartMatch() { m_pMatchSink->InsertNullTable(); //没有桌子的情况 if (m_MatchTableArray.GetCount() < m_pMatchOption->MatchType.Immediate.wStartUserCount / m_wChairCount) { if (m_OnMatchUserMap.GetCount() < m_wChairCount) { //构造数据包 CMD_CM_SystemMessage Message; Message.wType = SMT_EJECT | SMT_CHAT | SMT_CLOSE_GAME; lstrcpyn(Message.szString, TEXT("抱歉,由于某用户强行退出比赛,该场比赛提前结束。你可以继续等待比赛!"), CountArray(Message.szString)); Message.wLength = CountStringBuffer(Message.szString); //发送数据 WORD wSendSize = sizeof(Message)-sizeof(Message.szString) + Message.wLength*sizeof(TCHAR); m_pMatchSink->SendGroupData(MDM_CM_SYSTEM, SUB_CM_SYSTEM_MESSAGE, &Message, wSendSize, this); m_enMatchStatus = MatchStatus_Signup; return; } m_enMatchStatus = MatchStatus_Wait; //3秒后继续调用该函数直到有桌子 SetMatchGameTimer(IDI_WAITTABLE_FIRST_ROUND, 3000, 1, NULL); //构造数据包 CMD_CM_SystemMessage Message; Message.wType = SMT_CHAT; _sntprintf(Message.szString, CountArray(Message.szString), TEXT("抱歉,由于过多用户桌子数量不够!还差 %d 张桌子开赛,请等待。。。"), m_pMatchOption->MatchType.Immediate.wStartUserCount / m_wChairCount - m_MatchTableArray.GetCount()); Message.wLength = CountStringBuffer(Message.szString); //发送数据 WORD wSendSize = sizeof(Message)-sizeof(Message.szString) + Message.wLength*sizeof(TCHAR); m_pMatchSink->SendGroupData(MDM_CM_SYSTEM, SUB_CM_SYSTEM_MESSAGE, &Message, wSendSize, this); return; } //预赛安排座位 DWORD dwUserID = 0L; IServerUserItem *pIServerUserItem = NULL; POSITION pos = m_OnMatchUserMap.GetStartPosition(); WORD wChairID = 0; while (pos != NULL) { //获取用户 m_OnMatchUserMap.GetNextAssoc(pos, dwUserID, pIServerUserItem); ASSERT(pIServerUserItem != NULL); InsertFreeGroup(pIServerUserItem); //设置用户比赛中 pIServerUserItem->SetSignUpStatus(MS_MATCHING); pIServerUserItem->SetMatchData(this); } //桌子自动拉人 TabelRequestUser(false); //设置状态 m_enMatchStatus = MatchStatus_FirstRound; //记录时间 CTime::GetCurrentTime().GetAsSystemTime(m_MatchStartTime); //开始通知 if (m_pMatchSink != NULL) m_pMatchSink->OnEventMatchStart(this); //设置定时器 SetMatchGameTimer(IDI_CHECK_MATCH_GROUP, 1000, TIMES_INFINITY, 0); } //用户退赛 BOOL CImmediateGroup::OnUserQuitMatch(IServerUserItem *pUserItem) { //用户判断 ASSERT(pUserItem != NULL); if (pUserItem == NULL) return false; //删除用户 BOOL bSuccess = m_OnMatchUserMap.RemoveKey(pUserItem->GetUserID()); if (bSuccess == false)return false; if (pUserItem->IsAndroidUser()) { ASSERT(m_wAndroidUserCount > 0); if (m_wAndroidUserCount > 0) m_wAndroidUserCount--; } //设置状态 pUserItem->SetSignUpStatus(MatchStatus_Null); BYTE cbUserStatus = MatchStatus_Null; m_pMatchSink->SendData(pUserItem, MDM_GR_MATCH, SUB_GR_MATCH_STATUS, &cbUserStatus, sizeof(cbUserStatus)); return bSuccess; } //定时器 bool CImmediateGroup::OnTimeMessage(DWORD dwTimerID, WPARAM dwBindParameter) { //状态校验 if (m_enMatchStatus == MatchStatus_Null) return true; switch (dwTimerID) { case IDI_CHECK_MATCH_GROUP: { CaptureMatchTimer(); return true; } case IDI_WAITTABLE_FIRST_ROUND: { if (m_enMatchStatus == MatchStatus_Wait) { EfficacyStartMatch(); } return true; } case IDI_SWITCH_WAIT_TIME: { //将空闲用户自动配桌 RearrangeUserSeat(); TabelRequestUser(); //ContinueGame((ITableFrame*)dwBindParameter); return true; } case IDI_TABLE_REQUEST_USER: { TabelRequestUser(); return true; } case IDI_ENTER_NEXT_ROUND: { //if(m_enMatchStatus==MS_START_NEXT_ROUND) //{ // //继续下一轮 // ContinueRound(); //} return true; } case IDI_ALL_DISMISS_GAME: { RearrangeUserSeat(); return true; } case IDI_LASTMATCHRESULT: { //最后结束 MatchOver(); return true; } } return true; } WORD CImmediateGroup::SortMapUser(tagMatchScore score[]) { INT_PTR nCount = m_OnMatchUserMap.GetCount(); POSITION pos = m_OnMatchUserMap.GetStartPosition(); nCount = 0; while (pos != NULL) { m_OnMatchUserMap.GetNextAssoc(pos, score[nCount].dwUserID, score[nCount].pUserItem); score[nCount].dwUserID = score[nCount].pUserItem->GetUserID(); score[nCount].lScore = score[nCount].pUserItem->GetUserScore(); nCount++; } for (INT_PTR i = 1; i < nCount; i++) { INT_PTR left = 0, right = i - 1; tagMatchScore Temp = score[i]; while (left <= right) { INT_PTR mid = (left + right) / 2; if (score[i].lScore > score[mid].lScore)right = mid - 1; else left = mid + 1; } for (INT_PTR j = i - 1; j >= left; j--) score[j + 1] = score[j]; score[left] = Temp; } return (WORD)nCount; } //重置桌位 void CImmediateGroup::RearrangeUserSeat(bool bDismissGame) { KillMatchGameTimer(IDI_SWITCH_WAIT_TIME); for (WORD i = 0; i < m_MatchTableArray.GetCount(); i++) { tagTableFrameInfo *ptagTableFrameInfo = m_MatchTableArray[i]; ASSERT(ptagTableFrameInfo != NULL); if (ptagTableFrameInfo == NULL) continue; ITableFrame* pTableFrame = ptagTableFrameInfo->pTableFrame; ASSERT(pTableFrame != NULL); if (pTableFrame == NULL) continue; if (bDismissGame == false) { ptagTableFrameInfo->cbPlayCount = 0; ptagTableFrameInfo->bRoundTableFinish = false; ptagTableFrameInfo->bSwtichTableFinish = false; ptagTableFrameInfo->bWaitForNextInnings = false; } //强制解散游戏 if (pTableFrame->IsGameStarted() == true) { if (bDismissGame == true) { bool bSuccess = pTableFrame->DismissGame(); if (bSuccess == false) CTraceService::TraceString(TEXT("解散游戏"), TraceLevel_Exception); } else { TCHAR szMessage[64] = TEXT(""); _sntprintf(szMessage, CountArray(szMessage), TEXT("重置桌位时,第 %d 桌处于游戏状态"), pTableFrame->GetTableID()); CTraceService::TraceString(szMessage, TraceLevel_Exception); } } //该桌用户全部离开 AllUserExitTable(pTableFrame); } return; } //游戏开始 bool CImmediateGroup::OnEventGameStart(ITableFrame *pITableFrame, WORD wChairCount) { pITableFrame->SetCellScore(m_dwCurBase); KillMatchTimer(IDI_CHECK_TABLE_START, (WPARAM)pITableFrame); tagTableFrameInfo *pTableFrameInfo = GetTableInterface(pITableFrame); pTableFrameInfo->bRoundTableFinish = false; pTableFrameInfo->bSwtichTableFinish = false; pTableFrameInfo->bWaitForNextInnings = false; //已完成局数加1 pTableFrameInfo->cbPlayCount++; //发送比赛信息给桌子上的用户 SendTableUserMatchInfo(pITableFrame, INVALID_CHAIR); //构造数据包 CMD_CM_SystemMessage SystemMessage; ZeroMemory(&SystemMessage, sizeof(SystemMessage)); TCHAR szMsg[256] = TEXT(""); _sntprintf(szMsg, CountArray(szMsg), TEXT("定局排名赛第%d局开始(共%d局)。"), pTableFrameInfo->cbPlayCount, m_pMatchOption->MatchType.Immediate.cbPlayCount); lstrcpyn(SystemMessage.szString, szMsg, CountArray(SystemMessage.szString)); SystemMessage.wLength = CountStringBuffer(SystemMessage.szString); SystemMessage.wType = SMT_CHAT; //发送数据 WORD wSendSize = sizeof(SystemMessage)-sizeof(SystemMessage.szString) + SystemMessage.wLength*sizeof(TCHAR); pITableFrame->SendTableData(INVALID_CHAIR, SUB_GF_SYSTEM_MESSAGE, (void*)&SystemMessage, wSendSize, MDM_GF_FRAME); return true; } //游戏结束 bool CImmediateGroup::OnEventGameEnd(ITableFrame *pITableFrame, WORD wChairID, IServerUserItem * pIServerUserItem, BYTE cbReason) { //记录本局和哪些用户玩过 tagTableFrameInfo * ptagTableFrameInfo = GetTableInterface(pITableFrame); ASSERT(ptagTableFrameInfo); if (ptagTableFrameInfo == NULL)return false; if (m_enMatchStatus == MatchStatus_FirstRound) { FirstRoundRuleInningsGameEnd(pITableFrame); } //CheckExitMatch(); //比赛结束直接返回 if (m_enMatchStatus == MatchStatus_Null)return true; if (m_OnMatchUserMap.GetCount() > 0) { //分数通知 tagMatchScore *pScore = new tagMatchScore[m_OnMatchUserMap.GetCount()]; ZeroMemory(pScore, sizeof(tagMatchScore)*m_OnMatchUserMap.GetCount()); WORD wCount = SortMapUser(pScore); for (WORD i = 0; i < wCount; i++) { m_pMatchSink->SendGroupUserScore(pScore[i].pUserItem, this); } SafeDeleteArray(pScore); } return true; } //用户坐下 bool CImmediateGroup::OnActionUserSitDown(WORD wTableID, WORD wChairID, IServerUserItem * pIServerUserItem, bool bLookonUser) { return true; } //用户起立 bool CImmediateGroup::OnActionUserStandUp(WORD wTableID, WORD wChairID, IServerUserItem * pIServerUserItem, bool bLookonUser) { return true; } //用户同意 bool CImmediateGroup::OnActionUserOnReady(WORD wTableID, WORD wChairID, IServerUserItem * pIServerUserItem, VOID * pData, WORD wDataSize) { return false; } //获取名次 WORD CImmediateGroup::GetUserRank(IServerUserItem *pUserItem, ITableFrame *pITableFrame) { //参数效验 ASSERT(pUserItem != NULL); if (pUserItem == NULL) return INVALID_WORD; //定义变量 SCORE lUserScore = pUserItem->GetUserScore(); WORD wRank = 1; DWORD dwUserID = 0; IServerUserItem *pLoopUserItem = NULL; if (pITableFrame == NULL) { //遍历容器 POSITION pos = m_OnMatchUserMap.GetStartPosition(); while (pos != NULL) { m_OnMatchUserMap.GetNextAssoc(pos, dwUserID, pLoopUserItem); if (pLoopUserItem != pUserItem && pLoopUserItem->GetUserScore() > lUserScore) wRank++; } } else { ASSERT(pUserItem->GetTableID() == pITableFrame->GetTableID()); if (pUserItem->GetTableID() != pITableFrame->GetTableID()) return INVALID_WORD; for (WORD i = 0; iGetTableUserItem(i); if (pLoopUserItem == NULL) continue; if (pLoopUserItem != pUserItem && pLoopUserItem->GetUserScore()>lUserScore) wRank++; } } return wRank; } //获取桌子专用接口 tagTableFrameInfo* CImmediateGroup::GetTableInterface(ITableFrame* ITable) { for (int i = 0; i < m_MatchTableArray.GetCount(); i++) { if (m_MatchTableArray[i]->pTableFrame == ITable)return m_MatchTableArray[i]; } return NULL; } //比赛结束 void CImmediateGroup::MatchOver() { //删除定时器 AllKillMatchTimer(); KillMatchGameTimer(IDI_CHECK_MATCH_GROUP); KillMatchGameTimer(IDI_WAITTABLE_FIRST_ROUND); KillMatchGameTimer(IDI_WAITTABLE_RAND_TABLE); KillMatchGameTimer(IDI_SWITCH_WAIT_TIME); KillMatchGameTimer(IDI_ALL_DISMISS_GAME); KillMatchGameTimer(IDI_LASTMATCHRESULT); KillMatchGameTimer(IDI_TABLE_REQUEST_USER); //设置比赛状态 ASSERT(m_enMatchStatus == MatchStatus_FirstRound); if (m_enMatchStatus == MatchStatus_FirstRound) { m_enMatchStatus = MatchStatus_Null; m_pMatchSink->OnEventMatchOver(this); } } //定局排名游戏结束 void CImmediateGroup::FirstRoundRuleInningsGameEnd(ITableFrame *pITableFrame) { //获取对象 tagTableFrameInfo * ptagTableFrameInfo = GetTableInterface(pITableFrame); ASSERT(ptagTableFrameInfo); if (ptagTableFrameInfo == NULL) return; //设置等待下局标识 ptagTableFrameInfo->bWaitForNextInnings = true; TCHAR szMessage[128] = TEXT(""); //该桌打完指定局数 if (ptagTableFrameInfo->cbPlayCount >= m_pMatchOption->MatchType.Immediate.cbPlayCount) { _sntprintf(szMessage, CountArray(szMessage), TEXT("恭喜您,您已玩满%d局游戏,等其他桌完成后系统将进行排名,请您耐心等待!"), m_pMatchOption->MatchType.Immediate.cbPlayCount); //发送提示信息 for (WORD j = 0; j < m_wChairCount; j++) { IServerUserItem *pIServerUserItem = pITableFrame->GetTableUserItem(j); if (pIServerUserItem != NULL) { m_pMatchSink->SendGameMessage(pIServerUserItem, szMessage, SMT_CHAT | SMT_TABLE_ROLL); //插入空闲列表 InsertFreeGroup(pIServerUserItem); } else { ASSERT(FALSE); CTraceService::TraceString(TEXT("玩家信息为空1!"), TraceLevel_Exception); } } //设置完成标识 SetRoundTableFinish(pITableFrame); SendWaitTip(pITableFrame); ptagTableFrameInfo->cbPlayCount = 0; } else { if (m_pMatchOption->MatchType.Immediate.cbSwitchTableCount > 0 && (ptagTableFrameInfo->cbPlayCount%m_pMatchOption->MatchType.Immediate.cbSwitchTableCount) == 0) _sntprintf(szMessage, CountArray(szMessage), TEXT("%s"), TEXT("本局已结束,请耐心等待其他桌完成,稍后为您配桌...")); else _sntprintf(szMessage, CountArray(szMessage), TEXT("%s"), TEXT("本局已结束,请稍候,系统配桌中...")); //发送提示信息 for (WORD j = 0; j < m_wChairCount; j++) { IServerUserItem *pIServerUserItem = pITableFrame->GetTableUserItem(j); if (pIServerUserItem != NULL) { m_pMatchSink->SendGameMessage(pIServerUserItem, szMessage, SMT_CHAT | SMT_TABLE_ROLL); //插入空闲列表 InsertFreeGroup(pIServerUserItem); } else { ASSERT(FALSE); CTraceService::TraceString(TEXT("玩家信息为空2!"), TraceLevel_Exception); } } } //所有桌都完成指定局数 if (CheckRoundTableFinish()) { SetMatchGameTimer(IDI_LASTMATCHRESULT, 5000, 1, 0); return; } else if (ptagTableFrameInfo->bRoundTableFinish == false) { //自动换桌的控制 if (m_pMatchOption->MatchType.Immediate.cbSwitchTableCount > 0 && (ptagTableFrameInfo->cbPlayCount%m_pMatchOption->MatchType.Immediate.cbSwitchTableCount) == 0) { SetSwitchTableFinish(pITableFrame); SendWaitTip(pITableFrame); //检查该桌子是否可以换桌 if (CheckSwitchTableFinish()) { SetMatchGameTimer(IDI_SWITCH_WAIT_TIME, 5000, 1, 0); return; } } else //不换桌 { //设置定时器 PostMatchTimer(IDI_CONTINUE_GAME, 5, (WPARAM)pITableFrame); return; } } } //发送提示 VOID CImmediateGroup::SendWaitTip(ITableFrame *pTableFrame, WORD wChairID/*=INVALID_CHAIR*/) { //状态校验 if (m_enMatchStatus == MatchStatus_Null || m_enMatchStatus == MatchStatus_Signup) return; tagTableFrameInfo *pITableFameEx = GetTableInterface(pTableFrame); ASSERT(pITableFameEx != NULL); if (pITableFameEx == NULL) return; //变量定义 WORD wPlayingTable = 0; for (WORD i = 0; i < m_MatchTableArray.GetCount(); i++) { if (m_MatchTableArray[i]->pTableFrame->GetGameStatus() >= GAME_STATUS_PLAY) wPlayingTable++; } //变量定义 CMD_GR_Match_Wait_Tip WaitTip; ZeroMemory(&WaitTip, sizeof(WaitTip)); WaitTip.wPlayingTable = wPlayingTable; WaitTip.wUserCount = (WORD)m_OnMatchUserMap.GetCount(); WaitTip.wCurGameCount = pITableFameEx->cbPlayCount; WaitTip.wGameCount = m_pMatchOption->MatchType.Immediate.cbPlayCount; lstrcpyn(WaitTip.szMatchName, m_pMatchOption->szMatchName, LEN_SERVER); //发送比赛信息给本桌的玩家 for (WORD i = 0; i < m_wChairCount; i++) { if (wChairID != INVALID_CHAIR && wChairID != i) continue; IServerUserItem *pTableUserItem = pTableFrame->GetTableUserItem(i); if (pTableUserItem == NULL) continue; WaitTip.wCurTableRank = GetUserRank(pTableUserItem, pTableFrame); if (WaitTip.wCurTableRank == INVALID_WORD) continue; WaitTip.wRank = GetUserRank(pTableUserItem); WaitTip.lScore = pTableUserItem->GetUserScore(); m_pMatchSink->SendData(pTableUserItem, MDM_GF_FRAME, SUB_GR_MATCH_WAIT_TIP, &WaitTip, sizeof(WaitTip)); } //发送比赛信息给其他桌的玩家 for (WORD i = 0; i < m_MatchTableArray.GetCount(); i++) { if (pTableFrame->GetTableID() == m_MatchTableArray[i]->pTableFrame->GetTableID())continue; if (m_MatchTableArray[i]->pTableFrame->GetGameStatus() >= GAME_STATUS_PLAY) continue; for (WORD j = 0; j < m_wChairCount; j++) { IServerUserItem *pTableUserItem = m_MatchTableArray[i]->pTableFrame->GetTableUserItem(j); if (pTableUserItem == NULL) continue; WaitTip.wCurTableRank = GetUserRank(pTableUserItem, m_MatchTableArray[i]->pTableFrame); if (WaitTip.wCurTableRank == INVALID_WORD) continue; WaitTip.wRank = GetUserRank(pTableUserItem); WaitTip.lScore = pTableUserItem->GetUserScore(); m_pMatchSink->SendData(pTableUserItem, MDM_GF_FRAME, SUB_GR_MATCH_WAIT_TIP, &WaitTip, sizeof(WaitTip)); } } } //空闲桌子拉空闲用户 void CImmediateGroup::TabelRequestUser(bool bPrecedeSit) { //参赛用户不够 椅子数量就要终止比赛 if (CheckMatchUser()) { return; } CTableFrameMananerArray FreeTableArray; //空比赛桌子 //首先获取空桌子 for (INT_PTR i = 0; i < m_MatchTableArray.GetCount(); i++) { if (m_MatchTableArray[i]->pTableFrame->IsGameStarted() == false && m_MatchTableArray[i]->bRoundTableFinish == false) { //获取数量 INT_PTR cbTimer = m_MatchTimerArray.GetCount(); bool cbIsInsert = false; for (int j = 0; j < cbTimer; j++) { //判断一下有没有卡赛的桌子在等待 if ((m_MatchTimerArray[j]->dwTimerID == IDI_CHECK_TABLE_START || m_MatchTimerArray[j]->dwTimerID == IDI_CONTINUE_GAME) && (ITableFrame*)(m_MatchTimerArray[j]->wParam) == m_MatchTableArray[i]->pTableFrame) { cbIsInsert = true; break; } } if (cbIsInsert == false) FreeTableArray.Add(m_MatchTableArray[i]); } } DWORD dwCurTime = (DWORD)time(NULL); bool bIsContinueCheck = false;//优化优先坐下 原本是true for (INT_PTR i = 0; i0) { AllUserExitTable(FreeTableArray[i]->pTableFrame); for (int j = 0; j < m_wChairCount; j++) { //用户插入该桌 WORD wRandID = INVALID_VALUE; if (bPrecedeSit&&bIsContinueCheck) { wRandID = GetPrecedeSitUser(dwCurTime); } if (wRandID == INVALID_VALUE) { bIsContinueCheck = false;//已经没有优先用户了 wRandID = rand() % (WORD)m_FreeUserArray.GetCount(); } IServerUserItem *pIServerUserItem = m_FreeUserArray[wRandID]; ASSERT(pIServerUserItem != NULL); if (pIServerUserItem == NULL) continue; //先起立在坐下 让该桌的人全部起立 if (pIServerUserItem->GetTableID() != INVALID_TABLE) { for (int m = 0; m < m_MatchTableArray.GetCount(); m++) { if (pIServerUserItem->GetTableID() == m_MatchTableArray[m]->wTableID) { m_MatchTableArray[m]->pTableFrame->PerformStandUpAction(pIServerUserItem); break; } } } if (FreeTableArray[i]->pTableFrame->PerformSitDownAction(j, pIServerUserItem)) { m_FreeUserArray.RemoveAt(wRandID); } else { CTraceService::TraceString(TEXT("坐下失败?"), TraceLevel_Exception); } } //30秒后做一个检查 发现该桌还没有开始游戏 说明已经卡掉了 PostMatchTimer(IDI_CHECK_TABLE_START, 30, (WPARAM)FreeTableArray[i]->pTableFrame); } } return; } //发送一组信息 void CImmediateGroup::SendGroupBox(LPCTSTR pStrMessage) { //构造数据包 CMD_CM_SystemMessage Message; Message.wType = SMT_EJECT | SMT_CHAT; lstrcpyn(Message.szString, pStrMessage, CountArray(Message.szString)); Message.wLength = CountStringBuffer(Message.szString); //发送数据 WORD wSendSize = sizeof(Message)-sizeof(Message.szString) + Message.wLength*sizeof(TCHAR); m_pMatchSink->SendGroupData(MDM_CM_SYSTEM, SUB_CM_SYSTEM_MESSAGE, &Message, wSendSize, this); } //设置一轮完成标记 void CImmediateGroup::SetRoundTableFinish(ITableFrame *pITableFrame) { tagTableFrameInfo * ptagTableFrameInfo = GetTableInterface(pITableFrame); ASSERT(ptagTableFrameInfo); if (ptagTableFrameInfo)ptagTableFrameInfo->bRoundTableFinish = true; } //检查一轮是否完成 bool CImmediateGroup::CheckRoundTableFinish() { for (int i = 0; i < m_MatchTableArray.GetCount(); i++) { if (m_MatchTableArray[i]->bRoundTableFinish == false)return false; } return true; } //设置换桌完成标记 void CImmediateGroup::SetSwitchTableFinish(ITableFrame *pITableFrame) { tagTableFrameInfo * ptagTableFrameInfo = GetTableInterface(pITableFrame); ASSERT(ptagTableFrameInfo); if (ptagTableFrameInfo)ptagTableFrameInfo->bSwtichTableFinish = true; } //检查换桌是否完成 bool CImmediateGroup::CheckSwitchTableFinish() { for (int i = 0; i < m_MatchTableArray.GetCount(); i++) { if (m_MatchTableArray[i]->bSwtichTableFinish == false)return false; } return true; } //设置所有用户离开 void CImmediateGroup::AllUserExitTable(ITableFrame *pITableFrame) { ASSERT(pITableFrame != NULL); if (pITableFrame) { //该桌用户全部离开 for (int i = 0; i < m_wChairCount; i++) { IServerUserItem* pUserItem = pITableFrame->GetTableUserItem(i); if (pUserItem&&pUserItem->GetTableID() != INVALID_TABLE)pITableFrame->PerformStandUpAction(pUserItem); } } } //本桌继续游戏 void CImmediateGroup::ContinueGame(ITableFrame *pITableFrame) { if (CheckMatchUser()) { return; } tagTableFrameInfo * ptagTableFrameInfo = GetTableInterface(pITableFrame); ASSERT(ptagTableFrameInfo); if (ptagTableFrameInfo) { AllUserExitTable(pITableFrame); for (int i = 0; i < m_wChairCount; i++) { IServerUserItem* pIServerUserItem = m_FreeUserArray[0]; if (pIServerUserItem == NULL) { ASSERT(FALSE); CTraceService::TraceString(TEXT("空的用户存在于等待列表中。"), TraceLevel_Exception); return; } //先起立在坐下 让该桌的人全部起立 if (pIServerUserItem->GetTableID() != INVALID_TABLE) { for (int m = 0; m < m_MatchTableArray.GetCount(); m++) { if (pIServerUserItem->GetTableID() == m_MatchTableArray[m]->wTableID) { m_MatchTableArray[m]->pTableFrame->PerformStandUpAction(pIServerUserItem); break; } } } if (pITableFrame->PerformSitDownAction(i, pIServerUserItem)) { m_FreeUserArray.RemoveAt(0); } else { CTraceService::TraceString(TEXT("坐下失败?1"), TraceLevel_Exception); } } //30秒后做一个检查 发现该桌还没有开始游戏 说明已经卡掉了 PostMatchTimer(IDI_CHECK_TABLE_START, 30, (WPARAM)pITableFrame); } } void CImmediateGroup::SetMatchGameTimer(DWORD dwTimerID, DWORD dwElapse, DWORD dwRepeat, WPARAM dwBindParameter) { if (m_pMatchSink) m_pMatchSink->SetGameTimer(dwTimerID + 10 * m_LoopTimer, dwElapse, dwRepeat, dwBindParameter, this); } //杀死比赛专用定时器 void CImmediateGroup::KillMatchGameTimer(DWORD dwTimerID) { if (m_pMatchSink) m_pMatchSink->KillGameTimer(dwTimerID + 10 * m_LoopTimer, this); } //检测参赛人数 bool CImmediateGroup::CheckMatchUser() { //参赛用户不够 椅子数量就要终止比赛 DWORD nCurUserCount = (DWORD)m_OnMatchUserMap.GetCount(); if (nCurUserCount < m_wChairCount) { ASSERT(FALSE); CTraceService::TraceString(TEXT("检查人数..."), TraceLevel_Exception); return false; //构造数据包 CString szString; szString.Format(TEXT("抱歉,由于比赛用户强行退出比赛,人数不足 %d 人,提前结算。欢迎您继续报名参加比赛!"), m_wChairCount); SendGroupBox(szString); MatchOver(); return true; } return false; } //获取优先坐下用户 WORD CImmediateGroup::GetPrecedeSitUser(DWORD dwCurTime) { for (int i = 0; iGetTimeInfo(); if (dwCurTime - pTimerInfo->dwEndGameTimer>m_pMatchOption->MatchType.Immediate.wPrecedeTimer) return i; } return INVALID_VALUE; } //实现该函数可保证Free组唯一 void CImmediateGroup::InsertFreeGroup(IServerUserItem *pUserItem) { if (pUserItem == NULL)return; for (int i = 0; i < m_FreeUserArray.GetCount(); i++) { if (m_FreeUserArray[i] != NULL && m_FreeUserArray[i]->GetUserID() == pUserItem->GetUserID())return; } m_FreeUserArray.Add(pUserItem); } //发送比赛信息 void CImmediateGroup::SendTableUserMatchInfo(ITableFrame *pITableFrame, WORD wChairID) { //验证参数 ASSERT(pITableFrame != NULL); if (pITableFrame == NULL) return; tagTableFrameInfo *ptagTableFrameInfo = GetTableInterface(pITableFrame); if (ptagTableFrameInfo == NULL) return; //变量定义 WORD wChairCount = pITableFrame->GetChairCount(); TCHAR szMsg[256] = TEXT(""); if (m_enMatchStatus == MatchStatus_FirstRound) { //构造数据 CMD_GR_Match_Info MatchInfo; ZeroMemory(&MatchInfo, sizeof(MatchInfo)); _sntprintf(MatchInfo.szTitle[0], CountArray(MatchInfo.szTitle[0]), TEXT("积分方式:累计积分")); _sntprintf(MatchInfo.szTitle[1], CountArray(MatchInfo.szTitle[1]), TEXT("游戏基数:%d"), m_dwCurBase); _sntprintf(MatchInfo.szTitle[2], CountArray(MatchInfo.szTitle[2]), TEXT("局制名称:定局排名")); _sntprintf(MatchInfo.szTitle[3], CountArray(MatchInfo.szTitle[3]), TEXT("需要完成:%d局比赛"), m_pMatchOption->MatchType.Immediate.cbPlayCount); MatchInfo.wGameCount = ptagTableFrameInfo->cbPlayCount; //wChairID为INVALID_CHAIR发给本桌所有玩家,否则只发给指定玩家 for (WORD i = 0; i < wChairCount; i++) { //获取用户 if (wChairID != INVALID_CHAIR && wChairID != i) continue; IServerUserItem *pIServerUserItem = pITableFrame->GetTableUserItem(i); if (pIServerUserItem == NULL) continue; //发送数据 pITableFrame->SendTableData(i, SUB_GR_MATCH_INFO, &MatchInfo, sizeof(MatchInfo), MDM_GF_FRAME); } //发送提示 if ((wChairID != INVALID_CHAIR) && (ptagTableFrameInfo->bWaitForNextInnings == true)) { SendWaitTip(pITableFrame, wChairID); } } return; } //捕获比赛专用定时器 void CImmediateGroup::CaptureMatchTimer() { for (int i = 0; i < m_MatchTimerArray.GetCount(); i++) { if (--m_MatchTimerArray[i]->iElapse <= 0) { if (m_MatchTimerArray[i]->dwTimerID == IDI_CONTINUE_GAME) { //本桌用户继续游戏 ContinueGame((ITableFrame*)m_MatchTimerArray[i]->wParam); } else if (m_MatchTimerArray[i]->dwTimerID == IDI_LEAVE_TABLE) { //离开本桌 AllUserExitTable((ITableFrame*)m_MatchTimerArray[i]->wParam); } else if (m_MatchTimerArray[i]->dwTimerID == IDI_CHECK_TABLE_START) { //检查桌子是否开始游戏 //CheckTableStart((ITableFrame*)m_MatchTimerArray[i]->wParam); } //删除定时器 if (KillMatchTimer(i))i--; else ASSERT(false); } } } //投递比赛专用定时器 void CImmediateGroup::PostMatchTimer(DWORD dwTimerID, int iElapse, WPARAM wParam, LPARAM lParam) { tagMatchTimer* pMatchTimer = new tagMatchTimer; pMatchTimer->dwTimerID = dwTimerID; pMatchTimer->iElapse = iElapse; //pMatchTimer->dwRepeat=dwRepeat; pMatchTimer->wParam = wParam; pMatchTimer->lParam = lParam; m_MatchTimerArray.Add(pMatchTimer); } //杀死比赛专用定时器 bool CImmediateGroup::KillMatchTimer(DWORD dwTimerID, WPARAM wParam) { for (int i = 0; i < m_MatchTimerArray.GetCount(); i++) { if (m_MatchTimerArray[i]->dwTimerID == dwTimerID&&m_MatchTimerArray[i]->wParam == wParam) { tagMatchTimer* pMatchTimer = m_MatchTimerArray[i]; m_MatchTimerArray.RemoveAt(i); SafeDelete(pMatchTimer); return true; } } return false; } //杀死比赛专用定时器 bool CImmediateGroup::KillMatchTimer(INT_PTR dwIndexID) { ASSERT(dwIndexID >= 0 && dwIndexID < m_MatchTimerArray.GetCount()); if (dwIndexID >= 0 && dwIndexID < m_MatchTimerArray.GetCount()) { tagMatchTimer* pMatchTimer = m_MatchTimerArray[dwIndexID]; m_MatchTimerArray.RemoveAt(dwIndexID); SafeDelete(pMatchTimer); return true; } return false; } //全部杀死比赛专用定时器 void CImmediateGroup::AllKillMatchTimer() { for (int i = 0; i < m_MatchTimerArray.GetCount();/*i++*/) { tagMatchTimer* pMatchTimer = m_MatchTimerArray[i]; m_MatchTimerArray.RemoveAt(i); SafeDelete(pMatchTimer); } }