📄 mineview.cpp
字号:
// MineView.cpp : implementation of the CMineView class
//
#include "stdafx.h"
#include "Mine.h"
#include "MineDoc.h"
#include "MineView.h"
#include "CustomDlg.h"
#include "WinDlg.h"
#include "RecordDlg.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
enum { MINE = 10, CROSS, EXPLODE, MARK, FLAG, NONE };
enum { PRESSED, WIN, ANGRY, SURPRISE, SMILE };
enum { BASIC, INTERMEDIATE, EXPERT, CUSTOM };
int xmove[] = { -1, 0, 1, -1, 1, -1, 0, 1 };
int ymove[] = { -1, -1, -1, 0, 0, 1, 1, 1 };
TCHAR szSection[] = L"扫雷";
/////////////////////////////////////////////////////////////////////////////
// CMineView
IMPLEMENT_DYNCREATE(CMineView, CView)
BEGIN_MESSAGE_MAP(CMineView, CView)
//{{AFX_MSG_MAP(CMineView)
ON_WM_PAINT()
ON_COMMAND(ID_GAME_NEW, OnGameNew)
ON_WM_CREATE()
ON_WM_LBUTTONDOWN()
ON_WM_LBUTTONUP()
ON_WM_MOUSEMOVE()
ON_WM_TIMER()
ON_COMMAND(ID_GAME_CUSTOMIZE, OnGameCustomize)
ON_COMMAND(ID_GAME_MARK, OnGameMark)
ON_UPDATE_COMMAND_UI(ID_GAME_MARK, OnUpdateGameMark)
ON_COMMAND(ID_GAME_RECORD, OnGameRecord)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CMineView construction/destruction
CMineView::CMineView()
{
srand( GetTickCount() );
m_bmCells.LoadBitmap( IDB_CELLS );
m_bmFaces.LoadBitmap( IDB_FACES );
m_bmNumber.LoadBitmap( IDB_NUM );
m_level = AfxGetApp()->GetProfileInt( szSection, L"Difficulty", 0 );
if( m_level >= 3 ) // customize
{
m_height = AfxGetApp()->GetProfileInt( szSection, L"Height", 8 );
m_width = AfxGetApp()->GetProfileInt( szSection, L"Width", 8 );
m_nMines = AfxGetApp()->GetProfileInt( szSection, L"Mines", 10 );
}
m_bMark = AfxGetApp()->GetProfileInt( szSection, L"Mark", 1 );
for( int i = 0; i < 3; i ++ )
{
CString strEntry;
strEntry.Format( L"Time%d", i + 1 );
m_recordTime[i] = AfxGetApp()->GetProfileInt( szSection, strEntry, 999 );
strEntry.Format( L"Name%d", i + 1 );
m_recordName[i] = AfxGetApp()->GetProfileString( szSection, strEntry, L"匿名" );
}
}
CMineView::~CMineView()
{
AfxGetApp()->WriteProfileInt( szSection, L"Difficulty", m_level );
AfxGetApp()->WriteProfileInt( szSection, L"Height", m_height );
AfxGetApp()->WriteProfileInt( szSection, L"Width", m_width );
AfxGetApp()->WriteProfileInt( szSection, L"Mines", m_nMines );
AfxGetApp()->WriteProfileInt( szSection, L"Mark", m_bMark );
for( int i = 0; i < 3; i ++ )
{
CString strEntry;
strEntry.Format( L"Time%d", i + 1 );
AfxGetApp()->WriteProfileInt( szSection, strEntry, m_recordTime[i] );
strEntry.Format( L"Name%d", i + 1 );
AfxGetApp()->WriteProfileString( szSection, strEntry, m_recordName[i] );
}
}
BOOL CMineView::PreCreateWindow(CREATESTRUCT& cs)
{
// TODO: Modify the Window class or styles here by modifying
// the CREATESTRUCT cs
return CView::PreCreateWindow(cs);
}
/////////////////////////////////////////////////////////////////////////////
// CMineView drawing
void CMineView::OnDraw(CDC* pDC)
{
CMineDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
// TODO: add draw code for native data here
}
/////////////////////////////////////////////////////////////////////////////
// CMineView diagnostics
#ifdef _DEBUG
void CMineView::AssertValid() const
{
CView::AssertValid();
}
void CMineView::Dump(CDumpContext& dc) const
{
CView::Dump(dc);
}
CMineDoc* CMineView::GetDocument() // non-debug version is inline
{
ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CMineDoc)));
return (CMineDoc*)m_pDocument;
}
#endif //_DEBUG
/////////////////////////////////////////////////////////////////////////////
// CMineView message handlers
void CMineView::DrawFrame( CDC *pDC )
{
CRect rc;
GetClientRect( &rc );
int w = rc.Width() - 1;
int h = rc.Height() - 1;
CPen penDKGray;
penDKGray.CreatePen( PS_SOLID, 1, RGB(127,127,127) );
pDC->FillSolidRect( 0, 0, w, 55, RGB(191,191,191) );
pDC->FillSolidRect( CRect(0,55,12,h-12), RGB(191,191,191) );
pDC->FillSolidRect( CRect(0,h-12,w,h), RGB(191,191,191) );
pDC->FillSolidRect( CRect(w-11,55,w,h-12), RGB(191,191,191) );
CPen *ppenOld = (CPen *)(pDC->SelectStockObject( WHITE_PEN ));
pDC->MoveTo( w-1, 0 );
pDC->LineTo( 0, 0 );
pDC->LineTo( 0, h );
pDC->MoveTo( w-2, 1 );
pDC->LineTo( 1, 1 );
pDC->LineTo( 1, h-1 );
pDC->MoveTo( w-3, 2 );
pDC->LineTo( 2, 2 );
pDC->LineTo( 2, h-2 );
pDC->MoveTo( w-9, 10 );
pDC->LineTo( w-9, 45 );
pDC->LineTo( 9, 45 );
pDC->MoveTo( w-10, 11 );
pDC->LineTo( w-10, 44 );
pDC->LineTo( 10, 44 );
pDC->MoveTo( w-9, 53 );
pDC->LineTo( w-9, h-9 );
pDC->LineTo( 9, h-9 );
pDC->MoveTo( w-10, 54 );
pDC->LineTo( w-10, h-10 );
pDC->LineTo( 10, h-10 );
pDC->MoveTo( w-11, 55 );
pDC->LineTo( w-11, h-11 );
pDC->LineTo( 11, h-11 );
pDC->SelectObject( &penDKGray );
pDC->MoveTo( w, 1 );
pDC->LineTo( w, h );
pDC->LineTo( 1, h );
pDC->MoveTo( w-1, 2 );
pDC->LineTo( w-1, h-1 );
pDC->LineTo( 2, h-1 );
pDC->MoveTo( w-2, 3 );
pDC->LineTo( w-2, h-2 );
pDC->LineTo( 3, h-2 );
pDC->MoveTo( w-10, 9 );
pDC->LineTo( 9, 9 );
pDC->LineTo( 9, 45 );
pDC->MoveTo( w-11, 10 );
pDC->LineTo( 10, 10 );
pDC->LineTo( 10, 44 );
pDC->MoveTo( w-10, 52 );
pDC->LineTo( 9, 52 );
pDC->LineTo( 9, h-9 );
pDC->MoveTo( w-11, 53 );
pDC->LineTo( 10, 53 );
pDC->LineTo( 10, h-10 );
pDC->MoveTo( w-12, 54 );
pDC->LineTo( 11, 54 );
pDC->LineTo( 11, h-11 );
pDC->SelectObject( ppenOld );
}
void CMineView::DrawCell( CDC *pDC, int row, int col, int cell )
{
CDC dcMem;
dcMem.CreateCompatibleDC( pDC );
CBitmap *pbmOld = (CBitmap *)(dcMem.SelectObject(&m_bmCells));
if( cell == -1 )
cell = m_board[row][col];
pDC->BitBlt( 12+col*16, 55+row*16, 16, 16, &dcMem,
0, (15-cell)*16, SRCCOPY );
dcMem.SelectObject( pbmOld );
}
void CMineView::DrawAdjacentCells( CDC *pDC, int row, int col, int cell )
{
for( int i = 0; i < 8; i ++ )
{
int nextrow = row + ymove[i];
int nextcol = col + xmove[i];
if( InBound(nextrow, nextcol) &&
m_board[nextrow][nextcol] == NONE )
DrawCell( pDC, nextrow, nextcol, cell );
}
if( m_board[row][col] == NONE )
DrawCell( pDC, row, col, cell );
}
void CMineView::DrawBoard( CDC *pDC )
{
CDC dcMem;
dcMem.CreateCompatibleDC( pDC );
CBitmap *pbmOld = (CBitmap *)(dcMem.SelectObject(&m_bmCells));
for( int row = 0; row < m_height; row ++ )
for( int col = 0; col < m_width; col ++ )
{
pDC->BitBlt( 12+col*16, 55+row*16, 16, 16, &dcMem,
0, (15-m_board[row][col])*16, SRCCOPY );
}
dcMem.SelectObject( pbmOld );
}
void CMineView::DrawButton( CDC *pDC, int face )
{
CRect rc;
GetClientRect( &rc );
CDC dcMem;
dcMem.CreateCompatibleDC( pDC );
CBitmap *pbmOld = (CBitmap *)(dcMem.SelectObject(&m_bmFaces));
pDC->BitBlt( m_rcButton.left, m_rcButton.top, 24, 24,
&dcMem, 0, face*24, SRCCOPY );
dcMem.SelectObject( pbmOld );
}
void CMineView::DrawLCD( CDC *pDC, int x, int y, int num )
{
CDC dcMem;
dcMem.CreateCompatibleDC( pDC );
CBitmap *pbmOld = (CBitmap *)(dcMem.SelectObject(&m_bmNumber));
char buf[4];
sprintf( buf, "%03d", num );
for( int i = 0; i < 3; i ++ )
{
if( buf[i] == '-' )
pDC->BitBlt( x, y, 13, 23, &dcMem, 0, 0, SRCCOPY );
else
pDC->BitBlt( x, y, 13, 23, &dcMem, 0, (11-buf[i]+'0')*23, SRCCOPY );
x += 13;
}
dcMem.SelectObject( pbmOld );
}
BOOL CMineView::InBound( int row, int col )
{
return (row >= 0 && row < m_height &&
col >= 0 && col < m_width);
}
void CMineView::OnPaint()
{
CPaintDC dc(this); // device context for painting
CDC dcMem;
dcMem.CreateCompatibleDC( &dc );
CRect rc;
GetClientRect( &rc );
CBitmap bm;
bm.CreateCompatibleBitmap( &dc, rc.Width(), rc.Height() );
CBitmap *pbmOld = (CBitmap *)(dcMem.SelectObject(&bm));
DrawFrame( &dcMem );
DrawBoard( &dcMem );
DrawLCD( &dcMem, 17, 16, m_nMinesLeft );
DrawLCD( &dcMem, rc.Width()-57, 16, m_time );
if( m_gameState == GS_GAMEOVER )
DrawButton( &dcMem, ANGRY );
else if( m_gameState == GS_ACTIVE )
DrawButton( &dcMem, SMILE );
else
DrawButton( &dcMem, WIN );
dc.BitBlt( 0, 0, rc.Width(), rc.Height(), &dcMem, 0, 0, SRCCOPY );
dcMem.SelectObject( pbmOld );
}
void CMineView::OnGameNew()
{
KillTimer( 1 );
m_gameState = GS_ACTIVE;
switch( m_level )
{
case BASIC:
m_width = 8;
m_height = 8;
m_nMines = 10;
break;
case INTERMEDIATE:
m_width = 16;
m_height = 16;
m_nMines = 40;
break;
case EXPERT:
m_width = 30;
m_height = 16;
m_nMines = 99;
break;
}
m_nMinesLeft = m_nMines;
m_nDug = 0;
for( int i = 0; i < m_height; i ++ )
for( int j = 0; j < m_width; j ++ )
{
m_mines[i][j] = 0;
m_board[i][j] = NONE;
}
for( i = 0; i < m_nMines; )
{
int row = rand() % m_height;
int col = rand() % m_width;
if( m_mines[row][col] == 0 )
{
m_mines[row][col] = 9;
i ++;
}
}
for( int row = 0; row < m_height; row ++ )
for( int col = 0; col < m_width; col ++ )
{
if( m_mines[row][col] == 0 )
{
for( i = 0; i < 8; i ++ )
{
int nextrow = row + ymove[i];
int nextcol = col + xmove[i];
if( InBound(nextrow, nextcol) &&
m_mines[nextrow][nextcol] == 9 )
m_mines[row][col] ++;
}
}
}
// AfxGetMainWnd()->SetWindowPos( NULL, 0, 0, 30+16*m_width,
// 110+16*m_height, SWP_NOMOVE | SWP_NOZORDER );
CRect rc;
GetClientRect( &rc );
m_rcButton.left = (rc.Width()-24)/2;
m_rcButton.top = 16;
m_rcButton.right = m_rcButton.left + 24;
m_rcButton.bottom = m_rcButton.top + 24;
m_bButtonPressed = FALSE;
m_lastrow = -1;
m_time = 0;
m_bFirst = TRUE;
Invalidate();
}
int CMineView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CView::OnCreate(lpCreateStruct) == -1)
return -1;
OnGameNew();
return 0;
}
void CMineView::GameOver( int row, int col )
{
for( int i = 0; i < m_height; i ++ )
for( int j = 0; j < m_width; j ++ )
{
if( m_mines[i][j] == 9 )
{
if( m_board[i][j] != FLAG )
m_board[i][j] = MINE;
}
else if( m_board[i][j] == FLAG )
m_board[i][j] = CROSS;
}
m_board[row][col] = EXPLODE;
m_gameState = GS_GAMEOVER;
KillTimer( 1 );
Invalidate();
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -