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

📄 cwindow.cpp

📁 WindowsProgrammingFoundation C++学习很好的书籍 希望能够起到帮助
💻 CPP
字号:
#include "CWindow.h"

///////////////////////////////////////////////////////////////////////////////


void CWindow::Create(HWND hWnd, HINSTANCE hInstance )
{

    _hWnd = hWnd;
	m_hboard = ::LoadBitmap( hInstance, MAKEINTRESOURCE(IDB_BOARD));
//_hboard = ::LoadBitmap( hInstance, TEXT("BGROUND"));
	m_hblackchess = ::LoadBitmap( hInstance, MAKEINTRESOURCE(IDB_BLACKCHESS));
	m_hwhitechess = ::LoadBitmap( hInstance, MAKEINTRESOURCE(IDB_WHITECHESS));
	m_hblack = ::LoadBitmap( hInstance, MAKEINTRESOURCE(IDB_BLACK));
	m_hlastblackchess = ::LoadBitmap( hInstance, MAKEINTRESOURCE(IDB_LASTBLACK));
	m_hlastwhitechess = ::LoadBitmap( hInstance, MAKEINTRESOURCE(IDB_LASTWHITE));

	m_bwfirst = false;  //玩家先走
	m_binit = false;
	computer = player = false;

	InitializeBoard();

	::SetTimer( _hWnd, ID_TIMER, 80, NULL );//产生一个计时器,它每200毫秒给窗口发送一个WM_TIMER消息
 }

void CWindow::Destroy()
{
	::DeleteObject( m_hlastwhitechess);
	::DeleteObject( m_hlastblackchess );
	::DeleteObject( m_hblack );
	::DeleteObject( m_hwhitechess );
	::DeleteObject( m_hblackchess );
	::DeleteObject( m_hboard );
	::KillTimer( _hWnd, ID_TIMER );
	::PostQuitMessage( 0 );
}

void CWindow::InitializeBoard()
{
	//初始化函数
	int i,j,count=0,k;
	m_pclastpos.x=-1;//计算机走的前一步棋的位置
	m_pclastpos.y=-1;

	m_pplastpos.x=-1;//玩家走的前一步棋的位置
	m_pplastpos.y=-1;

	start = true;
	//判断哪方先开始
	if(m_bwfirst)  //计算机先走
	{
		player=false;
		computer=true;
	}
	else   //玩家先走
	{
		player=true;
	    computer=false;
	}

	pwin=cwin=false;

	//初始化计算机和玩家的获胜组合情况
	for(i=0;i<15;i++)
		for(j=0;j<15;j++)
			for(k=0;k<572;k++)
			{
				ptable[i][j][k]=false;
				ctable[i][j][k]=false;
			}
	for(i=0;i<2;i++)
		for(j=0;j<572;j++)
			win[i][j]=0;

	for(i=0;i<15;i++)
		for(j=0;j<15;j++)
			board[i][j] = NoBall;

	//Set the vertical combinations winning status.
    for(i=0;i<15;i++)
		for(j=0;j<11;j++)
		{
			for(k=0;k<5;k++)
			{
				ptable[j+k][i][count]=true;
				ctable[j+k][i][count]=true;
			}
			count++;
		}
	//Set the horizontal combinations winning status.
	for(i=0;i<15;i++)
		for(j=0;j<11;j++)
		{
			for(k=0;k<5;k++)
			{
				ptable[i][j+k][count]=true;
				ctable[i][j+k][count]=true;
			}
			count++;
		}
	//Set the positive diagonal winning status.
	for(i=0;i<11;i++)
		for(j=0;j<11;j++)
		{
			for(k=0;k<5;k++)
			{
				ptable[j+k][i+k][count]=true;
				ctable[j+k][i+k][count]=true;
			}
			count++;
		}
	//Set the negative diagonal winning status.
	for(i=0;i<11;i++)
		for(j=14;j>=4;j--)
		{
			for(k=0;k<5;k++)
			{
				ptable[j-k][i+k][count]=true;
				ctable[j-k][i+k][count]=true;
			}
			count++;
		}
}

void CWindow::OnLButtonDown(POINT point)
{
		int x,y,tx,ty;
	// 根据鼠标的数据point计算出棋盘的第几格?(x,y)

	if(player && point.x<=535 && point.y<=535)//判断是否在有效区域
	{
		tx=x=point.x-24;
		ty=y=point.y-25;
		while(tx>=36)
			tx-=36;
		while(ty>=36)
			ty-=36;
		tx+=x/36;
		ty+=y/36;
		if(tx>18)
			x=x/36+1;
		else
			x=x/36;
		if(ty>18)
			y=y/36+1;
		else
			y=y/36;
		if(board[x][y] == NoBall)
		{
			board[x][y] = PlayerBall;//设为玩家的棋子

			if(m_pplastpos.x!=-1 && m_pplastpos.y!=-1)//如果有玩家走的前一步棋
			{
				if(!m_bwfirst)//玩家先走
					DrawWhiteChess(m_pplastpos.x,m_pplastpos.y);
			    else
				    DrawBlackChess(m_pplastpos.x,m_pplastpos.y);
			}

			if(!m_bwfirst)//玩家先走
				DrawNowWhite(x,y);
			else
				DrawNowBlack(x,y);
			m_pplastpos.x = x;
			m_pplastpos.y = y;
			
			//修改玩家下子后棋盘状态的变化
			for(int i=0;i<572;i++)
			{
				if(ptable[x][y][i] && win[0][i]!=7)
					win[0][i]++;

				if(ctable[x][y][i])
				{
					ctable[x][y][i]=false;
					win[1][i]=7;
				}
			}
			player=false;
		    computer=true;
		}
	}
	//CDialog::OnLButtonDown(nFlags, point);
}


void CWindow::OnTimer(UINT nIDEvent) 
{
	// TODO: Add your message handler code here and/or call default
	IsWin();
	if(pwin)  //玩家取胜
	{
		::KillTimer(_hWnd,ID_TIMER);//清除计时器
		::MessageBox( NULL, "恭喜,您真厉害!", "RESULT", MB_OK | MB_ICONINFORMATION );
		player=false;
		computer=false;
		m_binit=true;
	}
	else if(cwin)  //计算机取胜
	{
		::KillTimer(_hWnd,ID_TIMER);
		::MessageBox( NULL, "抱歉,您输了", "RESULT", MB_OK | MB_ICONINFORMATION );
		player=false;
		computer=false;
		m_binit=true;
	}
	else  //还没有胜出
	{
		if(computer)  //轮到计算机下棋
			ComTurn();
	}
}

void CWindow::IsWin()//判断是否已有一方
{
	int i;
	for(i=0;i<572;i++)
	{
		if(win[0][i]==5)
		{
			pwin = true; //玩家取胜
			break;
		}
		if(win[1][i]==5)
		{
			cwin = true; //计算机取胜
			break;
		}
	}
}


void CWindow::ComTurn()
{
	//bestx,best为当前最佳位置;
	int bestx,besty;

	BestPosition(bestx,besty);
	board[bestx][besty] = ComputerBall;
	if(m_pclastpos.x!=-1 && m_pclastpos.y!=-1)//画前一棋子
	{
		if(!m_bwfirst)
			DrawBlackChess(m_pclastpos.x,m_pclastpos.y);
		else
			DrawWhiteChess(m_pclastpos.x,m_pclastpos.y);
	}

	if(!m_bwfirst)
		DrawNowBlack(bestx,besty);
	else
		DrawNowWhite(bestx,besty);
	m_pclastpos.x=bestx;
	m_pclastpos.y=besty;
	for(int i=0;i<572;i++)
	{//修改计算机下子后,棋盘的变化状况
		if(ctable[bestx][besty][i] && win[1][i]!=7)
			win[1][i]++;
		if(ptable[bestx][besty][i])
		{
			ptable[bestx][besty][i]=false;
			win[0][i]=7;
		}
	}
	computer=false;
	player=true;
}

void CWindow::BestPosition(int& bestx,int& besty)
{
	
	int i,j;//i,j是玩家能下的各种位置;
	int pi,pj;//pi,pj是计算机能下的各种位置;
	int ptemp,ctemp;
	int pscore=10,cscore=-10000;//cscore计算机的得分,pscore玩家的得分
	int ctempboard[15][15],ptempboard[15][15];
	
	int m,n,temp1[20],temp2[20];//暂存第一步搜索的信息
	if(start)//游戏刚开始
	{
		if(board[7][7] == NoBall)
		{
			bestx=7;
			besty=7;
		}
		else
		{
			bestx=8;
			besty=8;
		}
		start = false;
	}
	else
	{//寻找最佳位置
		GetBoard(ctempboard,board);
		while(SearchBlank(i,j,ctempboard))
		{
			n=0;
		//	pscore=10;
			GetBoard(ptempboard,board);
			ctempboard[i][j]=3;//标记已被查找
			ctemp=GiveScore(1,i,j);
			for(m=0;m<572;m++)
			{//暂时更改玩家信息
				if(ptable[i][j][m])
				{
					temp1[n]=m;
					ptable[i][j][m]=false;
					temp2[n]=win[0][m];
					win[0][m]=7;
					n++;
				}
			}
			ptempboard[i][j] = 3;  //1
		
			pi=i;
			pj=j;
			while(SearchBlank(i,j,ptempboard))
			{
				ptempboard[i][j]=3;//标记已被查找
				ptemp=GiveScore(0,i,j);
				if(pscore>ptemp)////此时为玩家下子,运用极小极大法时应选取最小值
					pscore=ptemp;
			}
			for(m=0;m<n;m++)
			{//恢复玩家信息
				ptable[pi][pj][temp1[m]]=true;
				win[0][temp1[m]]=temp2[m];
			}
			if(ctemp+pscore>cscore)//此时为计算机下子,运用极小极大法时应选取最最大值
			{
				cscore=ctemp+pscore;
				bestx=pi;
				besty=pj;
			}
		}
	}
}


void CWindow::GetBoard(int tempboard[][15], int nowboard[][15])
{
	int i,j;
	for(i=0;i<15;i++)
		for(j=0;j<15;j++)
			tempboard[i][j] = nowboard[i][j];
}

bool CWindow::SearchBlank(int &i, int &j, int nowboard[][15])
{
	int x,y;
	for(x=0;x<15;x++)
		for(y=0;y<15;y++)
		{
			if( nowboard[x][y] == NoBall)
			{
				i=x;
				j=y;
				return true;
			}
		}
    return false;
}


int CWindow::GiveScore(int type, int x, int y)
{
	int i,score=0;
	for(i=0;i<572;i++)
	{
		if(type==1)//计算机下
		{
			if(ctable[x][y][i])
			{
				switch(win[1][i])
				{
				case 1:
					score+=5;
					break;
				case 2:
					score+=50;
					break;
				case 3:
					score+=100;
					break;
				case 4:
					score+=10000;
					break;
                default:
					break;
				}
			}
		}
		else//玩家下
		{
			if(ptable[x][y][i])
			{
				switch(win[0][i])
				{
				case 1:
					score-=5;
					break;
			    case 2:
				    score-=50;
				    break;
			    case 3:
				    score-=500;
				    break;
			    case 4:
				    score-=5000;
					break;
			    default:
				break;
			}
			}
		}
	}
	return score;
}

void CWindow::DrawBlackChess(int x, int y)
{
	HDC		hdc = NULL,	hdcMem = NULL;
    hdc = ::GetDC( _hWnd );//创建屏幕客户区相对应的设备描述表
	hdcMem = ::CreateCompatibleDC( hdc );//创建内存设备描述表
	::SelectObject( hdcMem, m_hblack );//把位图m_hblacki选入内存设备描述表
	::BitBlt(hdc,
			24+x*36-x-18,
			25+y*36-y-18,
			33,
			33,
			hdcMem,
			0,
			0,
			MERGEPAINT );//把内存设备表中的图像传送到屏幕显示
	::SelectObject( hdcMem, m_hblackchess );
	::BitBlt(hdc,
			24+x*36-x-18,
			25+y*36-y-18,
			33,
			33,
			hdcMem,
			0,
			0,
			SRCAND );	
				
	::ReleaseDC( _hWnd, hdc );
	::DeleteDC( hdcMem );
}


void CWindow::DrawWhiteChess(int x, int y)
{
	HDC		hdc = NULL,	hdcMem = NULL;
    hdc = ::GetDC( _hWnd );//创建屏幕客户区相对应的设备描述表
	hdcMem = ::CreateCompatibleDC( hdc );//创建内存设备描述表
	::SelectObject( hdcMem, m_hblack );//把位图m_hblacki选入内存设备描述表
	::BitBlt(hdc,
			24+x*36-x-18,
			25+y*36-y-18,
			33,
			33,
			hdcMem,
			0,
			0,
			MERGEPAINT );//把内存设备表中的图像传送到屏幕显示
	::SelectObject( hdcMem, m_hwhitechess );
	::BitBlt(hdc,
			24+x*36-x-18,
			25+y*36-y-18,
			33,
			33,
			hdcMem,
			0,
			0,
			SRCAND );	
				
	::ReleaseDC( _hWnd, hdc );
	::DeleteDC( hdcMem );
}


void CWindow::DrawNowBlack(int x,int y)
{//画当前的黑子
	HDC		hdc = NULL,	hdcMem = NULL;
    hdc = ::GetDC( _hWnd );//创建屏幕客户区相对应的设备描述表
	hdcMem = ::CreateCompatibleDC( hdc );//创建内存设备描述表
	::SelectObject( hdcMem, m_hblack );//把位图m_hblacki选入内存设备描述表
	::BitBlt(hdc,
			24+x*36-x-18,
			25+y*36-y-18,
			33,
			33,
			hdcMem,
			0,
			0,
			MERGEPAINT );//把内存设备表中的图像传送到屏幕显示
	::SelectObject( hdcMem, m_hlastblackchess );
	::BitBlt(hdc,
			24+x*36-x-18,
			25+y*36-y-18,
			33,
			33,
			hdcMem,
			0,
			0,
			SRCAND );	
				
	::ReleaseDC( _hWnd, hdc );
	::DeleteDC( hdcMem );
}

void CWindow::DrawNowWhite(int x,int y)
{//画当前的白子
	HDC		hdc = NULL,	hdcMem = NULL;
    hdc = ::GetDC( _hWnd );//创建屏幕客户区相对应的设备描述表
	hdcMem = ::CreateCompatibleDC( hdc );//创建内存设备描述表
	::SelectObject( hdcMem, m_hblack );//把位图m_hblacki选入内存设备描述表
	::BitBlt(hdc,
			24+x*36-x-18,
			25+y*36-y-18,
			33,
			33,
			hdcMem,
			0,
			0,
			MERGEPAINT );//把内存设备表中的图像传送到屏幕显示
	::SelectObject( hdcMem, m_hlastwhitechess );
	::BitBlt(hdc,
			24+x*36-x-18,
			25+y*36-y-18,
			33,
			33,
			hdcMem,
			0,
			0,
			SRCAND );	
				
	::ReleaseDC( _hWnd, hdc );
	::DeleteDC( hdcMem );
}


void CWindow::OnPaint() 
{

	HDC		hdc = NULL,	hdcMem = NULL;
	PAINTSTRUCT	ps;

	hdc = ::BeginPaint( _hWnd, & ps );
	hdcMem = ::CreateCompatibleDC( hdc );
	::SelectObject( hdcMem, m_hboard );
	::BitBlt(hdc,
			0,
			0,
			600,
			537,
			hdcMem,
			0,
			0,
			SRCCOPY );

	for(int i=0;i<15;i++)
		for(int j=0;j<15;j++)
		{
			//玩家的棋子
			if(board[i][j] == PlayerBall)
			{
				if(m_pplastpos.x==i && m_pplastpos.y==j)//玩家走的前一步棋
				{
                   	if(!m_bwfirst)  //电脑先走
		                DrawNowWhite(m_pplastpos.x,m_pplastpos.y);
	                else  //玩家先走
		                DrawNowBlack(m_pplastpos.x,m_pplastpos.y);
					continue;
				}

             	if(!m_bwfirst)
					DrawWhiteChess(i,j);
	            else
		            DrawBlackChess(i,j);
			}
			
			//计算机的棋子
			if(board[i][j] == ComputerBall)
			{
				if(m_pclastpos.x==i&&m_pclastpos.y==j)
				{
                   	if(!m_bwfirst)
		                DrawNowBlack(m_pclastpos.x,m_pclastpos.y);
	                else
		                DrawNowWhite(m_pclastpos.x,m_pclastpos.y);
					continue;
				}

             	if(!m_bwfirst)
					DrawBlackChess(i,j);
	            else
		            DrawWhiteChess(i,j);
			}
		}
    
		::DeleteDC( hdcMem );
		::EndPaint( _hWnd, & ps );

//	dc.Draw3dRect(0,0,537,537,,RGB(0,0,0));
		RECT rect;
		rect.left = 0;
		rect.top = 0;
		rect.right = 537;
		rect.bottom = 537;
		FillRect(hdc,&rect,(HBRUSH)RGB(0,0,0));


}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -