-
完善剩下的上下左右的操作
-
设置定时器
-
消除bug
#pragma once
#include "CBlock.h"
#include "CBackGround.h"
#include <wtypes.h>
class CTetris
{
public:
CTetris();
~CTetris();
public:
void InitGame();
void ShowGame(HDC hdc);
void DrawALlBack(HDC hdc);
void DrawMaxLeft(HDC hdc);
void DrawMinRight(HDC hdc);
void BlockRotate();
int BlockDown();
void BlockLeft();
void BlockRight();
private:
bool IsCanMove();
bool IsGameOver();
CBlock m_cBlock;
CBackGround m_cBackGround;
size_t m_nRow;
size_t m_nCol;
int m_nScore = 0;
};
#include "CTetris.h"
CTetris::CTetris()
{
}
CTetris::~CTetris()
{
}
void CTetris::InitGame()
{
m_cBlock.RandCreateBlock();
m_cBlock.RandCreateBlock();
m_cBackGround.InitBackGround();
m_nRow = 0;
m_nCol = COL / 2 - 2;
m_cBackGround.WriteBlock2BackGround(m_cBlock, m_nRow, m_nCol, BLOCK_MOVE, BLOCK_MOVE);
}
void CTetris::ShowGame(HDC hdc)
{
DrawALlBack(hdc);
DrawMaxLeft(hdc);
DrawMinRight(hdc);
}
void CTetris::DrawALlBack(HDC hdc)
{
HGDIOBJ hPenNull = GetStockObject(NULL_PEN);
HGDIOBJ hBrushGray = GetStockObject(GRAY_BRUSH);
SelectObject(hdc, hPenNull);
SelectObject(hdc, hBrushGray);
Rectangle(hdc, WIDTH, WIDTH * 4, (COL - 1) * WIDTH, ROW * HEIGHT);
Rectangle(hdc, (COL + 1) * WIDTH, WIDTH * 4, (COL + 9) * WIDTH, ROW * HEIGHT);
DeleteObject(hBrushGray);
DeleteObject(hPenNull);
}
void CTetris::DrawMaxLeft(HDC hdc)
{
HGDIOBJ hPenBlaCk = GetStockObject(BLACK_PEN);
HGDIOBJ hBrushWhite = GetStockObject(WHITE_BRUSH);
SelectObject(hdc, hPenBlaCk);
SelectObject(hdc, hBrushWhite);
BACKGROUND BcakGround = m_cBackGround.GetBackGround();
for (size_t y = 0; y < ROW; y++)
{
for (size_t x = 0; x < COL; x++)
{
if (BcakGround[y][x] != BLOCK_SPACE && BcakGround[y][x] != BLOCK_WAll)
{
Rectangle(hdc, x * WIDTH, y * HEIGHT, x * WIDTH + WIDTH, y * HEIGHT + HEIGHT);
}
}
}
DeleteObject(hBrushWhite);
DeleteObject(hPenBlaCk);
}
void CTetris::DrawMinRight(HDC hdc)
{
HGDIOBJ hPenBlaCk = GetStockObject(BLACK_PEN);
HGDIOBJ hBrushWhite = GetStockObject(WHITE_BRUSH);
SelectObject(hdc, hPenBlaCk);
SelectObject(hdc, hBrushWhite);
BLOCKDATE BlockDate = m_cBlock.GetNextBlock();
for (size_t y = 0; y < BLOCK_ROW; y++)
{
for (size_t x = 0; x < BLOCK_COL; x++)
{
if (BlockDate[y][x] == BLOCK_MOVE)
{
Rectangle(hdc, (COL + 3 + x) * WIDTH, (y + 6) * HEIGHT, (COL + 3 + x) * WIDTH + WIDTH, (y + 6) * HEIGHT + HEIGHT);
}
}
}
DeleteObject(hBrushWhite);
DeleteObject(hPenBlaCk);
}
void CTetris::BlockRotate()
{
m_cBackGround.ClearBlock2BackGround(m_cBlock, m_nRow, m_nCol, BLOCK_MOVE);
size_t nIndex = m_cBlock.GetShape();
m_cBlock.RotateBlock();
if (!IsCanMove())
{
m_cBlock.SetShape(nIndex);
}
m_cBackGround.WriteBlock2BackGround(m_cBlock, m_nRow, m_nCol, BLOCK_MOVE, BLOCK_MOVE);
}
int CTetris::BlockDown()
{
m_cBackGround.ClearBlock2BackGround(m_cBlock, m_nRow, m_nCol, BLOCK_MOVE);
m_nRow++;
if (!IsCanMove())
{
m_nRow--;
m_cBackGround.WriteBlock2BackGround(m_cBlock, m_nRow, m_nCol, BLOCK_MOVE, BLOCK_FIXED);
m_cBackGround.RemoveRows();
if (IsGameOver())
{
return -1;
}
m_cBlock.RandCreateBlock();
m_nRow = 0;
m_nCol = COL / 2 - 2;
}
m_cBackGround.WriteBlock2BackGround(m_cBlock, m_nRow, m_nCol, BLOCK_MOVE, BLOCK_MOVE);
return 0;
}
void CTetris::BlockLeft()
{
m_cBackGround.ClearBlock2BackGround(m_cBlock, m_nRow, m_nCol, BLOCK_MOVE);
m_nCol--;
if (!IsCanMove())
{
m_nCol++;
}
m_cBackGround.WriteBlock2BackGround(m_cBlock, m_nRow, m_nCol, BLOCK_MOVE, BLOCK_MOVE);
}
void CTetris::BlockRight()
{
m_cBackGround.ClearBlock2BackGround(m_cBlock, m_nRow, m_nCol, BLOCK_MOVE);
m_nCol++;
if (!IsCanMove())
{
m_nCol--;
}
m_cBackGround.WriteBlock2BackGround(m_cBlock, m_nRow, m_nCol, BLOCK_MOVE, BLOCK_MOVE);
}
bool CTetris::IsCanMove()
{
BACKGROUND BcakGround = m_cBackGround.GetBackGround();
BLOCKDATE BlockDate = m_cBlock.GetCurrentBlock();
for (size_t y = 0; y < BLOCK_ROW; y++)
{
for (size_t x = 0; x < BLOCK_COL; x++)
{
if (BlockDate[y][x] == BLOCK_MOVE && (BcakGround[y + m_nRow][x + m_nCol] == BLOCK_WAll || BcakGround[y + m_nRow][x + m_nCol] == BLOCK_FIXED))
{
return false;
}
}
}
return true;
}
bool CTetris::IsGameOver()
{
BACKGROUND BcakGround = m_cBackGround.GetBackGround();
for (size_t x = 1; x < COL -1 ; x++)
{
if (BcakGround[3][x] == BLOCK_FIXED)
{
return true;
}
}
return false;
}
#include "framework.h"
#include "Project1.h"
#include "resource.h"
#include "CBlock.h"
#include "CTetris.h"
#define BLOCK_DOWN_TIMER 1
#define BLOCK_AI_TIMER 2
#define BLOCK_DOWN_SPEED 500
#define MAX_LOADSTRING 100
CTetris* pTetris = nullptr;
HINSTANCE hInst;
WCHAR szTitle[MAX_LOADSTRING];
WCHAR szWindowClass[MAX_LOADSTRING];
ATOM MyRegisterClass(HINSTANCE hInstance);
BOOL InitInstance(HINSTANCE, int);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
INT_PTR CALLBACK About(HWND, UINT, WPARAM, LPARAM);
int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
_In_opt_ HINSTANCE hPrevInstance,
_In_ LPWSTR lpCmdLine,
_In_ int nCmdShow)
{
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
LoadStringW(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
LoadStringW(hInstance, IDC_PROJECT1, szWindowClass, MAX_LOADSTRING);
MyRegisterClass(hInstance);
if (!InitInstance(hInstance, nCmdShow))
{
return FALSE;
}
HACCEL hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_PROJECT1));
MSG msg;
while (GetMessage(&msg, nullptr, 0, 0))
{
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return (int)msg.wParam;
}
ATOM MyRegisterClass(HINSTANCE hInstance)
{
WNDCLASSEXW wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_PROJECT1));
wcex.hCursor = LoadCursor(nullptr, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wcex.lpszMenuName = MAKEINTRESOURCEW(IDC_PROJECT1);
wcex.lpszClassName = szWindowClass;
wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
return RegisterClassExW(&wcex);
}
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
hInst = hInstance;
HWND hWnd = CreateWindowW(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
600, 300, (COL + 11) * WIDTH, (ROW + 2) * HEIGHT, nullptr, nullptr, hInstance, nullptr);
if (!hWnd)
{
return FALSE;
}
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
return TRUE;
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_TIMER:
{
switch (wParam)
{
case BLOCK_DOWN_TIMER:
{
if (pTetris)
{
if (pTetris->BlockDown() == -1)
{
PostQuitMessage(0);
}
}
InvalidateRect(hWnd, NULL, TRUE);
return 0;
}
break;
case BLOCK_AI_TIMER:
{
return 0;
}
break;
}
}
break;
case WM_KEYDOWN:
{
int wmId = LOWORD(wParam);
switch (wmId)
{
case VK_UP:
{
if (pTetris)
{
pTetris->BlockRotate();
}
InvalidateRect(hWnd, NULL, TRUE);
}
break;
case VK_DOWN:
{
if (pTetris)
{
if (pTetris->BlockDown() == -1)
{
PostQuitMessage(0);
}
}
InvalidateRect(hWnd, NULL, TRUE);
}
break;
case VK_LEFT:
{
if (pTetris)
{
pTetris->BlockLeft();
}
InvalidateRect(hWnd, NULL, TRUE);
}
break;
case VK_RIGHT:
{
if (pTetris)
{
pTetris->BlockRight();
}
InvalidateRect(hWnd, NULL, TRUE);
}
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
}
break;
case WM_COMMAND:
{
int wmId = LOWORD(wParam);
switch (wmId)
{
case IDM_ABOUT:
DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
break;
case IDM_EXIT:
DestroyWindow(hWnd);
break;
case MENU_START:
{
if (pTetris)
{
delete pTetris;
pTetris = nullptr;
}
pTetris = new CTetris();
if (pTetris)
{
pTetris->InitGame();
SetTimer(hWnd, BLOCK_DOWN_TIMER, BLOCK_DOWN_SPEED, NULL);
}
InvalidateRect(hWnd, NULL, TRUE);
}
break;
case MENU_PAUSE:
{
MessageBox(0, "MENU_PAUSE", "Menu", MB_OKCANCEL);
}
break;
case MENU_EXIT:
{
DestroyWindow(hWnd);
break;
}
break;
case MENU_AI:
{
MessageBox(0, "MENU_AI", "Menu", MB_OK);
}
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
}
break;
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hWnd, &ps);
if (pTetris)
{
pTetris->ShowGame(hdc);
}
EndPaint(hWnd, &ps);
}
break;
case WM_DESTROY:
{
KillTimer(hWnd, BLOCK_DOWN_TIMER);
KillTimer(hWnd, BLOCK_AI_TIMER);
PostQuitMessage(0);
}
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
UNREFERENCED_PARAMETER(lParam);
switch (message)
{
case WM_INITDIALOG:
return (INT_PTR)TRUE;
case WM_COMMAND:
if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
{
EndDialog(hDlg, LOWORD(wParam));
return (INT_PTR)TRUE;
}
break;
}
return (INT_PTR)FALSE;
}
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 按钮权限的设计及实现