📄 i_goview.cpp
字号:
/////////////////////////////////////////////////////////////////////////////
// CI_goView diagnostics
#ifdef _DEBUG
void CI_goView::AssertValid() const
{
CView::AssertValid();
}
void CI_goView::Dump(CDumpContext& dc) const
{
CView::Dump(dc);
}
CI_goDoc* CI_goView::GetDocument() // non-debug version is inline
{
ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CI_goDoc)));
return (CI_goDoc*)m_pDocument;
}
#endif //_DEBUG
/////////////////////////////////////////////////////////////////////////////
// CI_goView message handlers
void CI_goView::OnLButtonDown(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
CI_goDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
//===========================================================================//
//开始
//===========================================================================//
pDoc->fIllegal = FALSE;
CPoint pointE;
int nXDistance=(point.x-pDoc->pointBegin.x)%pDoc->nDistance;
int nYDistance=(point.y-pDoc->pointBegin.y)%pDoc->nDistance;
if(nXDistance<pDoc->nDistance/2)
pointE.x=point.x-nXDistance;
else
pointE.x=point.x-nXDistance+pDoc->nDistance;
if(nYDistance<pDoc->nDistance/2)
pointE.y=point.y-nYDistance;
else
pointE.y=point.y-nYDistance+pDoc->nDistance;
//===========================================================================//
int row=(pointE.y-pDoc->pointBegin.y)/pDoc->nDistance;//鼠标所在点在的行位置
int col=(pointE.x-pDoc->pointBegin.x)/pDoc->nDistance;//鼠标所在点在的列位置
//===========================================================================//
CRect m_rectQipan(pDoc->pointBegin.x-pDoc->r/2,pDoc->pointBegin.y-pDoc->r/2,pDoc->pointBegin.x+pDoc->nDistance*18+pDoc->r/2,pDoc->pointBegin.y+pDoc->nDistance*18+pDoc->r/2);
if(m_rectQipan.PtInRect(point)&&nCenter==nDie)
{
//===========================================================================//
//将此前的各状态备份
//===========================================================================//
Backup_Parameters();
pDoc->nCount++;
if(pDoc->nCount%2==1) //第一手画黑棋
nCenter=nBlack;
else
nCenter=nWhite;
//===========================================================================//
//更改当前点和周围四个点的关系,即链标志
//===========================================================================//
Set_Left_Up_Right_Down_Chain(row,col);
//===========================================================================//
//对所有的点进行扫描,并根据情况进行更改
//即重新生成标志数组pDoc->nSign[1~19][1~19]
//把更改前的保存在数组pDoc->nOldSign[1~19][1~19]
//===========================================================================//
Scan_And_Change();
//===========================================================================//
//扫描所有点,如果标志pDoc->nSign[i][j]为nWhite的相邻点
//标志nWhiteWait改为nWhite
//===========================================================================//
Chg_nWhiteWait_to_nWhite();
//===========================================================================//
//扫描所有点,如果标志pDoc->nSign[i][j]为nBlack的相邻点
//标志nBlackWait改为nBlack
//===========================================================================//]
Chg_nBlackWait_to_nBlack();
//===========================================================================//
//清除所有标志为nWhiteWait或者nBlackWait或者nDie的棋子
//将与之相关的非界外链改为nFree,界外链维持nDifferent
//===========================================================================//
Clear_nWhiteWait_and_nBlackWait_and_nDie();
//===========================================================================//
//统计双方当前棋子数
//===========================================================================//
Calculate_Black_And_White();
//===========================================================================//
//打劫:
//新填的子被吃掉吗?
//1、如果被吃掉,而且吃掉前一次点击未在此处吃同色的子,
//则改子要恢复成吃掉以前的棋子,即新棋子
//同时将四周的链关系改回来
//2、如果被吃掉,而且吃掉前一次点击刚在该处被吃掉同色的子,则视为非法走步
//各标志位恢复到下子以前的状态
//===========================================================================//
//新填的子被吃?(nCenter==nDie?)
//yes!
//同时导致对方的字被吃?Y
//前一次有没有与新填的字同色的子在该处被吃?Y
//则为合法走步!则恢复被吃掉的与新填子同色的被吃子,更改链标志
//如果为非法走步,则此次走棋无效,调用悔棋程序,并提示走步非法
//===========================================================================//
Determine_Illegal_And_Dajie(row,col);
//===========================================================================//
//统计双方当前棋子数
//===========================================================================//
Calculate_Black_And_White();
//===========================================================================//
//更新左边的文字区域
//===========================================================================//
CRect m_rectLeft(0,0,pDoc->pointBegin.x-50,pDoc->pointBegin.y+pDoc->nDistance*18);
InvalidateRect(m_rectLeft);
//===========================================================================//
//只画被更新的围棋点,即nOldCenter和nCenter不同的棋子
//===========================================================================//
InvalidateRect(pDoc->m_rectEllipse[row][col]);
for(row=0;row<19;row++)
for(col=0;col<19;col++)
if(nOldCenter!=nCenter) //有变化的更新
InvalidateRect(pDoc->m_rectEllipse[row][col]);
pDoc->fRegretOnlyOnce = FALSE;
}
//===========================================================================//
//悔棋
//===========================================================================//
else
{
CRect m_rectRegret(pDoc->pointForRegret.x,pDoc->pointForRegret.y,pDoc->pointForRegret.x+8*pDoc->r,pDoc->pointForRegret.y+2*pDoc->r);
if(m_rectRegret.PtInRect(point) && pDoc->fRegretOnlyOnce == FALSE)
{
regret();
Invalidate();
pDoc->fRegretOnlyOnce = TRUE;
}
}
CView::OnLButtonDown(nFlags, point);
}
//===========================================================================//
//对所有的点进行扫描,并根据情况进行更改
//即重新生成标志数组pDoc->nSign[1~19][1~19]
//把更改前的保存在数组pDoc->nOldSign[1~19][1~19]
//===========================================================================//
void CI_goView::Scan_And_Change()
{
CI_goDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
for(int row=0;row<19;row++)
for(int col=0;col<19;col++)
if(nCenter!=nDie)//空位不用判断
{
//情况1:当前子的四周至少有一个空位,活棋
//决策:与该子有关的所有子状态不变,若已经被改为nWait则要改回来
if(nLeftChain==nFree||nRightChain==nFree||nUpChain==nFree||nDownChain==nFree)
{
nCenter = nCenter;
}
//情况2:当前子的四周有子,且都是不同子,被围死
//决策:置该子的标志为nWait,更新中被清除
else if(nLeftChain==nDifferent&&nRightChain==nDifferent&&nUpChain==nDifferent&&nDownChain==nDifferent)
{
nOldCenter = nCenter;
nCenter = nWait;
}
//情况3:当前子的四周都有子,但至少有一个相同子
//决策:标志若为nWhite则改为nWhiteWait
// nBlack则改为nBlackWait
// 并保存原标志道nOldCenter
else if(nLeftChain==nSame||nRightChain==nSame||nUpChain==nSame||nDownChain==nSame)
{
nOldCenter = nCenter;
if(nCenter==nWhite)
nCenter = nWhiteWait;
else
nCenter = nBlackWait;
}
}
}
//===========================================================================//
//扫描所有点,如果标志pDoc->nSign[i][j]为nWhite的相邻点
//标志nWhiteWait改为nWhite
//===========================================================================//
void CI_goView::Chg_nWhiteWait_to_nWhite()
{
CI_goDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
for(int i=0;i<361;i++)
for(int row=0;row<19;row++)
for(int col=0;col<19;col++)
if(nCenter==nWhite)
{
if(nLeft == nWhiteWait)
nLeft = nOldLeft;
if(nRight == nWhiteWait)
nRight = nOldRight;
if(nUp == nWhiteWait)
nUp = nOldUp;
if(nDown == nWhiteWait)
nDown = nOldDown;
}
}
//===========================================================================//
//扫描所有点,如果标志pDoc->nSign[i][j]为nBlack的相邻点
//标志nBlackWait改为nBlack
//===========================================================================//
void CI_goView::Chg_nBlackWait_to_nBlack()
{
CI_goDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
for(int i=0;i<361;i++)
for(int row=0;row<19;row++)
for(int col=0;col<19;col++)
if(nCenter==nBlack)
{
if(nLeft == nBlackWait)
nLeft = nOldLeft;
if(nRight == nBlackWait)
nRight = nOldRight;
if(nUp == nBlackWait)
nUp = nOldUp;
if(nDown == nBlackWait)
nDown = nOldDown;
}
}
//===========================================================================//
//清除所有标志为nWhiteWait或者nBlackWait或者nDie的棋子
//将与之相关的非界外链改为nFree,界外链维持nDifferent
//===========================================================================//
void CI_goView::Clear_nWhiteWait_and_nBlackWait_and_nDie()
{
CI_goDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
for(int row=0;row<19;row++)
for(int col=0;col<19;col++)
//(nCenter!=nBackCenter)判断只是为了避免对本来就是空位的点进行清空
if((nCenter!=nBackCenter)&&(nCenter==nWhiteWait||nCenter==nBlackWait||nCenter==nWait))
{
nCenter=nDie;
Set_Left_Up_Right_Down_Chain(row, col);
}
}
//===========================================================================//
//将此前的各状态备份
//===========================================================================//
void CI_goView::Backup_Parameters()
{
CI_goDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
for(int row=0;row<19;row++)
for(int col=0;col<19;col++)
{
nBackThreeTimesBeforeCenter = nBackTwoTimesBeforeCenter;
nBackTwoTimesBeforeCenter = nBackCenter;
nBackOldCenter = nOldCenter;
nBackCenter = nCenter;
nBackRightChain= nRightChain;
nBackDownChain = nDownChain;
}
pDoc->nBackCalculateBlack = pDoc->nCalculateBlack;
pDoc->nBackCalculateWhite = pDoc->nCalculateWhite;
pDoc->nBackCountTwoTimesBefore =pDoc->nBackCount;
pDoc->nBackCount = pDoc->nCount;
}
//===========================================================================//
//悔棋程序
//===========================================================================//
void CI_goView::regret()
{
CI_goDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
for(int row=0;row<19;row++)
for(int col=0;col<19;col++)
{
nOldCenter = nBackOldCenter;
nCenter = nBackCenter;
nBackCenter= nBackTwoTimesBeforeCenter;
nBackTwoTimesBeforeCenter = nBackThreeTimesBeforeCenter;
nRightChain= nBackRightChain;
nDownChain = nBackDownChain;
}
pDoc->nCount = pDoc->nBackCount;
pDoc->nBackCount = pDoc->nBackCountTwoTimesBefore;
pDoc->nCalculateBlack = pDoc->nBackCalculateBlack;
pDoc->nCalculateWhite = pDoc->nBackCalculateWhite;
}
//===========================================================================//
//统计双方当前棋子数目
//===========================================================================//
void CI_goView::Calculate_Black_And_White()
{
CI_goDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -