⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 i_goview.cpp

📁 一个简单的围棋游戏
💻 CPP
📖 第 1 页 / 共 3 页
字号:
/////////////////////////////////////////////////////////////////////////////
// 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 + -