📄 cwindow.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 + -