接着昨天的继续完成牌壳的程序。
1.继续完成 CardsApp 类
1.1 在 CardsApp 类的析构函数中删除光标链表 lstCursorCards 上的牌;
1.2 为显示光标上的牌创建一个函数:ShowCursorCards,只需传入一个 dc 就可以;
1.首先需要一个 int X 和一个 int Y 来记录光标在横轴和纵轴上移动的距离,X 和 Y 可以由在 OnLButtonUp 和 OnMouseMove 里获取的鼠标坐标相减获得;
2.对光标链表上的元素进行遍历,遍历的过程中进行贴图;
3.在 OnGameDraw 函数里使用 this 调用 ShowCursorCards 函数。
1.3 具体程序
void CCardsApp::ShowCursorCards(HDC hdc)
{
int X = pointMouseMove.x - pointMouseDown.x;
int Y = pointMouseMove.y - pointMouseDown.y;
list<Node*>::iterator ite = lstCursorCards.begin();
while (ite != lstCursorCards.end())
{
HDC tempDC = ::CreateCompatibleDC(hdc);
::SelectObject(tempDC, (*ite)->pCards->m_hBmpCards);
::BitBlt(hdc, (*ite)->x+X, (*ite)->y+Y, 71, 96, tempDC, 0, 0, SRCCOPY);
::DeleteDC(tempDC);
++ite;
}
}
2.向项目中添加 AAARule 类
2.1 本次的 AAARule 类已经在之前的学习中编写完成,可以直接复制拷贝到当前工作目录下;
2.2 在完成了上述步骤后可以进行拿牌的操作,但是会发现一个问题:当鼠标在窗口外部时移动鼠标,牌也会跟着移动,即当鼠标移出窗口时,希望牌回到原来的位置,因此我们需要一些小技巧来进行捕获鼠标消息。
1.在 OnLButtonDown 中截获鼠标消息: ::SetCapture(m_hMainWnd);
2.在 OnLButtonUp 中释放鼠标消息: ::ReleaseCapture()。
经过上述两步操作即可完成鼠标移出当前窗口后,牌会回到原位而不是随着鼠标继续移动。
2.3 具体代码
void CCardsApp::OnLButtonDown(POINT point) // WM_LBUTTONDOWN
{
pointMouseDown = point;
::SetCapture(m_hMainWnd);
// 判断是否有拿牌的规则
if (m_pRule)
{
m_pRule->GetCards(point, m_pRank, lstCursorCards);
}
this->OnGameDraw();
}
void CCardsApp::OnLButtonUp(POINT point) // WM_LBUTTONUP
{
// 释放截获鼠标消息的动作
::ReleaseCapture();
if (m_pRule) // 若有规则,则判断光标的链表是不是空,
{
if(lstCursorCards.empty() == false)
{
// 如果光标链表不是空,判断能否接受牌,不能则还原
if(m_pRule->ReceiveCards(point, m_pRank, lstCursorCards) == false)
m_pRule->RevertCards(m_pRank, lstCursorCards);
}
// 如果是空,则判断能否进行发牌
else
{
if(m_pRule->IsOpenCards(point, m_pRank) == true)
m_pRule->OpenCards(m_pRank);
}
this->OnGameDraw();
}
}
3.完成 Rule 类中的 ReceiveCards 函数
3.1 首先我们遍历所有的链表,由于本函数的目的是判断是否收到了牌,因此需要判断是否能够接收牌;
3.2 若能够接收牌,若当前链表可以接收牌(满足 IsReceiveCardsRule ),则我们将光标上的链表放到当前链表的最后,并对齐、更新位置 this->UpDatePos ;
3.3 若光标链表牌的原位置仍有牌则将该牌翻过来,并将记录拿牌的链表的下标数 m_nGetCardsListID 归为初始值 -1 。
3.4 具体代码
bool CRule::ReceiveCards(POINT point, CCardsRank* pCradsRank, list<Node*>& lstCursorCards)
{
for (size_t i=0; i<pCradsRank->m_vecRank.size(); i++)
{
// 判断是否能够接收牌,
if(this->IsReceiveCardsRule(point, i, pCradsRank, lstCursorCards) == true)
{
// 能接收则与第i个链表结合
pCradsRank->m_vecRank[i].splice(pCradsRank->m_vecRank[i].end(), lstCursorCards);
// 对齐,更新位置
this->UpDatePos(pCradsRank, i);
// 将移动牌原位置上一张牌进行翻牌:如果有的话
if(m_nGetCardsListID != -1 && pCradsRank->m_vecRank[m_nGetCardsListID].empty() == false)
pCradsRank->m_vecRank[m_nGetCardsListID].back()->bflag = true;
m_nGetCardsListID = -1; // 使用后归位初始值
return true;
}
}
return false;
}