/
avplat
/
Tetris-MFC
Обзор
Документация
Войти
/
avplat
/
Tetris-MFC
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
CTetrisView.cpp
350 строк
12 KB
Андрей Платонов
добавил assert'ов
24 окт 2025, 17:34
24 окт 2025, 17:34
a2ddda2
Код
Авторство
О чём код?
/// @file /// @brief Вкладка с рейтингами игроков /// @copyright Copyright Андрей Платонов, 2025 #include "pch.h" #include <map> #include <utility> #include <vector> #include "framework.h" #include "resource.h" #include "CTetrisView.h" #ifdef _DEBUG #define new DEBUG_NEW #endif BEGIN_MESSAGE_MAP( CTetrisView, CView ) ON_WM_SIZE() ON_WM_DESTROY() END_MESSAGE_MAP() CTetrisView::CTetrisView() : CView() { } BOOL CTetrisView::Create( CWnd* pParentWnd, UINT nID ) { CString strWndClass = AfxRegisterWndClass( 0, AfxGetApp()->LoadStandardCursor( IDC_ARROW ), (HBRUSH)(COLOR_WINDOW + 1) ); CRect rc( 0, 0, 10, 10 ); BOOL res = CView::Create( strWndClass, NULL, WS_CHILDWINDOW | WS_VISIBLE, rc, pParentWnd, nID ); if ( !res ) { return FALSE; } return TRUE; } void CTetrisView::UpdateField( const std::vector< std::vector< int > >& field, BlockType type, BlockDirection dir, int line, int col ) { ASSERT( bitmap.GetSafeHandle() != nullptr ); ASSERT( !field.empty() ); ASSERT( field.size() == fieldRects.size() ); for ( int i = 0; i < field.size(); ++i ) { ASSERT( !field[ i ].empty() ); ASSERT( fieldRects[ i ].size() == field[ i ].size() ); } ASSERT( col >= 0 && col < field[ 0 ].size() && line >= 0 && line < field.size() ); CRect rc; GetClientRect( &rc ); CDC* dc = GetDC(); ASSERT( dc != nullptr ); ASSERT( dc->GetSafeHdc() != nullptr ); CDC memDC; memDC.CreateCompatibleDC( dc ); ReleaseDC( dc ); CBitmap* pOldBitmap = memDC.SelectObject( &bitmap ); DWORD colorBack = GetSysColor( COLOR_WINDOW ); memDC.FillSolidRect( &rc, colorBack ); // рисуем игровое поле for ( int i = 0; i < field.size(); ++i ) { for ( int j = 0; j < field[ i ].size(); ++j ) { if ( field[ i ][ j ] != 0 ) { drawCell( memDC, field[ i ][ j ], i, j ); } } } // рисуем падающий блок if ( type != BlockType::none ) { std::vector< std::pair< int, int > > parts = GetBlocks( type, dir ); ASSERT( parts.size() == 4 ); for ( const auto& p : parts ) { drawCell( memDC, static_cast< int >( type ), line + p.first, col + p.second ); } } ASSERT( pOldBitmap != nullptr ); memDC.SelectObject( pOldBitmap ); Invalidate(); UpdateWindow(); } std::vector< std::pair< int, int > > CTetrisView::GetBlocks( BlockType type, BlockDirection dir ) const { std::vector< std::pair< int, int > > result; switch ( type ) { case BlockType::I: if ( dir == BlockDirection::vertical || dir == BlockDirection::verticalReversed ) { result.push_back( std::make_pair( 0, 0 ) ); result.push_back( std::make_pair( -1, 0 ) ); result.push_back( std::make_pair( -2, 0 ) ); result.push_back( std::make_pair( -3, 0 ) ); } else { result.push_back( std::make_pair( 0, -1 ) ); result.push_back( std::make_pair( 0, 0 ) ); result.push_back( std::make_pair( 0, 1 ) ); result.push_back( std::make_pair( 0, 2 ) ); } break; case BlockType::J: if ( dir == BlockDirection::vertical ) { result.push_back( std::make_pair( 0, 0 ) ); result.push_back( std::make_pair( -1, 0 ) ); result.push_back( std::make_pair( -2, 0 ) ); result.push_back( std::make_pair( -2, -1 ) ); } else if ( dir == BlockDirection::verticalReversed ) { result.push_back( std::make_pair( 0, 0 ) ); result.push_back( std::make_pair( 0, 1 ) ); result.push_back( std::make_pair( -1, 0 ) ); result.push_back( std::make_pair( -2, 0 ) ); } else if ( dir == BlockDirection::horizontal ) { result.push_back( std::make_pair( 0, -1 ) ); result.push_back( std::make_pair( -1, -1 ) ); result.push_back( std::make_pair( -1, 0 ) ); result.push_back( std::make_pair( -1, 1 ) ); } else { result.push_back( std::make_pair( 0, -1 ) ); result.push_back( std::make_pair( 0, 0 ) ); result.push_back( std::make_pair( 0, 1 ) ); result.push_back( std::make_pair( -1, 1 ) ); } break; case BlockType::L: if ( dir == BlockDirection::vertical ) { result.push_back( std::make_pair( 0, 0 ) ); result.push_back( std::make_pair( -1, 0 ) ); result.push_back( std::make_pair( -2, 0 ) ); result.push_back( std::make_pair( -2, 1 ) ); } else if ( dir == BlockDirection::verticalReversed ) { result.push_back( std::make_pair( 0, 0 ) ); result.push_back( std::make_pair( 0, -1 ) ); result.push_back( std::make_pair( -1, 0 ) ); result.push_back( std::make_pair( -2, 0 ) ); } else if ( dir == BlockDirection::horizontal ) { result.push_back( std::make_pair( 0, -1 ) ); result.push_back( std::make_pair( 0, 0 ) ); result.push_back( std::make_pair( 0, 1 ) ); result.push_back( std::make_pair( -1, -1 ) ); } else { result.push_back( std::make_pair( 0, 1 ) ); result.push_back( std::make_pair( -1, -1 ) ); result.push_back( std::make_pair( -1, 0 ) ); result.push_back( std::make_pair( -1, 1 ) ); } break; case BlockType::O: result.push_back( std::make_pair( 0, 0 ) ); result.push_back( std::make_pair( 0, 1 ) ); result.push_back( std::make_pair( -1, 0 ) ); result.push_back( std::make_pair( -1, 1 ) ); break; case BlockType::S: if ( dir == BlockDirection::vertical || dir == BlockDirection::verticalReversed ) { result.push_back( std::make_pair( 0, 0 ) ); result.push_back( std::make_pair( 0, 1 ) ); result.push_back( std::make_pair( -1, 0 ) ); result.push_back( std::make_pair( -1, -1 ) ); } else { result.push_back( std::make_pair( 0, 0 ) ); result.push_back( std::make_pair( -1, 0 ) ); result.push_back( std::make_pair( -1, 1 ) ); result.push_back( std::make_pair( -2, 1 ) ); } break; case BlockType::T: if ( dir == BlockDirection::vertical ) { result.push_back( std::make_pair( 0, -1 ) ); result.push_back( std::make_pair( 0, 0 ) ); result.push_back( std::make_pair( 0, 1 ) ); result.push_back( std::make_pair( -1, 0 ) ); } else if ( dir == BlockDirection::verticalReversed ) { result.push_back( std::make_pair( 0, 0 ) ); result.push_back( std::make_pair( -1, -1 ) ); result.push_back( std::make_pair( -1, 0 ) ); result.push_back( std::make_pair( -1, 1 ) ); } else if ( dir == BlockDirection::horizontal ) { result.push_back( std::make_pair( 0, 0 ) ); result.push_back( std::make_pair( -1, 0 ) ); result.push_back( std::make_pair( -2, 0 ) ); result.push_back( std::make_pair( -1, -1 ) ); } else { result.push_back( std::make_pair( 0, 0 ) ); result.push_back( std::make_pair( -1, 0 ) ); result.push_back( std::make_pair( -2, 0 ) ); result.push_back( std::make_pair( -1, 1 ) ); } break; case BlockType::Z: if ( dir == BlockDirection::vertical || dir == BlockDirection::verticalReversed ) { result.push_back( std::make_pair( 0, -1 ) ); result.push_back( std::make_pair( 0, 0 ) ); result.push_back( std::make_pair( -1, 0 ) ); result.push_back( std::make_pair( -1, 1 ) ); } else { result.push_back( std::make_pair( 0, 0 ) ); result.push_back( std::make_pair( -1, 0 ) ); result.push_back( std::make_pair( -1, -1 ) ); result.push_back( std::make_pair( -2, -1 ) ); } break; default: ASSERT( false ); break; } return result; } void CTetrisView::OnDraw( CDC* pDC ) { ASSERT( pDC != nullptr ); ASSERT( pDC->GetSafeHdc() != nullptr ); ASSERT( bitmap.GetSafeHandle() != nullptr ); CRect rc; GetClientRect( &rc ); CDC memDC; memDC.CreateCompatibleDC( pDC ); CBitmap* pOldBitmap = memDC.SelectObject( &bitmap ); pDC->BitBlt( rc.left, rc.top, rc.Width(), rc.Height(), &memDC, rc.left, rc.top, SRCCOPY ); ASSERT( pOldBitmap != nullptr ); memDC.SelectObject( pOldBitmap ); } void CTetrisView::OnSize( UINT nType, int cx, int cy ) { CView::OnSize( nType, cx, cy ); if ( bitmap.GetSafeHandle() != nullptr ) { bitmap.DeleteObject(); } CDC* dc = GetDC(); ASSERT( dc != nullptr ); ASSERT( dc->GetSafeHdc() != nullptr ); CRect rc( 0, 0, cx, cy ); CDC memDC; memDC.CreateCompatibleDC( dc ); bitmap.CreateCompatibleBitmap( dc, rc.Width(), rc.Height() ); CBitmap* pOldBitmap = memDC.SelectObject( &bitmap ); DWORD colorBack = GetSysColor( COLOR_WINDOW ); memDC.FillSolidRect( &rc, colorBack ); ASSERT( pOldBitmap != nullptr ); memDC.SelectObject( pOldBitmap ); ReleaseDC( dc ); if ( cx > 30 && cy > 50 ) { int szX = cx / 10; int szY = cy / 20; int sz = min( szX, szY ); ASSERT( sz > 0 ); int offX = (cx - sz * 10) / 2; int offY = (cy - sz * 20) / 2; fieldRects.clear(); fieldRects.resize( 20, std::vector< CRect >( 10 ) ); for ( int i = 0; i < 10; i++ ) { for ( int j = 0; j < 20; j++ ) { fieldRects[ 20 - j - 1 ][ i ] = CRect( offX + i * sz, offY + j * sz, offX + (i + 1) * sz - 1, offY + (j + 1) * sz - 1 ); } } } } void CTetrisView::drawCell( CDC& dc, int color, int line, int col ) { // цвета разных типов блоков std::map< int, std::vector< COLORREF > > colors = { { 1, { RGB( 190, 250, 250 ), RGB( 80, 215, 215 ), RGB( 40, 120, 120 ), RGB( 90, 240, 240 ) } }, { 2, { RGB( 180, 180, 250 ), RGB( 25, 0, 215 ), RGB( 10, 0, 120 ), RGB( 30, 0, 240 ) } }, { 3, { RGB( 250, 230, 180), RGB( 210, 150, 15 ), RGB( 115, 80, 5 ), RGB( 230, 165, 15 ) } }, { 4, { RGB( 250, 250, 180 ), RGB( 215, 215, 5 ), RGB( 120, 120, 0 ), RGB( 240, 240, 5 ) } }, { 5, { RGB( 190, 250, 180 ), RGB( 70, 215, 0 ), RGB( 55, 135, 20 ), RGB( 80, 240, 0 ) } }, { 6, { RGB( 225, 180, 250 ), RGB( 140, 10, 215 ), RGB( 75, 5, 120 ), RGB( 155, 15, 240 ) } }, { 7, { RGB( 250, 180, 180 ), RGB( 200, 20, 20 ), RGB( 115, 10, 5 ), RGB( 230, 30, 25 ) } } }; ASSERT( colors.find( color ) != colors.end() ); ASSERT( colors[ color ].size() == 4 ); ASSERT( dc.GetSafeHdc() != nullptr ); CPen pen1( PS_SOLID, 1, colors[ color ][ 0 ] ); CPen pen2( PS_SOLID, 1, colors[ color ][ 1 ] ); CPen pen3( PS_SOLID, 1, colors[ color ][ 2 ] ); CPen* oldPen = dc.SelectObject( &pen1 ); dc.MoveTo( fieldRects[ line ][ col ].left, fieldRects[ line ][ col ].top ); dc.LineTo( fieldRects[ line ][ col ].right, fieldRects[ line ][ col ].top ); dc.MoveTo( fieldRects[ line ][ col ].left + 1, fieldRects[ line ][ col ].top + 1 ); dc.LineTo( fieldRects[ line ][ col ].right - 1, fieldRects[ line ][ col ].top + 1 ); dc.SelectObject( &pen2 ); dc.MoveTo( fieldRects[ line ][ col ].right, fieldRects[ line ][ col ].top ); dc.LineTo( fieldRects[ line ][ col ].right, fieldRects[ line ][ col ].bottom ); dc.MoveTo( fieldRects[ line ][ col ].right - 1, fieldRects[ line ][ col ].top + 1 ); dc.LineTo( fieldRects[ line ][ col ].right - 1, fieldRects[ line ][ col ].bottom - 1 ); dc.SelectObject( &pen3 ); dc.MoveTo( fieldRects[ line ][ col ].right, fieldRects[ line ][ col ].bottom ); dc.LineTo( fieldRects[ line ][ col ].left, fieldRects[ line ][ col ].bottom ); dc.MoveTo( fieldRects[ line ][ col ].right - 1, fieldRects[ line ][ col ].bottom - 1); dc.LineTo( fieldRects[ line ][ col ].left + 1, fieldRects[ line ][ col ].bottom - 1 ); dc.SelectObject( &pen2 ); dc.MoveTo( fieldRects[ line ][ col ].left, fieldRects[ line ][ col ].bottom ); dc.LineTo( fieldRects[ line ][ col ].left, fieldRects[ line ][ col ].top ); dc.MoveTo( fieldRects[ line ][ col ].left + 1, fieldRects[ line ][ col ].bottom - 1 ); dc.LineTo( fieldRects[ line ][ col ].left + 1, fieldRects[ line ][ col ].top + 1 ); dc.SelectObject( oldPen ); CRect rc = fieldRects[ line ][ col ]; rc.DeflateRect( 2, 2, 1, 1 ); dc.FillSolidRect( &rc, colors[ color ][ 3 ] ); }