📄 minecrackdlg.cpp
字号:
if ( m_nWidth == 30 && m_nHeight == 16 )
m_nMineNum = 99;
else if ( m_nWidth == 16 && m_nHeight == 16 )
m_nMineNum = 40;
else if ( m_nWidth == 9 && m_nHeight == 9 )
m_nMineNum = 10;
else{
MessageBox("本程序不支持自定义雷区!", NULL, MB_OK | MB_ICONINFORMATION);
return;
}
}
if (m_map) {
delete m_map;
m_map = NULL;
}
m_map = new BYTE[ m_nWidth*m_nHeight ];
ZeroMemory(m_map, m_nWidth*m_nHeight);
::PostMessage(hWinMineWnd,WM_KEYDOWN,VK_F2,0);
m_nMineCurNum = 0;
m_bStart = TRUE;
m_hook.StartMouseHook( GetSafeHwnd() );
}
void CMineCrackDlg::OnBtstart()
{
// TODO: Add your control notification handler code here
StartGame();
}
BOOL CMineCrackDlg::ScanTheMap()
{
int i, j, ret;
CPoint pt;
BOOL finish = FALSE;
for (i=0; i<m_nHeight; i++)
{
for(j=0; j<m_nWidth; j++)
{
if (m_map[ i*m_nWidth + j ] != 0) continue;
pt = CPoint( 12 + j*BMPWIDTH, 55 + i*BMPHEIGHT + 7 ); //坐标从上至下;
ret = GetColorSample(pt);
switch(ret)
{
case 0: m_map[ i*m_nWidth + j ] = NOMINE; break;
case 1: m_map[ i*m_nWidth + j ] = NEIGHBOR_1; break;
case 2: m_map[ i*m_nWidth + j ] = NEIGHBOR_2; break;
case 3: m_map[ i*m_nWidth + j ] = NEIGHBOR_3; break;
case 4: m_map[ i*m_nWidth + j ] = NEIGHBOR_4; break;
case 5: m_map[ i*m_nWidth + j ] = NEIGHBOR_5; break;
case 6: m_map[ i*m_nWidth + j ] = NEIGHBOR_6; break;
case 7: m_map[ i*m_nWidth + j ] = NEIGHBOR_7; break;
case 8: m_map[ i*m_nWidth + j ] = NEIGHBOR_8; break;
case 9: m_map[ i*m_nWidth + j ] = NOMINE; break;
case 10: finish = TRUE; break;
case 11: finish = TRUE; break;
case 12: finish = TRUE; break;
case 13: m_map[ i*m_nWidth + j ] = UNKNOW; break;
case 14: m_map[ i*m_nWidth + j ] = ISMINE; break;
case 15: m_map[ i*m_nWidth + j ] = UNKNOW; break;
}
}
}
if ( finish ) return FALSE;
else return TRUE;
}
BOOL CMineCrackDlg::ScanTheMap98()
{
return FALSE;
}
int CMineCrackDlg::GetColorSample(CPoint pt)
{
BYTE ptrColor[8];
COLORREF colorref1,colorref2;
int i;
HDC hDC = ::GetDC(NULL);
memset(ptrColor, 0, 8);
::ClientToScreen(hWinMineWnd,&pt);
for(i=0; i<8; i++)
{
colorref1=::GetPixel(hDC, pt.x+i*2, pt.y);
colorref2=::GetPixel(hDC, pt.x+i*2+1, pt.y);
BYTE tmp1 = Color256To16(colorref1);
BYTE tmp2 = Color256To16(colorref2);
ptrColor[i] = tmp1<<4 | tmp2;
}
::ReleaseDC(NULL,hDC);
for(i=0; i<16; i++)
if ( m_ColorSample[i][0] == ptrColor[0] &&
m_ColorSample[i][1] == ptrColor[1] &&
m_ColorSample[i][2] == ptrColor[2] &&
m_ColorSample[i][3] == ptrColor[3] &&
m_ColorSample[i][4] == ptrColor[4] &&
m_ColorSample[i][5] == ptrColor[5] &&
m_ColorSample[i][6] == ptrColor[6] &&
m_ColorSample[i][7] == ptrColor[7] )
{
return i; //返回匹配值
}
return -1; //没有匹配
}
BYTE CMineCrackDlg::Color256To16(COLORREF colorref)
{
BYTE ret;
switch( colorref )
{
case RGB( 0, 0, 0): ret = 0x00; break;
case RGB(128, 0, 0): ret = 0x01; break;
case RGB( 0, 128, 0): ret = 0x02; break;
case RGB(128, 128, 0): ret = 0x03; break;
case RGB( 0, 0, 128): ret = 0x04; break;
case RGB(128, 0, 128): ret = 0x05; break;
case RGB( 0, 128, 128): ret = 0x06; break;
case RGB(128, 128, 128): ret = 0x07; break;
case RGB(192, 192, 192): ret = 0x08; break;
case RGB(255, 0, 0): ret = 0x09; break;
case RGB( 0, 255, 0): ret = 0x0A; break;
case RGB(255, 255, 0): ret = 0x0B; break;
case RGB( 0, 0, 255): ret = 0x0C; break;
case RGB(255, 0, 255): ret = 0x0D; break;
case RGB( 0, 255, 255): ret = 0x0E; break;
case RGB(255, 255, 255): ret = 0x0F; break;
}
return ret;
}
BOOL CMineCrackDlg::MakeDecision(BOOL * bSign, BOOL * bStatus)
{
int i, j, k, curMineCount = 0;
for ( i=0; i<m_nHeight; i++ )
{
for ( j=0; j<m_nWidth; j++ )
{
if ( m_map[i*m_nWidth + j] == ISMINE ) { curMineCount++; continue; }
if ( m_map[i*m_nWidth + j] < NEIGHBOR_1 || m_map[i*m_nWidth + j] > NEIGHBOR_8 ) continue;
//计算数字方格(i,j)周围的8个方格中,有多少个未标记的方格;
CArray < CPoint, CPoint > ArrayOfCenPt;
int isMineNumOfCenPt = 0;
LookAroundDot(i, j, &ArrayOfCenPt, &isMineNumOfCenPt);
if ( ! ArrayOfCenPt.GetSize() ) continue;
//如果方格(i,j)周围的未标记方格数 = 方格(i,j)本身显示雷数值 - 周围已标记是雷的方格数
if ( ArrayOfCenPt.GetSize() == m_map[i*m_nWidth + j] - isMineNumOfCenPt )
{
for ( k=0; k<ArrayOfCenPt.GetSize(); k++ )
{
//从数组中将点取出,给每个点标记“是雷”的标志
::PostMessage( hWinMineWnd, WM_RBUTTONDOWN, MK_RBUTTON,
MAKELPARAM(12+ArrayOfCenPt[k].y*BMPWIDTH+8, 55+ArrayOfCenPt[k].x*BMPHEIGHT+8) );
m_map[ ArrayOfCenPt[k].x * m_nWidth + ArrayOfCenPt[k].y ] = ISMINE;
}
( *bSign ) = TRUE;
}
if ( m_map[i*m_nWidth + j] == isMineNumOfCenPt )
{
::PostMessage( hWinMineWnd, WM_LBUTTONDOWN, MK_LBUTTON | MK_RBUTTON,
MAKELPARAM(12+j*BMPWIDTH+8, 55+i*BMPHEIGHT+8) );
::PostMessage( hWinMineWnd, WM_RBUTTONUP, 0,
MAKELPARAM(12+j*BMPWIDTH+8, 55+i*BMPHEIGHT+8) );
( *bStatus ) = TRUE;
}
}
}
if ( m_nMineNum == curMineCount )
{
for ( i=0; i<m_nHeight; i++ )
{
for ( j=0; j<m_nWidth; j++ )
{
if ( m_map[i*m_nWidth + j] == UNKNOW )
{
::PostMessage( hWinMineWnd, WM_LBUTTONDOWN, MK_LBUTTON,
MAKELPARAM(12+j*BMPWIDTH+8, 55+i*BMPHEIGHT+8) );
::PostMessage( hWinMineWnd, WM_LBUTTONUP, 0,
MAKELPARAM(12+j*BMPWIDTH+8, 55+i*BMPHEIGHT+8) );
}
}
}
return TRUE;
} else m_nMineCurNum = curMineCount;
return FALSE;
}
//在普通决策(bSign == FALSE && bStatus == FALSE)条件下调用高级决策
BOOL CMineCrackDlg::AdvanceDecision(BOOL * bSign, BOOL * bStatus)
{
int i, j, i1, j1, k, curMineCount = 0;
for ( i=0; i<m_nHeight; i++ )
{
for ( j=0; j<m_nWidth; j++ )
{
if ( m_map[i*m_nWidth + j] < NEIGHBOR_1 || m_map[i*m_nWidth + j] > NEIGHBOR_8 ) continue;
//计算方格(i, j)周围3×3区域中有多少个雷区和未标示区
CArray < CPoint, CPoint > ArrayOfCenPt;
int isMineNumOfCenPt = 0;
LookAroundDot(i, j, &ArrayOfCenPt, &isMineNumOfCenPt);
if ( ArrayOfCenPt.GetSize() == 0 ) continue; //周围没有未标示区
ASSERT( ArrayOfCenPt.GetSize() != 1 ); //在高级决策下这种情况不存在
if ( ArrayOfCenPt.GetSize() == 2 ) //如果周围只有两个未标示区,则无法进行高级决策
{
ASSERT( m_map[i*m_nWidth + j] == isMineNumOfCenPt + 1 );
continue;
}
/*……得到了方格(i, j)周围已标示雷区点的个数isMineNumOfCenPt和
未标示区点的数组ArrayOfCenPt后,对方格(i, j)周围5×5区域进行扫描……*/
int xx1, xx2, yy1, yy2;
if ( i-2 >= 0 ) xx1 = i-2;
else if ( i-1 >= 0 ) xx1 = i-1;
else xx1 = i;
if ( i+2 <= m_nHeight-1 ) xx2 = i+2;
else if ( i+1 <= m_nHeight-1 ) xx2 = i+1;
else xx2 = i;
if ( j-2 >= 0 ) yy1 = j-2;
else if ( j-1 >= 0 ) yy1 = j-1;
else yy1 = j;
if ( j+2 <= m_nWidth-1 ) yy2 = j+2;
else if ( j+1 <= m_nWidth-1 ) yy2 = j+1;
else yy2 = j;
for ( i1=xx1; i1<=xx2; i1++ )
{
for ( j1=yy1; j1<=yy2; j1++ )
{
//对方格(i, j)自身不考察
if ( i1==i && j1==j ) continue;
//对方格(i, j)周围5×5区域中标示为非数字方块不考察
if ( m_map[i1*m_nWidth + j1] < NEIGHBOR_1 || m_map[i1*m_nWidth + j1] > NEIGHBOR_8 ) continue;
CArray < CPoint, CPoint > ArrayOfArdPt;
int isMineNumOfArdPt = 0;
LookAroundDot( i1, j1, &ArrayOfArdPt, &isMineNumOfArdPt);
if ( !ArrayOfArdPt.GetSize() ) continue; //若该点周围没有未标示方块
CArray < int ,int > indexArray;
BOOL haveOther = FALSE;
for (k=0; k<ArrayOfArdPt.GetSize(); k++)
{
int retindex = LookUpFromArray( &ArrayOfCenPt, ArrayOfArdPt.GetAt(k) );
if ( retindex >= 0 ) indexArray.Add(retindex);
else if ( retindex == -1 ) haveOther = TRUE;
}
if ( !haveOther )
ASSERT( indexArray.GetSize() != 1 ); //等于1的情况在MakeDecision()函数中处理过了
if ( indexArray.GetSize() < 2 ) continue; //若没有或有一个共同的未标示方格
//CommonMineNum:两个点之间公共的未标示区域中包括的雷数
int CommonMineNum = m_map[i1*m_nWidth + j1] - isMineNumOfArdPt;
int leaveUnknowDot = ArrayOfCenPt.GetSize() - indexArray.GetSize();
if ( !leaveUnknowDot ) continue;
if (m_map[i*m_nWidth + j] - isMineNumOfCenPt - CommonMineNum == leaveUnknowDot)
{ //剩下的未标示方格全为雷,标记
for ( k=0; k<ArrayOfCenPt.GetSize(); k++ )
{
int retindex = LookUpFromArray( &ArrayOfArdPt, ArrayOfCenPt.GetAt(k) );
if ( retindex == -1 )
{
::PostMessage( hWinMineWnd, WM_RBUTTONDOWN, MK_RBUTTON,
MAKELPARAM(12+ArrayOfCenPt[k].y*BMPWIDTH+8, 55+ArrayOfCenPt[k].x*BMPHEIGHT+8) );
m_map[ ArrayOfCenPt[k].x * m_nWidth + ArrayOfCenPt[k].y ] = ISMINE;
}
}
( *bSign ) = TRUE;
return TRUE;
}
if (m_map[i*m_nWidth + j] - isMineNumOfCenPt == CommonMineNum && haveOther == FALSE )
{ //剩下的方格全不是雷,点开 ps:haveOther=FALSE,必然事件;haveOther=TRUE,最大可能事件
for ( k=0; k<ArrayOfCenPt.GetSize(); k++ )
{
int retindex = LookUpFromArray( &ArrayOfArdPt, ArrayOfCenPt.GetAt(k) );
if ( retindex == -1 )
{
::PostMessage( hWinMineWnd, WM_LBUTTONDOWN, MK_LBUTTON,
MAKELPARAM(12+ArrayOfCenPt[k].y*BMPWIDTH+8, 55+ArrayOfCenPt[k].x*BMPHEIGHT+8) );
::PostMessage( hWinMineWnd, WM_LBUTTONUP, 0,
MAKELPARAM(12+ArrayOfCenPt[k].y*BMPWIDTH+8, 55+ArrayOfCenPt[k].x*BMPHEIGHT+8) );
}
}
( *bStatus ) = TRUE;
return TRUE;
}
}
}
}
}
return FALSE;
}
void CMineCrackDlg::LookAroundDot(int i, int j, void * ptrarr, int * isMine)
{
CArray < CPoint, CPoint > * ptrArray = ( CArray < CPoint, CPoint > * )ptrarr;
int i1, j1;
for ( i-1>=0 ? i1=i-1 : i1=i; i+1<=m_nHeight-1 ? i1<=i+1 : i1<=i; i1++ )
{
for ( j-1>=0 ? j1=j-1 : j1=j; j+1<=m_nWidth-1 ? j1<=j+1 : j1<=j; j1++ )
{
if ( i1==i && j1==j )
{
ASSERT( m_map[i*m_nWidth + j] != 0 );
continue;
}
if ( !m_map[i1*m_nWidth + j1] )
{
CPoint pt = CPoint(i1, j1);
ptrArray->Add(pt);
}
else if ( m_map[i1*m_nWidth + j1] == ISMINE ) (* isMine)++;
}
}
}
int CMineCrackDlg::LookUpFromArray(const void * ptrarr, CPoint pt)
{
CArray < CPoint, CPoint > * ptrArray = ( CArray < CPoint, CPoint > * )ptrarr;
for ( int i=0; i<ptrArray->GetSize(); i++ )
if ( (* ptrArray)[i] == pt ) return i;
return -1;
}
void CMineCrackDlg::OnBtsweepmine()
{
// TODO: Add your control notification handler code here
if ( ! m_bStart )
{
MessageBox("先点击开始按钮!", NULL, MB_OK | MB_ICONINFORMATION);
return;
}
if(::IsIconic(hWinMineWnd)) ::ShowWindow(hWinMineWnd,SW_SHOWNORMAL);
::BringWindowToTop(hWinMineWnd);
::SetActiveWindow(hWinMineWnd);
BOOL DoScan = TRUE;
while ( TRUE )
{
Sleep(20);
if ( DoScan )
{
if( !ScanTheMap() )
{
m_bStart = FALSE;
ASSERT( m_map !=NULL );
delete m_map;
m_map = NULL;
MessageBox("扫雷失败了,GAME OVER!", NULL, MB_OK | MB_ICONINFORMATION);
break;
}
}
else DoScan = TRUE;
BOOL bSign = FALSE, bStatus = FALSE;
BOOL bSuccess = MakeDecision( & bSign, & bStatus );
if ( bSuccess )
{
m_bStart = FALSE;
ASSERT( m_map !=NULL );
delete m_map;
m_map = NULL;
MessageBox("恭喜啊,扫雷成功了!", NULL, MB_OK | MB_ICONINFORMATION);
break;
}
if ( bSign == FALSE && bStatus == FALSE )
{
BOOL improve = AdvanceDecision( & bSign, & bStatus );
if ( ! improve )
{
MessageBox("算法不能继续了,自己来吧!", NULL, MB_OK | MB_ICONINFORMATION);
::BringWindowToTop(hWinMineWnd);
::SetActiveWindow(hWinMineWnd);
break;
}
}
if ( bStatus ) continue;
if ( bSign ) DoScan = FALSE;
}
}
void CMineCrackDlg::OnOK()
{
// TODO: Add extra validation here
CDialog::OnOK();
}
void CMineCrackDlg::OnCancel()
{
// TODO: Add extra cleanup here
CDialog::OnCancel();
}
void CMineCrackDlg::OnAbout()
{
// TODO: Add your control notification handler code here
CAboutDlg dlg;
dlg.DoModal();
}
BOOL CMineCrackDlg::OnCopyData(CWnd* pWnd, COPYDATASTRUCT* pCopyDataStruct)
{
// TODO: Add your message handler code here and/or call default
static BOOL bDown = FALSE;
MsgMouse * pMsg;
pMsg = (MsgMouse *) (pCopyDataStruct->lpData);
CPoint pt = pMsg->pt;
::ScreenToClient(hWinMineWnd,&pt);
if (pt.x>239 && pt.x<264 && pt.y>15 && pt.y<40 )
{
if ( pMsg->KeyValue == WM_LBUTTONDOWN ) bDown = TRUE;
if ( pMsg->KeyValue == WM_LBUTTONUP && bDown )
{
StartGame();
bDown = FALSE;
}
}
if ( pMsg->KeyValue == WM_LBUTTONUP && bDown ) bDown = FALSE;
return CDialog::OnCopyData(pWnd, pCopyDataStruct);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -