СПИСОК ИСПОЛЬЗОВАННЫХ ИСТОЧНИКОВ
1) Шлее, М. Qt 4.8. Профессиональное програмирование на С++ / СПб.: БХВ-Петербург, 2012.
2) Qt Documentaion [Электронный ресурс]. – Режим доступа: http://doc.qt.io. – (Дата обращения: 10.11.2015).
3) Франка П. С++: Учебный курс. 2-е изд. – СПБ. Питер, 2012.
4) Эффективное программирование на С++, Эндрю Кениг, 2002.
5) С++ и STL. Справочное руководство, Дэвид Р. Мюссер, 2010.
ПРИЛОЖЕНИЕ 1. ИСХОДНЫЙ КОД ПРОГРАММЫ
TetrisDlg.h
//Дата создания проекта: 2.12.2015
//Разработчики: Наумов Г.М., Сон И.В.
//Версия программы: 1.0
#pragma once
#include "block.h"
class CTetrisDlg : public CDialog
{
public:
CTetrisDlg(CWnd* pParent = NULL);
~CTetrisDlg();
enum
{
IDD = IDD_TETRIS_DIALOG,
ROW = 20, //размерность строк
COL = 10, //размерность столбцов
WIDTH = COL << 5, //ширина
HEIGHT = ROW << 5 //высота
};
protected:
BOOL PreTranslateMessage(MSG *pMsg);
protected:
HICON m_hIcon;
private:
CMenu m_menu; //Меню
CImage m_bk;
CImage m_block; //Сегмент Блока
CImage m_window;
CImage m_gameover; //Окончание игры
CDC m_memDC;
CBitmap m_memBmp; //Картинка блоков
CClientDC *m_pDC;
BYTE **m_board; //Поле игры
Block *m_pBlock; //Блок
BYTE m_level; //Сложность
BYTE m_gameParam; //Статус игры
BYTE m_nextColor; //Цвет фигуры
UINT m_lines; //Отдельная строка игры
UINT m_score; //Количество набранных очков за игру
BYTE m_mouseOver; //Проверка координат мыши
void Update();
void AdjustFrame();//Размер окна
void Initialize();//Инициализация
void RedrawBkgnd(RECT rect); //Отрисовка фона
void DrawText(SHORT x1, SHORT y1, SHORT x2, SHORT y2,
CString &text, UINT format, COLORREF clr);
void SetFontSize(BYTE size); //Установка параметров шрифта
void Play(MCIDEVICEID id); //Старт игры
void UpdateBlock();//Обновление блока
void UpdateWindow();//Обновление окна
void NextRandomBlock();//Следующий случайный блок
BYTE NextRandomColor();//Цвет следующего случайного блока
Block *BlockFromIndex(BYTE i); //Случайный блок
BOOL CheckLine(BYTE row); //Проверка линии
void RemoveLine(BYTE row); //Удаление линии
BOOL IsGameOver(BYTE blockType);
void GameOver();
public:
virtual BOOL OnInitDialog();
afx_msg void OnPaint();//параметры отображения иконки
afx_msg HCURSOR OnQueryDragIcon();
afx_msg void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags); //При нажатии
afx_msg void OnLButtonDown(UINT nFlags, CPoint point); //вниз длительное
afx_msg void OnLButtonUp(UINT nFlags, CPoint point); //вверх длительное
afx_msg void OnMouseMove(UINT nFlags, CPoint point); //по движению
afx_msg UINT OnGetDlgCode();
afx_msg BOOL OnEraseBkgnd(CDC* pDC);
afx_msg void OnTimer(UINT_PTR nIDEvent); //Таймер
afx_msg void OnGameNew();//Новая игра
afx_msg void OnGamePause();//Пауза
afx_msg void OnGameStop();//Остановка игры
afx_msg void OnLevelBeginner();//Начальный уровень
afx_msg void OnLevelIntermediate();//второй уровень
afx_msg void OnLevelAdvanced();//Третий уровень
afx_msg void OnLevelExpert();//Четвертый уровень
afx_msg void OnLevelDevil();//Пятый уровень
afx_msg void OnLevelHell();//последний уровень сложности
afx_msg void OnGameExit();//выход
afx_msg void OnHelpAbout();
DECLARE_MESSAGE_MAP()//обработчик сообщений
};
// CAboutDlg dialog
class CAboutDlg : public CDialog
{
public:
CAboutDlg(CWnd* pParent = NULL) : CDialog(CAboutDlg::IDD, pParent) {}
// Dialog Data
enum { IDD = IDD_ABOUTBOX };
};
TetrisDlg.cpp
//Дата создания проекта: 2.12.2015
//Разработчики: Наумов Г.М., Сон И.В.
//Версия программы: 1.0
#include "stdafx.h" //подключение библиотек
#include "Tetris.h"
#include "TetrisDlg.h"
#include <vector>
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
CTetrisDlg::CTetrisDlg(CWnd* pParent) //конструктор
: CDialog(CTetrisDlg::IDD, pParent)
{
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
m_bk.Load(_T("res\\003-StarlitSky01.jpg"));
m_block.Load(_T("res\\178-Switch01.png"));
m_window.Load(_T("res\\window.png"));
m_gameover.Load(_T("res\\gameover.png"));
vector<vector<BYTE>> m_board(ROW, vector<Byte>(COL));
m_level = 0;
m_gameParam = 0x08;
m_pBlock = NULL;
}
CTetrisDlg::~CTetrisDlg()//деструктор
{
m_memBmp.DeleteObject();
m_memDC.DeleteDC();
delete m_pDC;
delete m_pBlock;
for(BYTE i = 0; i < ROW; ++i)
{
delete[] m_board[i];
}
delete[] m_board;
}
BEGIN_MESSAGE_MAP(CTetrisDlg, CDialog) //обработчик сообщений
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_WM_KEYDOWN()
ON_WM_LBUTTONDOWN()
ON_WM_LBUTTONUP()
ON_WM_MOUSEMOVE()
ON_WM_GETDLGCODE()
ON_WM_ERASEBKGND()
ON_WM_TIMER()
ON_COMMAND(ID_GAME_NEW, &CTetrisDlg::OnGameNew)
ON_COMMAND(ID_GAME_PAUSE, &CTetrisDlg::OnGamePause)
ON_COMMAND(ID_GAME_STOP, &CTetrisDlg::OnGameStop)
ON_COMMAND(ID_LEVEL_BEGINNER, &CTetrisDlg::OnLevelBeginner)
ON_COMMAND(ID_LEVEL_INTERMEDIATE, &CTetrisDlg::OnLevelIntermediate)
ON_COMMAND(ID_LEVEL_ADVANCED, &CTetrisDlg::OnLevelAdvanced)
ON_COMMAND(ID_LEVEL_EXPERT, &CTetrisDlg::OnLevelExpert)
ON_COMMAND(ID_LEVEL_DEVIL, &CTetrisDlg::OnLevelDevil)
ON_COMMAND(ID_LEVEL_HELL, &CTetrisDlg::OnLevelHell)
ON_COMMAND(ID_GAME_EXIT, &CTetrisDlg::OnGameExit)
ON_COMMAND(ID_HELP_ABOUT, &CTetrisDlg::OnHelpAbout)
END_MESSAGE_MAP()
void CTetrisDlg::Update()//обновление
{
RedrawBkgnd(CRect(0, 0, WIDTH + 320, HEIGHT));
UpdateBlock();
UpdateWindow();
if(m_gameParam & 0x04)
{
CDC gameoverMemDC;
gameoverMemDC.CreateCompatibleDC(&m_memDC);
gameoverMemDC.SelectObject(m_gameover);
BLENDFUNCTION bf;
bf.BlendOp = AC_SRC_OVER;
bf.BlendFlags = 0;
bf.SourceConstantAlpha = 255;
bf.AlphaFormat = AC_SRC_ALPHA;
::AlphaBlend(m_memDC, 0, 0, WIDTH + 320, HEIGHT, gameoverMemDC, 0, 0, WIDTH + 320, HEIGHT, bf);
}
m_pDC->BitBlt(0, 0, WIDTH + 320, HEIGHT, &m_memDC, 0, 0, SRCCOPY);
}
void CTetrisDlg::AdjustFrame()//парметры окна
{
CRect rect;
rect.left = 0;
rect.top = 0;
rect.right = WIDTH + 320;
rect.bottom = HEIGHT;
::AdjustWindowRectEx(rect, ::GetWindowLong(m_hWnd, GWL_STYLE), TRUE, ::GetWindowLong(m_hWnd, GWL_EXSTYLE));
SetWindowPos(NULL, 0, 0, rect.Width(), rect.Height(), SWP_NOMOVE | SWP_NOZORDER);
}
void CTetrisDlg::Initialize()//инициализация
{
KillTimer(555);
m_lines = 0;
m_score = 0;
for(BYTE i = 0; i < ROW; ++i)
{
memset(m_board[i], 0, COL);
}
delete m_pBlock;
m_pBlock = NULL;
m_menu.EnableMenuItem(ID_GAME_STOP, MF_DISABLED | MF_GRAYED);
m_menu.EnableMenuItem(ID_GAME_PAUSE, MF_DISABLED | MF_GRAYED);
m_menu.CheckMenuItem(ID_GAME_PAUSE, MF_UNCHECKED);
}
void CTetrisDlg::RedrawBkgnd(RECT rect) //отрисовка фона
{
CBrush bkBr(CBitmap::FromHandle(m_bk));
m_memDC.FillRect(&rect, &bkBr);
}
void CTetrisDlg::DrawText(SHORT x1, SHORT y1, SHORT x2, SHORT y2, CString &text, UINT format, COLORREF clr = 0xFFFFFF) //вывод текста
{
m_memDC.SetTextColor(0x000000);
m_memDC.DrawText(text, CRect(x1 + 2, y1 + 2, x2 + 2, y2 + 2), format | DT_NOCLIP);
m_memDC.SetTextColor(clr);
m_memDC.DrawText(text, CRect(x1, y1, x2, y2), format | DT_NOCLIP);
}
void CTetrisDlg::SetFontSize(BYTE size) //параметры шрифта
{
CFont font;
font.CreateFont(
size, // высота
0, // расстояние между буквами
0, // значение угла наклона
0, // угол основания
FW_NORMAL, // вес
FALSE, // курсив
FALSE, // подчеркивание
0, // опции атрибутов
ANSI_CHARSET, // кодировка
OUT_DEFAULT_PRECIS, // точность вывода
CLIP_DEFAULT_PRECIS, // глубина вывода
DEFAULT_QUALITY, // стандартная опция
DEFAULT_PITCH | FF_SWISS, // семейство шрифтов
_T("Impact") // название шрифта
);
m_memDC.SelectObject(&font);
}
void CTetrisDlg::Play(MCIDEVICEID id) //старт игры
{
if(m_gameParam & 0x08)
{
MCI_PLAY_PARMS playParms;
playParms.dwFrom = 0;
::mciSendCommand(id, MCI_PLAY, MCI_FROM, (DWORD)(LPMCI_PLAY_PARMS)&playParms);
}
}
void CTetrisDlg::UpdateBlock() //обновление блока
{
CDC blockMemDC;
blockMemDC.CreateCompatibleDC(&m_memDC);
blockMemDC.SelectObject(m_block);
BLENDFUNCTION bf;
bf.BlendOp = AC_SRC_OVER;
bf.BlendFlags = 0;
bf.SourceConstantAlpha = 220;
bf.AlphaFormat = AC_SRC_ALPHA;
for(BYTE i = 0; i < ROW; ++i)
{
BYTE *nextRow = m_board[i];
for(BYTE j = 0; j < COL; ++j)
{
BYTE clr = nextRow[j];
if(clr)
{
::AlphaBlend(m_memDC, j << 5, i << 5, 32, 32, blockMemDC, (clr - 1) << 5, 0, 32, 32, bf);
}
}
}
blockMemDC.DeleteDC();
}
void CTetrisDlg::UpdateWindow()//обновление окна
{
CDC wndMemDC;
wndMemDC.CreateCompatibleDC(&m_memDC);
wndMemDC.SelectObject(m_window);
BLENDFUNCTION bf;
bf.BlendOp = AC_SRC_OVER;
bf.BlendFlags = 0;
bf.SourceConstantAlpha = 255;
bf.AlphaFormat = AC_SRC_ALPHA;
::AlphaBlend(m_memDC, 328, 10, 308, 629, wndMemDC, 0, 0, 308, 629, bf);
wndMemDC.DeleteDC();
SetFontSize(30);
CString str;
DrawText(360, 32, 600, 64, str = "Cледующая фигура:", DT_LEFT);
CDC blockMemDC;
blockMemDC.CreateCompatibleDC(&m_memDC);
blockMemDC.SelectObject(m_block);
BYTE x = (m_nextColor - 1) << 5;
switch((m_gameParam & 0xE0) >> 5)
{
case 1: //отображение следующей фигуры
m_memDC.StretchBlt(414, 96, 32, 32, &blockMemDC, x, 0, 32, 32, SRCCOPY);
m_memDC.StretchBlt(446, 96, 32, 32, &blockMemDC, x, 0, 32, 32, SRCCOPY);
m_memDC.StretchBlt(478, 96, 32, 32, &blockMemDC, x, 0, 32, 32, SRCCOPY);
m_memDC.StretchBlt(510, 96, 32, 32, &blockMemDC, x, 0, 32, 32, SRCCOPY);
break;
case 2:
m_memDC.StretchBlt(430, 96, 32, 32, &blockMemDC, x, 0, 32, 32, SRCCOPY);
m_memDC.StretchBlt(462, 96, 32, 32, &blockMemDC, x, 0, 32, 32, SRCCOPY);
m_memDC.StretchBlt(494, 96, 32, 32, &blockMemDC, x, 0, 32, 32, SRCCOPY);
m_memDC.StretchBlt(494, 128, 32, 32, &blockMemDC, x, 0, 32, 32, SRCCOPY);
break;
case 3:
m_memDC.StretchBlt(430, 96, 32, 32, &blockMemDC, x, 0, 32, 32, SRCCOPY);
m_memDC.StretchBlt(462, 96, 32, 32, &blockMemDC, x, 0, 32, 32, SRCCOPY);
m_memDC.StretchBlt(494, 96, 32, 32, &blockMemDC, x, 0, 32, 32, SRCCOPY);
m_memDC.StretchBlt(430, 128, 32, 32, &blockMemDC, x, 0, 32, 32, SRCCOPY);
break;
case 4:
m_memDC.StretchBlt(446, 96, 32, 32, &blockMemDC, x, 0, 32, 32, SRCCOPY);
m_memDC.StretchBlt(478, 96, 32, 32, &blockMemDC, x, 0, 32, 32, SRCCOPY);
m_memDC.StretchBlt(446, 128, 32, 32, &blockMemDC, x, 0, 32, 32, SRCCOPY);
m_memDC.StretchBlt(478, 128, 32, 32, &blockMemDC, x, 0, 32, 32, SRCCOPY);
break;
case 5:
m_memDC.StretchBlt(462, 96, 32, 32, &blockMemDC, x, 0, 32, 32, SRCCOPY);
m_memDC.StretchBlt(494, 96, 32, 32, &blockMemDC, x, 0, 32, 32, SRCCOPY);
m_memDC.StretchBlt(430, 128, 32, 32, &blockMemDC, x, 0, 32, 32, SRCCOPY);
m_memDC.StretchBlt(462, 128, 32, 32, &blockMemDC, x, 0, 32, 32, SRCCOPY);
break;
case 6:
m_memDC.StretchBlt(430, 96, 32, 32, &blockMemDC, x, 0, 32, 32, SRCCOPY);
m_memDC.StretchBlt(462, 96, 32, 32, &blockMemDC, x, 0, 32, 32, SRCCOPY);
m_memDC.StretchBlt(494, 96, 32, 32, &blockMemDC, x, 0, 32, 32, SRCCOPY);
m_memDC.StretchBlt(462, 128, 32, 32, &blockMemDC, x, 0, 32, 32, SRCCOPY);
break;
case 7:
m_memDC.StretchBlt(430, 96, 32, 32, &blockMemDC, x, 0, 32, 32, SRCCOPY);
m_memDC.StretchBlt(462, 96, 32, 32, &blockMemDC, x, 0, 32, 32, SRCCOPY);
m_memDC.StretchBlt(462, 128, 32, 32, &blockMemDC, x, 0, 32, 32, SRCCOPY);
m_memDC.StretchBlt(494, 128, 32, 32, &blockMemDC, x, 0, 32, 32, SRCCOPY);
}
blockMemDC.DeleteDC();//отображение состояние игры
DrawText(360, 192, 600, 224, str = "Уровень:", DT_LEFT);
str.Format(_T("%d"), m_level + 1);
DrawText(360, 192, 600, 224, str, DT_RIGHT);
DrawText(360, 256, 600, 288, str = "Очки:", DT_LEFT);
str.Format(_T("%d"), m_score);
DrawText(360, 256, 600, 288, str, DT_RIGHT);
DrawText(360, 320, 600, 352, str = "Уничтожено линий:", DT_LEFT);
str.Format(_T("%d"), m_lines);
DrawText(360, 320, 600, 352, str, DT_RIGHT);
SetFontSize(m_mouseOver == 0x01 ? 36 : 30);
DrawText(360, 384, 600, 416, str = "Новая игра", DT_CENTER);
if(!(m_gameParam & 0x01) || (m_gameParam & 0x04))
{
SetFontSize(30);
DrawText(400, 448, 560, 480, str = "Пауза", DT_LEFT, 0xA0A0A0);
DrawText(400, 448, 560, 480, str = "Стоп", DT_RIGHT, 0xA0A0A0);
}
else
{
SetFontSize(m_mouseOver == 0x02 ? 36 : 30);
DrawText(400, 448, 560, 480, str = "Пауза", DT_LEFT, m_gameParam & 0x02 ? 0x0000FF : 0xFFFFFF);
SetFontSize(m_mouseOver == 0x04 ? 36 : 30);
DrawText(400, 448, 560, 480, str = "Стоп", DT_RIGHT, 0xFFFFFF);
}
SetFontSize(m_mouseOver == 0x08 ? 36 : 30);
SetTextColor(m_memDC, 0xFFFFFF);
SetFontSize(m_mouseOver == 0x10 ? 36 : 30);
DrawText(360, 576, 600, 608, str = "Выход", DT_CENTER);
}
void CTetrisDlg::NextRandomBlock()//выбор случайного блока
{
UINT r;
rand_s(&r);
m_gameParam &= 0x1F;
m_gameParam |= ((BYTE)((DOUBLE)r / ((__int64)UINT_MAX + 1) * 7) + 1) << 5;
m_nextColor = NextRandomColor();
}
BYTE CTetrisDlg::NextRandomColor()//выбор случайнго цвета
{
UINT r;
rand_s(&r);
return (BYTE)((DOUBLE)r / ((__int64)UINT_MAX + 1) * 4 + 1);
}
Block *CTetrisDlg::BlockFromIndex(BYTE i) //функция фыбора случайного блока
{
Play(theApp.m_se_apprID);
switch(i >> 5)
{
case 1:
return new BlockI(m_nextColor, m_board);
case 2:
return new BlockJ(m_nextColor, m_board);
case 3:
return new BlockL(m_nextColor, m_board);
case 4:
return new BlockO(m_nextColor, m_board);
case 5:
return new BlockS(m_nextColor, m_board);
case 6:
return new BlockT(m_nextColor, m_board);
default:
return new BlockZ(m_nextColor, m_board);
}
}
BOOL CTetrisDlg::CheckLine(BYTE row) //проверка каждой линии
{
BYTE *thisRow = m_board[row];
for(BYTE i = 0; i < COL; ++i)
{
if(!thisRow[i])
return false;
}
return true;
}
void CTetrisDlg::RemoveLine(BYTE row) //удаление линии с добавлением очков
{
BYTE *prevRow;
BYTE *thisRow = m_board[row];
CDC blockMemDC;
blockMemDC.CreateCompatibleDC(&m_memDC);
blockMemDC.SelectObject(m_block);
BLENDFUNCTION bf;
bf.BlendOp = AC_SRC_OVER;
bf.BlendFlags = 0;
bf.AlphaFormat = AC_SRC_ALPHA;
Play(theApp.m_se_dsprID);
for(BYTE opacity = 250; opacity != 0; --opacity)
{
RedrawBkgnd(CRect(0, row << 5, WIDTH, (row + 1) << 5));
bf.SourceConstantAlpha = opacity;
for(BYTE i = 0; i < COL; ++i)
{
::AlphaBlend(m_memDC, i << 5, row << 5, 32, 32, blockMemDC, (thisRow[i] - 1) << 5, 0, 32, 32, bf);
}
m_pDC->BitBlt(0, 0, WIDTH, HEIGHT, &m_memDC, 0, 0, SRCCOPY);
}
for(CHAR i = row; i > 0; --i)
{
prevRow = m_board[i - 1];
thisRow = m_board[i];
for(BYTE j = 0; j < COL; ++j)
{
thisRow[j] = prevRow[j];
}
}
for(BYTE i = 0; i < COL; ++i)
{
prevRow[i] = 0;
}
blockMemDC.DeleteDC();
m_score += 100 + m_level * 50;
++m_lines;
Update();
}
BOOL CTetrisDlg::IsGameOver(BYTE blockType) //проверка координат последнего блока
{
switch(blockType)
{
case 0:
return m_board[0][3] || m_board[0][4] || m_board[0][5] || m_board[0][6];
case 1:
return m_board[0][3] || m_board[0][4] || m_board[0][5]|| m_board[1][5];
case 2:
return m_board[0][3] || m_board[0][4] || m_board[0][5] || m_board[1][3];
case 3:
return m_board[0][4] || m_board[0][5] || m_board[1][4] || m_board[1][5];
case 4:
return m_board[0][4] || m_board[0][5] || m_board[1][3] || m_board[1][4];
case 5:
return m_board[0][3] || m_board[0][4] || m_board[0][5] || m_board[1][4];
default:
return m_board[0][3] || m_board[0][4] || m_board[1][4] || m_board[1][5];
}
}
void CTetrisDlg::GameOver()//функция завершения игры
{
Play(theApp.m_me_gmvrID);
KillTimer(555);
m_gameParam |= 0x04;
m_menu.EnableMenuItem(ID_GAME_STOP, MF_DISABLED | MF_GRAYED);
m_menu.EnableMenuItem(ID_GAME_PAUSE, MF_DISABLED | MF_GRAYED);
}
BOOL CTetrisDlg::PreTranslateMessage(MSG *pMsg) //завершение использования системных клавиш
{
if(pMsg->message == WM_KEYDOWN)
{
switch(pMsg->wParam)
{
// Disable OK & Cancel function
case VK_ESCAPE:
case VK_RETURN:
return TRUE;
}
}
return CDialog::PreTranslateMessage(pMsg);
}
BOOL CTetrisDlg::OnInitDialog()//инициализания главного окна
{
CDialog::OnInitDialog();
SetIcon(m_hIcon, TRUE);
SetIcon(m_hIcon, FALSE);
m_menu.LoadMenu(IDR_MENU);
SetMenu(&m_menu);
m_menu.EnableMenuItem(ID_GAME_PAUSE, MF_DISABLED | MF_GRAYED);
m_menu.EnableMenuItem(ID_GAME_STOP, MF_DISABLED | MF_GRAYED);
m_pDC = new CClientDC(this);
m_memDC.CreateCompatibleDC(m_pDC);
m_memBmp.CreateCompatibleBitmap(m_pDC, WIDTH + 320, HEIGHT);
m_memDC.SelectObject(m_memBmp);
m_memDC.SetBkMode(TRANSPARENT);
SetFontSize(30);
AdjustFrame();
Initialize();
m_menu.CheckMenuItem(ID_LEVEL_BEGINNER, MF_CHECKED);
return TRUE;
}
void CTetrisDlg::OnPaint()//отображение иконки в панели задач
{
Update();
if (IsIconic())
{
CPaintDC dc(this);
SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
CRect rect;
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + 1) / 2;
int y = (rect.Height() - cyIcon + 1) / 2;
dc.DrawIcon(x, y, m_hIcon);
}
else
{
CDialog::OnPaint();
}
}
HCURSOR CTetrisDlg::OnQueryDragIcon()
{
return static_cast<HCURSOR>(m_hIcon);
}
void CTetrisDlg::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) //обработчик нажатия клавиш
{
switch(nChar)
{
case VK_F1:
PostMessage(WM_COMMAND, ID_GAME_NEW, 0L);
break;
case VK_F2:
if((m_gameParam & 0x01) && !(m_gameParam & 0x04))
PostMessage(WM_COMMAND, ID_GAME_PAUSE, 0L);
break;
case VK_F3:
if((m_gameParam & 0x01) && !(m_gameParam & 0x04))
PostMessage(WM_COMMAND, ID_GAME_STOP, 0L);
}
if((m_gameParam & 0x07) == 0x01)
{
switch(nChar)
{
case VK_UP:
if(!(nFlags & 0x4000))
{
if(m_pBlock->canTurn())
{
Play(theApp.m_se_turnID);
m_pBlock->turn();
}
else if(m_gameParam & 0x08)
{
Play(theApp.m_se_dsblID);
}
}
break;
case VK_DOWN:
if(m_pBlock->canMoveDown())
{
m_pBlock->moveDown();
m_score += m_level + 1;
}
break;
case VK_LEFT:
if(m_pBlock->canMoveLeft())
{
m_pBlock->moveLeft();
}
break;
case VK_RIGHT:
if(m_pBlock->canMoveRight())
{
m_pBlock->moveRight();
}
break;
}
Invalidate(FALSE);
}
CDialog::OnKeyDown(nChar, nRepCnt, nFlags);
}
void CTetrisDlg::OnLButtonDown(UINT nFlags, CPoint point)
{
if(m_mouseOver != 0x00)
{
m_gameParam |= 0x10;
}
}
void CTetrisDlg::OnLButtonUp(UINT nFlags, CPoint point) //отображение кпопок функций игры
{
if(m_gameParam & 0x10)
{
if(m_mouseOver == 0x01)
{
PostMessage(WM_COMMAND, ID_GAME_NEW);
}
else if((m_gameParam & 0x01) && !(m_gameParam & 0x04) && m_mouseOver == 0x02)
{
PostMessage(WM_COMMAND, ID_GAME_PAUSE);
}
else if((m_gameParam & 0x01) && !(m_gameParam & 0x04) && m_mouseOver == 0x04)
{
PostMessage(WM_COMMAND, ID_GAME_STOP);
}
else if(m_mouseOver == 0x10)
{
PostMessage(WM_COMMAND, ID_GAME_EXIT);
}
}
}
void CTetrisDlg::OnMouseMove(UINT nFlags, CPoint point) //обработчк движения курсора
{
CRect rect;
rect.SetRect(459, 384, 502, 413);
if(m_mouseOver != 0x01 && ::PtInRect(&rect, point))
{
Play(theApp.m_se_crsrID);
m_mouseOver = 0x01;
Invalidate(FALSE);
}
else if(m_mouseOver == 0x01 && !::PtInRect(&rect, point))
{
m_mouseOver = 0x00;
Invalidate(FALSE);
}
else
{
rect.SetRect(400, 448, 459, 477);
if((m_gameParam & 0x01) && !(m_gameParam & 0x04) && m_mouseOver != 0x02 && ::PtInRect(&rect, point))
{
Play(theApp.m_se_crsrID);
m_mouseOver = 0x02;
Invalidate(FALSE);
}
else if(m_mouseOver == 0x02 && !::PtInRect(&rect, point))
{
m_mouseOver = 0x00;
Invalidate(FALSE);
}
else
{
rect.SetRect(512, 448, 560, 477);
if((m_gameParam & 0x01) && !(m_gameParam & 0x04) && m_mouseOver != 0x04 && ::PtInRect(&rect, point))
{
Play(theApp.m_se_crsrID);
m_mouseOver = 0x04;
Invalidate(FALSE);
}
else if(m_mouseOver == 0x04 && !::PtInRect(&rect, point))
{
m_mouseOver = 0x00;
Invalidate(FALSE);
}
else
{
rect.SetRect(448, 512, 512, 541);
if(m_mouseOver != 0x08 && ::PtInRect(&rect, point))
{
Play(theApp.m_se_crsrID);
m_mouseOver = 0x08;
Invalidate(FALSE);
}
else if(m_mouseOver == 0x08 && !::PtInRect(&rect, point))
{
m_mouseOver = 0x00;
Invalidate(FALSE);
}
else
{
rect.SetRect(460, 576, 500, 608);
if(m_mouseOver != 0x10 && ::PtInRect(&rect, point))
{
Play(theApp.m_se_crsrID);
m_mouseOver = 0x10;
Invalidate(FALSE);
}
else if(m_mouseOver == 0x10 && !::PtInRect(&rect, point))
{
m_mouseOver = 0x00;
Invalidate(FALSE);
}
}
}
}
}
}
UINT CTetrisDlg::OnGetDlgCode()
{
return DLGC_WANTARROWS | CDialog::OnGetDlgCode();
}
BOOL CTetrisDlg::OnEraseBkgnd(CDC* pDC)
{
return TRUE;
}
void CTetrisDlg::OnTimer(UINT_PTR nIDEvent) //обработчик движения блока по полю
{
if(m_pBlock->canMoveDown())
{
m_pBlock->moveDown();
}
else
{
for(CHAR i = ROW - 1; i >= 0; --i)
{
if(CheckLine(i))
{
RemoveLine(i);
++i;
}
}
MSG msg;
while(::PeekMessage(&msg, m_hWnd, 0, 0, PM_REMOVE));
if(IsGameOver(m_gameParam & 0xE0))
{
GameOver();
}
else
{
delete m_pBlock;
m_pBlock = BlockFromIndex(m_gameParam & 0xE0);
NextRandomBlock();
m_nextColor = NextRandomColor();
}
}
Invalidate(FALSE);
CDialog::OnTimer(nIDEvent);
}
void CTetrisDlg::OnGameNew()//инициализация новой игры
{
if(m_gameParam & 0x01)
{
Initialize();
}
m_gameParam |= 0x01;
m_gameParam &= ~0x06;
m_menu.EnableMenuItem(ID_GAME_STOP, MF_ENABLED);
m_menu.EnableMenuItem(ID_GAME_PAUSE, MF_ENABLED);
SetTimer(555, 500 - m_level * 90, NULL);
NextRandomBlock();
m_pBlock = BlockFromIndex(m_gameParam & 0xE0);
NextRandomBlock();
Invalidate(FALSE);
}
void CTetrisDlg::OnGamePause()//пауза
{
Play(theApp.m_se_slctID);
if(m_gameParam & 0x02)
{
m_menu.CheckMenuItem(ID_GAME_PAUSE, MF_UNCHECKED);
m_gameParam &= ~0x02;
SetTimer(555, 500 - m_level * 90, NULL);
}
else
{
m_menu.CheckMenuItem(ID_GAME_PAUSE, MF_CHECKED);
m_gameParam |= 0x02;
KillTimer(555);
}
Invalidate(FALSE);
}
void CTetrisDlg::OnGameStop()//остановка
{
Play(theApp.m_se_slctID);
m_gameParam &= ~0xE7;
Initialize();
Invalidate(FALSE);
}
void CTetrisDlg::OnLevelBeginner()//уровень 1
{
m_menu.GetSubMenu(0)->GetSubMenu(3)->CheckMenuItem(m_level, MF_BYPOSITION | MF_UNCHECKED);
m_menu.CheckMenuItem(ID_LEVEL_BEGINNER, MF_CHECKED);
m_level = 0;
if(m_gameParam & 0x01)
PostMessage(WM_COMMAND, ID_GAME_STOP, 0L);
}
void CTetrisDlg::OnLevelIntermediate()//уровень 2
{
m_menu.GetSubMenu(0)->GetSubMenu(3)->CheckMenuItem(m_level, MF_BYPOSITION | MF_UNCHECKED);
m_menu.CheckMenuItem(ID_LEVEL_INTERMEDIATE, MF_CHECKED);
m_level = 1;
if(m_gameParam & 0x01)
PostMessage(WM_COMMAND, ID_GAME_STOP, 0L);
}
void CTetrisDlg::OnLevelAdvanced()//уровень 3
{
m_menu.GetSubMenu(0)->GetSubMenu(3)->CheckMenuItem(m_level, MF_BYPOSITION | MF_UNCHECKED);
m_menu.CheckMenuItem(ID_LEVEL_ADVANCED, MF_CHECKED);
m_level = 2;
if(m_gameParam & 0x01)
PostMessage(WM_COMMAND, ID_GAME_STOP, 0L);
}
void CTetrisDlg::OnLevelExpert()//уровень 4
{
m_menu.GetSubMenu(0)->GetSubMenu(3)->CheckMenuItem(m_level, MF_BYPOSITION | MF_UNCHECKED);
m_menu.CheckMenuItem(ID_LEVEL_EXPERT, MF_CHECKED);
m_level = 3;
if(m_gameParam & 0x01)
PostMessage(WM_COMMAND, ID_GAME_STOP, 0L);
}
void CTetrisDlg::OnLevelDevil()//уровень 5
{
m_menu.GetSubMenu(0)->GetSubMenu(3)->CheckMenuItem(m_level, MF_BYPOSITION | MF_UNCHECKED);
m_menu.CheckMenuItem(ID_LEVEL_DEVIL, MF_CHECKED);
m_level = 4;
if(m_gameParam & 0x01)
PostMessage(WM_COMMAND, ID_GAME_STOP, 0L);
}
void CTetrisDlg::OnLevelHell()//уровень 6
{
m_menu.GetSubMenu(0)->GetSubMenu(3)->CheckMenuItem(m_level, MF_BYPOSITION | MF_UNCHECKED);
m_menu.CheckMenuItem(ID_LEVEL_HELL, MF_CHECKED);
m_level = 5;
if(m_gameParam & 0x01)
PostMessage(WM_COMMAND, ID_GAME_STOP, 0L);
}
void CTetrisDlg::OnGameExit()//обработчик выхода
{
PostMessage(WM_COMMAND, IDOK, 0L);
}
void CTetrisDlg::OnHelpAbout()//вывод окна «о программе»
{
CAboutDlg dlgAbout;
dlgAbout.DoModal();
}
Block.cpp
//Дата создания проекта: 2.12.2015
//Разработчики: Наумов Г.М., Сон И.В.
//Версия программы: 1.0
#include "StdAfx.h"
#include "Block.h"
#include "Tetris.h"
Block::Block(unsigned char clr, unsigned char **board) //описание внутренних полей блока
{
row = 0;
col = 4;
dir = 0;
this->clr = clr;
this->board = board;
}
BlockI.cpp
//Дата создания проекта: 2.12.2015
//Разработчики: Наумов Г.М., Сон И.В.
//Версия программы: 1.0
#include "StdAfx.h"
#include "Tetris.h"
#include "TetrisDlg.h"
/*буквой х обозначена ось вращения тетромины
case dir
when 0
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . * x * * . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
when 1
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . * . . . . . .
. . . . . x . . . . . .
. . . . . * . . . . . .
. . . . . * . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
*/
BlockI::BlockI(unsigned char clr, unsigned char **board) : Block(clr, board)
{//координаты появления блока
board[0][3] = clr;
board[0][4] = clr;
board[0][5] = clr;
board[0][6] = clr;
}
bool BlockI::canMoveDown()//проверка остановки
{
switch(dir)
{
case 0:
return passable(row + 1, col);
default:
return row < CTetrisDlg::ROW - 3 && !board[row + 3][col];
}
}
bool BlockI::canMoveLeft()//проверка движения влево
{
switch(dir)
{
case 0:
return col > 1 && !board[row][col - 2];
default:
return passable(row, col - 1);
}
}
bool BlockI::canMoveRight()//проверка движения вправо
{
switch(dir)
{
case 0:
return col < CTetrisDlg::COL - 3 && !board[row][col + 3];
default:
return passable(row, col + 1);
}
}
bool BlockI::canTurn()//проверка возможности поворота
{
switch(dir)
{
case 0:
return row > 0 && row < CTetrisDlg::ROW - 2 && !board[row - 1][col] && !board[row + 1][col] && !board[row + 2][col];
default:
if(col > 0 && col < CTetrisDlg::COL - 2)
{
unsigned char *thisRow = board[row];
return !thisRow[col - 1] && !thisRow[col + 1] && !thisRow[col + 2];
}
return false;
}
}
void BlockI::moveDown()//функция движения вниз
{
switch(dir)
{
case 0:
clear();
++row;
show();
return;
default:
board[row - 1][col] = 0;
++row;
board[row + 2][col] = clr;
}
}
void BlockI::moveLeft()//движение влево
{
unsigned char *thisRow = board[row];
switch(dir)
{
case 0:
thisRow[col + 2] = 0;
--col;
thisRow[col - 1] = clr;
return;
default:
clear();
--col;
show();
}
}
void BlockI::moveRight()//движение вправо
{
unsigned char *thisRow = board[row];
switch(dir)
{
case 0:
thisRow[col - 1] = 0;
++col;
thisRow[col + 2] = clr;
return;
default:
clear();
++col;
show();
}
}
void BlockI::turn()//функция поворота
{
clear();
dir ^= 1;
show();
}
bool BlockI::passable(char row, char col) //функция остановки блока на поле
{
switch(dir)
{
case 0:
if(row < CTetrisDlg::ROW && col > 0 && col < CTetrisDlg::COL - 2)
{
unsigned char *thisRow = board[row];
return !thisRow[col - 1] && !thisRow[col] && !thisRow[col + 1] && !thisRow[col + 2];
}
return false;
default:
if(row > 0 && row < CTetrisDlg::ROW - 2 && col > -1 && col < CTetrisDlg::COL)
{
return !board[row - 1][col] && !board[row][col] && !board[row + 1][col] && !board[row + 2][col];
}
return false;
}
}
void BlockI::show()//функция отображения блока
{
unsigned char *thisRow = board[row];
switch(dir)
{
case 0:
thisRow[col - 1] = clr;
thisRow[col] = clr;
thisRow[col + 1] = clr;
thisRow[col + 2] = clr;
return;
default:
board[row - 1][col] = clr;
board[row][col] = clr;
board[row + 1][col] = clr;
board[row + 2][col] = clr;
}
}
void BlockI::clear()//функция удаления блока
{
unsigned char *thisRow = board[row];
switch(dir)
{
case 0:
thisRow[col - 1] = 0;
thisRow[col] = 0;
thisRow[col + 1] = 0;
thisRow[col + 2] = 0;
return;
default:
board[row - 1][col] = 0;
board[row][col] = 0;
board[row + 1][col] = 0;
board[row + 2][col] = 0;
}
}
Аналогоично были реализованы остальные тетромины, их код приведен в электронном виде.
· BlockL.cpp (l-образный блок)
· BlockJ.cpp (j-образный блок)
· BlockO.cpp (o-образный блок)
· BlockS.cpp (s-образный блок)
· BlockT.cpp (t-образный блок)
· BlockZ.cpp (z-образный блок)
Поиск по сайту:
|