用VC撸了一个俄罗斯方块, 实在是内流满面啊, 我屮艸芔茻, 纠结代码:
// Blocks.cpp : 定义应用程序的入口点。
#include "stdafx.h"
#include "Blocks.h"
#include "stdio.h"
#include "time.h"
#include<stdlib.h>
#define MAX_LOADSTRING 100
#define BOUND_SIZE 10
#define TETRIS_SIZE 30
#define GAME_X 10
#define GAME_Y 20
//游戏中方块的类型
int Tetris[][4][4] = {
{
{ 0,0,0,0 },
{ 1,1,1,1 },
{ 0,0,0,0 },
{ 0,0,0,0 }
},
{
{ 1,1,0,0 },
{ 1,1,0,0 },
{ 0,0,0,0 },
{ 0,0,0,0 }
},
{
{ 1,1,0,0 },
{ 0,1,1,0 },
{ 0,0,0,0 },
{ 0,0,0,0 }
},
{
{ 0,1,1,0 },
{ 1,1,0,0 },
{ 0,0,0,0 },
{ 0,0,0,0 }
},
{
{ 1,0,0,0 },
{ 1,1,1,0 },
{ 0,0,0,0 },
{ 0,0,0,0 }
}
};
//方块的个数
int TetrisCount = sizeof(Tetris) / sizeof(Tetris[0]);
int currentTetris[4][4] = {
{ 0,0,0,0 },
{ 1,1,1,1 },
{ 0,0,0,0 },
{ 0,0,0,0 }
};
int tempTetris[4][4];
//游戏面板.保存临时数据
int game_board[GAME_X][GAME_Y];
//游戏初始化的变量, X和Y为当前的方块的几何轴, timer为定时器变量;
int X = 3, Y = 0, timer = 0;
//随机生成方块
VOID generateTetris(int TETData[4][4]);
//返回1的话就是碰到,返回0就是没有碰到;
int CheckTetris(int x, int y, int TETData[4][4], int gb[GAME_X][GAME_Y]);
//合并背景方块和消方块
VOID RefreshTetris(int x, int y, int TETData[4][4], int gb[GAME_X][GAME_Y]);
//旋转方块
VOID rotateTetris(int tet[4][4]);
//绘制方块
VOID DrawTetris(HDC hdc, int x, int y, int tet[4][4]);
//绘制背景
VOID DrawBackGround(HDC hdc);
// 全局变量:
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);
// TODO: 在此放置代码。
// 初始化全局字符串
LoadStringW(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
LoadStringW(hInstance, IDC_BLOCKS, szWindowClass, MAX_LOADSTRING);
MyRegisterClass(hInstance);
// 执行应用程序初始化:
if (!InitInstance (hInstance, nCmdShow))
{
return FALSE;
}
HACCEL hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_BLOCKS));
MSG msg;
// 主消息循环:
while (GetMessage(&msg, nullptr, 0, 0))
{
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return (int) msg.wParam;
}
//
// 函数: MyRegisterClass()
//
// 目的: 注册窗口类。
//
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_BLOCKS));
wcex.hCursor = LoadCursor(nullptr, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = MAKEINTRESOURCEW(IDC_BLOCKS);
wcex.lpszClassName = szWindowClass;
wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
return RegisterClassExW(&wcex);
}
//
// 函数: InitInstance(HINSTANCE, int)
//
// 目的: 保存实例句柄并创建主窗口
//
// 注释:
//
// 在此函数中,我们在全局变量中保存实例句柄并
// 创建和显示主程序窗口。
//
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
hInst = hInstance; // 将实例句柄存储在全局变量中
HWND hWnd = CreateWindowW(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, nullptr, nullptr, hInstance, nullptr);
if (!hWnd)
{
return FALSE;
}
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
return TRUE;
}
//绘制背景
VOID DrawBackGround(HDC hdc) {
int x, y;
HPEN hPen = (HPEN)GetStockObject(NULL_PEN);
HBRUSH hBrush = (HBRUSH)GetStockObject(GRAY_BRUSH);
HPEN hPen1 = (HPEN)GetStockObject(NULL_PEN);
HBRUSH hBrush1 = (HBRUSH)GetStockObject(BLACK_BRUSH);
Rectangle(hdc, BOUND_SIZE, BOUND_SIZE, BOUND_SIZE+ TETRIS_SIZE*GAME_X, BOUND_SIZE+TETRIS_SIZE*GAME_Y);
for (x = 0; x < GAME_X; x++) {
for (y = 0; y < GAME_Y; y++) {
if (game_board[x][y] == 1) {
SelectObject(hdc, hBrush1);
Rectangle(hdc,
BOUND_SIZE + x*TETRIS_SIZE,
BOUND_SIZE + y*TETRIS_SIZE,
BOUND_SIZE + (x + 1)*TETRIS_SIZE,
BOUND_SIZE + (y + 1)*TETRIS_SIZE);
}else {
SelectObject(hdc, hPen);
SelectObject(hdc, hBrush);
Rectangle(hdc,
BOUND_SIZE + TETRIS_SIZE*x,
BOUND_SIZE + TETRIS_SIZE*y,
BOUND_SIZE + TETRIS_SIZE*x + TETRIS_SIZE,
BOUND_SIZE + TETRIS_SIZE*y + TETRIS_SIZE);
}
}
}
}
//绘制方块
VOID DrawTetris(HDC hdc, int x, int y, int tet[4][4]) {
HPEN hPen = (HPEN)GetStockObject(BLACK_PEN);
HBRUSH hBrush = (HBRUSH)GetStockObject(BLACK_BRUSH);
SelectObject(hdc, hPen);
SelectObject(hdc, hBrush);
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
if (tet[i][j]) {
Rectangle(hdc,
BOUND_SIZE + (x + j)*TETRIS_SIZE,
BOUND_SIZE + (y + i)*TETRIS_SIZE,
BOUND_SIZE + (x + j + 1 )*TETRIS_SIZE,
BOUND_SIZE + (y + i + 1)*TETRIS_SIZE);
}
}
}
}
//旋转方块
VOID rotateTetris(int tet[4][4]) {
int x, y;
int bNewTet[4][4];
for (x = 0; x < 4; x++) {
for (y = 0; y < 4; y++) {
bNewTet[x][y] = tet[3 - y][x];
}
}
//tet = bNewTet
memcpy(tet, bNewTet, sizeof(bNewTet));
}
//合并背景方块和消方块
VOID RefreshTetris(int x, int y, int TETData[4][4], int gb[GAME_X][GAME_Y]) {
//合并TETData和gb;
int i, j;
for (j = 0; j < 4; j++) {
for (i = 0; i < 4; i++) {
if (TETData[j][i] == 1) {
gb[x + i][y + j] = 1;
}
}
}
int flag, newY;
for (i = GAME_Y, newY = GAME_Y; i >= 0; i--) {
flag = 1;
for (j = 0; j < GAME_X; j++) {
game_board[j][newY] = game_board[j][i];
if (game_board[j][i] == 0) {
flag = 0;
}
}
if (flag == 1) {
//满格的话,用上一行替换这一行
}else {
//如果没有满格的话
newY--;
}
}
}
//返回1的话就是碰到,返回0就是没有碰到;
int CheckTetris(int x, int y, int TETData[4][4], int gb[GAME_X][GAME_Y]) {
if (x < 0) {
return 1;
}
int flag = 0, i = 0, j = 0;
for (j=0; j < 4; j++) {
for (i=0; i < 4; i++) {
if (TETData[j][i] == 1) {
if (x + i >= GAME_X) {
return 1;
}
if (y + j >= GAME_Y) {
return 1;
}
if (gb[x + i][y + j]) {
return 1;
}
}
}
}
return 0;
}
//随机生成方块
VOID generateTetris(int TETData[4][4]) {
srand(time(NULL));
int getTetris = rand()%TetrisCount;
currentTetris;
memcpy(currentTetris, Tetris[getTetris], sizeof(currentTetris));
}
//
// 函数: WndProc(HWND, UINT, WPARAM, LPARAM)
//
// 目的: 处理主窗口的消息。
//
// WM_COMMAND - 处理应用程序菜单
// WM_PAINT - 绘制主窗口
// WM_DESTROY - 发送退出消息并返回
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_CREATE:
{
memset(game_board, 0, sizeof(game_board));
RECT rect;
int nWinX, nWinY, nClientX, nClientY, nScreenWidth, nScreenHeight, userWidth, userHeight;
GetWindowRect(hWnd, &rect);
//获取窗口大小
nWinX = rect.right - rect.left;
nWinY = rect.bottom - rect.top;
//获取客户区大小
GetClientRect(hWnd, &rect);
nClientX = rect.right - rect.left;
nClientY = rect.bottom - rect.top;
//计算窗口大小
userWidth = 3 * BOUND_SIZE + GAME_X *TETRIS_SIZE + (nWinX - nClientX);
userHeight = 2 * BOUND_SIZE + GAME_Y*TETRIS_SIZE + (nWinY - nClientY);
//移动居中
nScreenWidth = GetSystemMetrics(SM_CXSCREEN);
nScreenHeight = GetSystemMetrics(SM_CYSCREEN);
//设置对象在桌面中的位置
MoveWindow(hWnd, (nScreenWidth - userWidth) / 2, (nScreenHeight - userHeight) / 2, userWidth, userHeight, TRUE);
//启动定时器
SetTimer(hWnd, timer, 1000, NULL);
}
break;
case WM_TIMER:
{
if (0==CheckTetris(X, Y + 1, currentTetris, game_board)) {
Y++;
}
else {
//合成方块到游戏面板中
RefreshTetris(X, Y , currentTetris, game_board);
//生成新的方块
generateTetris(currentTetris);
//X,Y重新赋值
Y = 0;
X = 3;
};
InvalidateRect(hWnd, NULL, true);
}
break;
case WM_LBUTTONDOWN:
{
//测试代码
//rotateTetris(currentTetris)
//刷新界面
//InvalidateRect(hWnd, NULL, true)
}
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;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
}
break;
case WM_KEYDOWN:
{
switch(wParam) {
case VK_LEFT :
{
if (0 == CheckTetris(X-1, Y , currentTetris, game_board)) {
X--;
}
}
break;
case VK_RIGHT:
{
if (0 == CheckTetris(X + 1, Y, currentTetris, game_board)) {
X++;
}
}
break;
case VK_UP:
{
memcpy(tempTetris, currentTetris, sizeof(currentTetris));
rotateTetris(tempTetris);
if (0 == CheckTetris(X, Y, tempTetris, game_board)) {
rotateTetris(currentTetris);
}
}
break;
case VK_DOWN:
{
while (0 == CheckTetris(X, Y + 1, currentTetris, game_board)) {
Y++;
}
}
break;
default:
{
}
break;
}
}
break;
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hWnd, &ps);
// TODO: 在此处添加使用 hdc 的任何绘图代码...
DrawBackGround(hdc);
DrawTetris(hdc, X,Y, currentTetris);
EndPaint(hWnd, &ps);
}
break;
case WM_DESTROY:
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;
}
eof
天道酬勤