当前位置: 首页 > 工具软件 > 变色方块 > 使用案例 >

WIN32 俄罗斯方块

田鹤轩
2023-12-01

WIN32 主程序

#include<Windows.h>
#include"Tetris.h"


LRESULT CALLBACK WndProc(HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam);      // 回调函数

// WINAPI 调用约定
// 当前窗口句柄 HINSTANCE hInstance
// 前一个窗口句柄 HINSTANCE hPreInstance
// 指定命令行参数 LPTSTR lpCmdLine
// 窗口显示方式
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPreInstance, LPTSTR lpCmdLine, int nCmdShow)
{
	WNDCLASSEX wc;                           // 初始化窗口类
	wc.cbClsExtra = 0;
	wc.cbSize = sizeof(WNDCLASSEX);
	wc.cbWndExtra = 0;
	wc.hbrBackground = (HBRUSH)COLOR_WINDOW; // 窗口背景颜色
	wc.hCursor = NULL;                       // 鼠标光标
	wc.hIcon = NULL;                         // 窗口大图标
	wc.hIconSm = NULL;                       // 窗口的小图标
	wc.hInstance = hInstance;                // 窗口句柄
	wc.lpfnWndProc = WndProc;                // 回调函数地址
	wc.lpszClassName = "Tetris";             // 窗口名字,给操作系统看的
	wc.lpszMenuName = NULL;                  // 菜单名字
	wc.style = CS_HREDRAW | CS_VREDRAW;      // 窗口风格(垂直刷新和水平刷新)

	// 12个成员
	

	if (RegisterClassEx(&wc) == 0)              // 注册窗口对象
		return 0;
	HWND hWnd = CreateWindowEx(WS_EX_TOPMOST,"Tetris", "俄罗斯方块",
		WS_OVERLAPPEDWINDOW,100,100,500,650,NULL,
		NULL, hInstance,NULL);                  // 创建窗口
	if (hWnd == NULL)
		return 0;

	ShowWindow(hWnd, nCmdShow);                 // 显示窗口
		
	MSG mSg;                                    // 消息结构体
	
	while (GetMessage(&mSg, NULL, 0, 0))        // 消息循环
	{
		TranslateMessage(&mSg);                 // 翻译消息
		DispatchMessage(&mSg);                  // 分发消息
	}
	
	return 0;
}

LRESULT CALLBACK WndProc(HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam)       // 回调函数
{
	PAINTSTRUCT pt;
	HDC hDC;          
	switch (nMsg)
	{
	case WM_CREATE:   // 窗口创建初期只产生一次、
		// 初始化数据
		OnCreate();
		break;

	case WM_PAINT:
		hDC = BeginPaint(hWnd,&pt);       // 窗口可操作区域的标识
		OnPaint(hDC);                     // 绘制界面

		EndPaint(hWnd, &pt);
		break;

	case WM_TIMER:
		OnTimer(hWnd);                    // 定时器相应函数
		break;

	case WM_KEYDOWN:
		switch (wParam)
		{
		case VK_RETURN:
			OnReturn(hWnd);                      // 回车响应函数
			break;
		case VK_LEFT:
			OnLeft(hWnd);                        // 左键响应函数
			break;
		case VK_RIGHT:
			OnRight(hWnd);                       // 右键响应函数
			break;
		case VK_UP:
			OnChangeSquare(hWnd);                // 上键响应函数
			break;
		case VK_DOWN:                            // 下键响应函数
			OnDown(hWnd);
			break;
		}
		break;

	case WM_DESTROY:
		KillTimer(hWnd, DEF_TIMER);                      // 关闭定时器
		PostQuitMessage(0);
		break;


	}
	return DefWindowProc(hWnd, nMsg, wParam, lParam);     // 让系统自动处理一些消息
}

俄罗斯方块声明函数

#pragma once
#include<Windows.h>
#include<stdio.h>
#include<time.h>

#define DEF_TIMER 1234        // 定时器id

void OnPaint(HDC hDc);          //  显示界面
void PaintSquare(HDC hDc);      //  画方块
void CreateRandomSquare();      // 创建随机块
void CopySquareToBack();        // 随机快贴背景
void Change1To2();              // 方块落到最底部将1变为2
void ShowSquare2(HDC  hMemDC);  // 显示底部方块


void OnCreate();                // 创建背景随机块
void OnReturn(HWND hWnd);       // 处理回车按键
void OnTimer(HWND hWnd);        // 定时器响应函数
void OnLeft(HWND hWnd);         // 处理左键
void OnRight(HWND hWnd);        // 处理右键
void OnDown(HWND hWnd);         // 处理下键
void OnChangeSquare(HWND hWnd); // 处理按上键方块变形


int CanSquareDown();           // 0代表方块不可以下落,1代表方块可以下落
int CanSquareDown2();          // 方块下落遇到障碍判断
int CanSquareLeft();           // 判断方块是否能左移
int CanSquareLeft2();          // 判断方块向左移动与存在方块碰撞
int CanSquareRight();          // 判断方块与右墙壁的碰撞
int CanSquareRight2();         // 检查方块与右方块的碰撞
int CanSquareChangeShape();    // 判断方块是否能变形
int CanLineSquareChange();     // 判断长条是否能变形


void SquareDown();             // 方块下落
void SquareLeft();             // 方块左移
void SquareRight();            // 方块右动

void ChangeSquare();           // 方块变形函数
void ChangeLineSquare();       // 长条变形
void DestroyOneLineSquare();   // 消除一行方块
void ShowScore(HDC hHemDC);    // 显示分数
int CanGameOver();             // 游戏结束弹窗

 

具体函数实现

#include "Tetris.h"


char g_arrBackGround[20][10] = { 0 };                   // 背景数组
char g_arrSquare[2][4] = { 0 };                         // 方块类型的小数组
int g_nSquareID;                                        // 方块的类型编号
int g_nLine = -1;                                       // 方块包围盒的左上角行
int g_nList = -1;                                       // 方块包围盒的左上角列
int g_nScore = 0;                                       // 计分

void OnPaint(HDC hDc)
{
	HDC hMemDC = CreateCompatibleDC(hDc);               // 创建兼容性DC
	HBITMAP hBitmapBack = CreateCompatibleBitmap(hDc, 500, 600);    // 创建一张纸
	SelectObject(hMemDC, hBitmapBack);                     // 窗口和纸关联在一起

	PaintSquare(hMemDC);                                // 画方块
	ShowSquare2(hMemDC);                                // 落到底部的方块,画颜色
	ShowScore(hMemDC);                                  // 界面显示分数
	BitBlt(hDc, 0, 0, 500, 600, hMemDC, 0, 0, SRCCOPY); // 内存DC复制到窗口
	

	DeleteObject(hBitmapBack);                          // 释放内存
	DeleteDC(hMemDC);
}

void OnCreate()
{
	srand((unsigned int)time(NULL));                   // 当前系统时间作为随机数种子
	CreateRandomSquare();                              // 创建随机方块
	CopySquareToBack();                                // 将随机方块贴到背景
}

void PaintSquare(HDC hMemDC)
{
	Rectangle(hMemDC, 0, 0, 300, 600);                  // 画矩形框    

	HGDIOBJ hOldBrush;
	HGDIOBJ hNewBrush = CreateSolidBrush(RGB(63, 191, 49));
	hOldBrush = SelectObject(hMemDC, hNewBrush);
	for (int i = 0; i < 20; i++)
	{
		for (int j = 0; j < 10; j++)
		{
			if (g_arrBackGround[i][j] == 1)
			{
				Rectangle(hMemDC, j * 30, i * 30, (j + 1) * 30, (i + 1) * 30);
			}
		}
	}
	hNewBrush = SelectObject(hMemDC, hOldBrush);
	DeleteObject(hNewBrush);

}

void CreateRandomSquare()
{
	int n;
	n = rand() % 7;
	switch (n)
	{
	case 0:
		g_arrSquare[0][0] = 1, g_arrSquare[0][1] = 1, g_arrSquare[0][2] = 0, g_arrSquare[0][3] = 0;
		g_arrSquare[1][0] = 0, g_arrSquare[1][1] = 1, g_arrSquare[1][2] = 1, g_arrSquare[1][3] = 0;
		g_nLine = 0;
		g_nList = 3;
		break;
	case 1:
		g_arrSquare[0][0] = 0, g_arrSquare[0][1] = 1, g_arrSquare[0][2] = 1, g_arrSquare[0][3] = 0;
		g_arrSquare[1][0] = 1, g_arrSquare[1][1] = 1, g_arrSquare[1][2] = 0, g_arrSquare[1][3] = 0;
		g_nLine = 0;
		g_nList = 3;
		break;
	case 2:
		g_arrSquare[0][0] = 1, g_arrSquare[0][1] = 0, g_arrSquare[0][2] = 0, g_arrSquare[0][3] = 0;
		g_arrSquare[1][0] = 1, g_arrSquare[1][1] = 1, g_arrSquare[1][2] = 1, g_arrSquare[1][3] = 0;
		g_nLine = 0;
		g_nList = 3;
		break;
	case 3:
		g_arrSquare[0][0] = 0, g_arrSquare[0][1] = 0, g_arrSquare[0][2] = 1, g_arrSquare[0][3] = 0;
		g_arrSquare[1][0] = 1, g_arrSquare[1][1] = 1, g_arrSquare[1][2] = 1, g_arrSquare[1][3] = 0;
		g_nLine = 0;
		g_nList = 3;
		break;
	case 4:
		g_arrSquare[0][0] = 0, g_arrSquare[0][1] = 1, g_arrSquare[0][2] = 0, g_arrSquare[0][3] = 0;
		g_arrSquare[1][0] = 1, g_arrSquare[1][1] = 1, g_arrSquare[1][2] = 1, g_arrSquare[1][3] = 0;
		g_nLine = 0;
		g_nList = 3;
		break;
	case 5:
		g_arrSquare[0][0] = 0, g_arrSquare[0][1] = 1, g_arrSquare[0][2] = 1, g_arrSquare[0][3] = 0;
		g_arrSquare[1][0] = 0, g_arrSquare[1][1] = 1, g_arrSquare[1][2] = 1, g_arrSquare[1][3] = 0;
		g_nLine = 0;
		g_nList = 4;
		break;
	case 6:
		g_arrSquare[0][0] = 1, g_arrSquare[0][1] = 1, g_arrSquare[0][2] = 1, g_arrSquare[0][3] = 1;
		g_arrSquare[1][0] = 0, g_arrSquare[1][1] = 0, g_arrSquare[1][2] = 0, g_arrSquare[1][3] = 0;
		g_nLine = 0;
		g_nList = 4;
		break;
	}

	g_nSquareID = n;

}

void CopySquareToBack()
{
	for (int i = 0; i < 2; i++)
	{
		for (int j = 0; j < 4; j++)
		{
			g_arrBackGround[i][j+3] = g_arrSquare[i][j];
		}
	}
}

void OnReturn(HWND hWnd)
{
	SetTimer(hWnd, DEF_TIMER, 400, NULL);       // 直接调用定时器函数
}

void SquareDown()
{
	for (int i = 19; i >= 0; i--)
	{
		for (int j = 0; j < 10; j++)
		{
			if (g_arrBackGround[i][j] == 1)
			{
				g_arrBackGround[i + 1][j] = g_arrBackGround[i][j];
				g_arrBackGround[i][j] = 0;
			}
		}
	}
}

void OnTimer(HWND hWnd)
{
	HDC hDc = GetDC(hWnd);
	if (CanSquareDown() == 1 && CanSquareDown2() == 1)
	{
		SquareDown();             // 如果方块能下落,方块下落
		g_nLine++;
	}
	else
	{              
		Change1To2();             // 当方块落到底部时,将1变为2
		DestroyOneLineSquare();   // 消除方块
		if (CanGameOver() == 0)
		{
			KillTimer(hWnd, DEF_TIMER);
			return;
		}
		CanGameOver();            // 判断游戏结束
		CreateRandomSquare();     // 如果方块落到底部,产生新的方块
		CopySquareToBack();
	}
       
	OnPaint(hDc);
	ReleaseDC(hWnd, hDc);  // 释放

}

int CanSquareDown()
{
	for (int i = 0; i < 10; i++)
	{
		if (g_arrBackGround[19][i] == 1)
		{
			return 0;
		}
	}
	return 1;
}

void Change1To2()
{
	for (int i = 0; i < 20; i++)
	{
		for (int j = 0; j < 10; j++)
		{
			if (g_arrBackGround[i][j] == 1)
			{
				g_arrBackGround[i][j] = 2;
			}
		}
	}
}

void ShowSquare2(HDC  hMemDC)
{
	HGDIOBJ hOldBrush;
	HGDIOBJ hNewBrush = CreateSolidBrush(RGB(233, 27, 182));  // 创建一个画刷
	hOldBrush = SelectObject(hMemDC, hNewBrush);
	for (int i = 0; i < 20; i++)
	{
		for (int j = 0; j < 10; j++)
		{
			if (g_arrBackGround[i][j] == 2)
			{
				Rectangle(hMemDC, j * 30, i * 30, (j + 1) * 30, (i + 1) * 30);
			}
		}
	}
	hNewBrush = SelectObject(hMemDC, hOldBrush);
	DeleteObject(hNewBrush);
}

int CanSquareDown2()
{
	for (int i = 19; i >=0; i--)
	{
		for (int j = 0; j < 10; j++)
		{
			if (g_arrBackGround[i][j] == 1 && g_arrBackGround[i+1][j] == 2)
			{
				return 0;
			}
		}
	}
	return 1;
}

void OnLeft(HWND hWnd)
{
	
	if (CanSquareLeft() == 1 && CanSquareLeft2()==1)
	{
		HDC hDc = GetDC(hWnd);
		SquareLeft();          // 方块向左移
		g_nList--;
		OnPaint(hDc);
		ReleaseDC(hWnd, hDc);
	}
	
}

void SquareLeft()
{
	for (int i = 0; i < 20; i++)
	{
		for (int j = 0; j < 10; j++)
		{
			if (g_arrBackGround[i][j] == 1)
			{
				g_arrBackGround[i][j-1] = g_arrBackGround[i][j];
				g_arrBackGround[i][j] = 0;
			}
		}
	}
}

int CanSquareLeft()
{
	for (int i = 0; i < 20; i++)
	{
		if (1 == g_arrBackGround[i][0])
		{
			return 0;
		}
	}
	return 1;
}

int CanSquareLeft2()
{
	for (int i = 0; i < 20; i++)
	{
		for (int j = 0; j < 10; j++)
		{
			if (g_arrBackGround[i][j] == 1 && g_arrBackGround[i][j - 1] == 2)
				return 0;
		}
	}
	return 1;
}

void OnRight(HWND hWnd)
{
	
	
	if (CanSquareRight() == 1 && CanSquareRight2()==1)
	{
		HDC hDc = GetDC(hWnd);
		SquareRight();
		g_nList++;
		OnPaint(hDc);
		ReleaseDC(hWnd, hDc);
	}
	
}

void SquareRight()
{
	for (int i = 0; i < 20; i++)
	{
		for (int j = 9; j >= 0; j--)
		{
			if (g_arrBackGround[i][j] == 1)
			{
				g_arrBackGround[i][j + 1] = g_arrBackGround[i][j];
				g_arrBackGround[i][j] = 0;
			}
		}
	}
}

int CanSquareRight()
{
	for (int i = 0; i < 20; i++)
	{
		if (g_arrBackGround[i][9] == 1)
		{
			return 0;
		}
	}
	return 1;
}

int CanSquareRight2()
{
	for (int i = 0; i < 20; i++)
	{
		for (int j = 9; j >= 0; j--)
		{
			if (g_arrBackGround[i][j] == 1 && g_arrBackGround[i][j+1]==2)
			{
				return 0;
			}
		}
	}
	return 1;
}

void OnDown(HWND hWnd)
{
	OnTimer(hWnd);
}

void OnChangeSquare(HWND hWnd)
{
	HDC hDc = GetDC(hWnd);
	switch (g_nSquareID)
	{
	case 0:
	case 1:
	case 2:
	case 3:
	case 4:
		if (CanSquareChangeShape() == 1)
			ChangeSquare();
		else
			return;
		break;
	case 5:
		return;          // 正方形不变形
	case 6:
		if (CanLineSquareChange() == 1)
			ChangeLineSquare();

		
		break;
	}

	OnPaint(hDc);
	ReleaseDC(hWnd, hDc);
}

void ChangeSquare()
{
	char arrSquare[3][3] = { 0 };
	
	for (int i = 0; i < 3; i++)
	{
		for (int j = 0; j < 3; j++)          // 背景块复制出来
		{
			arrSquare[i][j] = g_arrBackGround[g_nLine + i][g_nList + j];      
		}
	}

	int nTemp;
	for (int i = 0; i < 3; i++)
	{
		nTemp = 2;
		for (int j = 0; j < 3; j++)
		{
			g_arrBackGround[g_nLine + i][g_nList + j] = arrSquare[nTemp][i];
			nTemp--;
		}
	}
}

int CanSquareChangeShape()
{
	for (int i = 0; i < 3; i++)
	{
		for (int j = 0; j < 3; j++)
		{
			if (g_arrBackGround[g_nLine + i][g_nList + j] == 2)
				return 0;
		}
	}

	if (g_nList < 0)
		g_nList = 0;
	else if (g_nList > 7)
		g_nList = 7;
	return 1;
}

void ChangeLineSquare()
{
	if (g_arrBackGround[g_nLine][g_nList - 1] == 1)
	{
		// 清零
		g_arrBackGround[g_nLine][g_nList - 1] = 0;
		g_arrBackGround[g_nLine][g_nList + 1] = 0;
		g_arrBackGround[g_nLine][g_nList + 2] = 0;

		if (g_arrBackGround[g_nLine + 1][g_nList] == 2)
		{
			g_arrBackGround[g_nLine - 3][g_nList] = 1;
			g_arrBackGround[g_nLine - 2][g_nList] = 1;
			g_arrBackGround[g_nLine - 1][g_nList] = 1;
			//g_nLine -= 2;
			
		}
		else if(g_arrBackGround[g_nLine + 2][g_nList] == 2)
		{
			g_arrBackGround[g_nLine + 1][g_nList] = 1;
			g_arrBackGround[g_nLine - 1][g_nList] = 1;
			g_arrBackGround[g_nLine - 2][g_nList] = 1;
			//g_nLine--;
		
		}
		else
		{
			// 元素赋值
			g_arrBackGround[g_nLine - 1][g_nList] = 1;
			g_arrBackGround[g_nLine + 1][g_nList] = 1;
			g_arrBackGround[g_nLine + 2][g_nList] = 1;
		}
		
	}
	else
	{
		// 清零
		g_arrBackGround[g_nLine - 1][g_nList] = 0;
		g_arrBackGround[g_nLine + 1][g_nList] = 0;
		g_arrBackGround[g_nLine + 2][g_nList] = 0;
		if (g_arrBackGround[g_nLine][g_nList + 1] == 2 || g_nList==9)
		{
			g_arrBackGround[g_nLine][g_nList - 1] = 1;
			g_arrBackGround[g_nLine][g_nList - 2] = 1;
			g_arrBackGround[g_nLine][g_nList - 3] = 1;
			g_nList -= 2;
		}
		else if (g_arrBackGround[g_nLine][g_nList + 2] == 2|| g_nList ==8)
		{
			g_arrBackGround[g_nLine][g_nList + 1] = 1;
			g_arrBackGround[g_nLine][g_nList - 1] = 1;
			g_arrBackGround[g_nLine][g_nList - 2] = 1;
			g_nList -= 2;
		}
		else if (g_arrBackGround[g_nLine][g_nList - 1] == 2 || g_nList == 0)
		{
			g_arrBackGround[g_nLine][g_nList + 1] = 1;
			g_arrBackGround[g_nLine][g_nList + 2] = 1;
			g_arrBackGround[g_nLine][g_nList + 3] = 1;
			g_nList++;
		}

		else
		{
			g_arrBackGround[g_nLine][g_nList - 1] = 1;
			g_arrBackGround[g_nLine][g_nList + 1] = 1;
			g_arrBackGround[g_nLine][g_nList + 2] = 1;
		}
	
		
	}
}

int CanLineSquareChange()
{
	int i, j;
	for (i = 1; i < 4; i++)
	{
		if (g_arrBackGround[g_nLine][g_nList + i] == 2
			|| g_nList+i>9)
		{
			break;
		}
	}
	for (j = 1; j < 4; j++)
	{
		if (g_arrBackGround[g_nLine][g_nList - j] == 2 || g_nList - j < 0)
		{
			break;
		}
	}

	if (i - 1 + j - 1 < 3)
		return 0;
	
	return 1;
	
}

void DestroyOneLineSquare()
{
	int nSum = 0;
	for (int i = 19; i >= 0; i--)
	{
		for (int j = 0; j < 10; j++)
		{
			nSum += g_arrBackGround[i][j];
		}
		if (nSum == 20)
		{
			g_nScore += 10;
			for (int k = i - 1; k >= 0; k--)
			{
				for (int l = 0; l < 10; l++)
				{
					g_arrBackGround[k + 1][l] = g_arrBackGround[k][l];
				}
			}
			i = 20;
		}
		nSum = 0;
	}

}

void ShowScore(HDC hMemDC)
{
	char strScore[10] = { 0 };                                     // 分数字符串
	Rectangle(hMemDC, 300, 0, 500, 600);
	sprintf_s(strScore, "%d", g_nScore, strlen(strScore));
	TextOut(hMemDC, 400, 100, strScore, strlen(strScore));
}

int CanGameOver()
{
	for (int i = 0; i < 10; i++)
	{
		if (g_arrBackGround[0][i] == 2)
		{
			MessageBox(NULL,"GameOver","提示",MB_OK);           // 游戏结束
			return 0;
		}
	}
	return 1;
}

 

 

 类似资料: