先打开VS,创建解决方案
选择windows应用程序
在源文件文件夹下新建tetris.cpp文件,用来写我们实现俄罗斯方块的代码
代码及其注释如下所示:
/*
创建窗口
win32窗口的创建过程主要有6部分
1.头文件与主函数、2.创建窗口结构体、3.注册窗口、4.创建窗口、5.显示窗口、6.消息循环、7.回调函数
头文件:windows.h
主函数:int WINAPI WinMain( HINSTANCE hlnstance, //句柄:一个数,窗口唯一标识
HINSTANCE hPrevlnstance, //前一个句柄
LPTSTR lpCmdLine,//传递给应用程序的命令行参数
int nCmdShow)//指定窗口的显示方式 隐藏 最大最小显示
返回值:int
WINAPI:调用约定, 主要是参数的入栈顺序,这个栈空间的清理者,__stdcall,APIENTRY,本质都是一样的
WinMain:主函数的写法,注意不是main
*/
#include<time.h>
#include<stdlib.h>
#include<windows.h>
//定时器ID
#define DEF_TIMER1 1234
//创建兼容性DC
void OnPaint(HDC hDc);
//显示方块
void PaintSpare(HDC hMemDC);
//随机小方块
int CreateRandmSqare();
//随机小方块贴进背景
void CopySqareToBack();
//初始化
void OnCreate();
//回车键函数
void OnReturn(HWND hWnd);
//方块下落
void SqareDwon();
//定时器相应函数
void OnTimer(HWND hWnd);
//方块停在最底下 0 不可以下落 1可以下落
int CanSgareDown();
//下落
int CanSgareDown2();
//将1变成2
void Change1To2();
//显示2
void ShowSqare2(HDC hMemDC);
//左键
void OnLeft(HWND hWnd);
//左移
void SqareLeft();
//方块在最左面 0 不可以左移 1可以左移
int CanSgareLeft();
//左移限制
int CanSgareLeft2();
//右键
void OnRight(HWND hWnd);
//右移
void SqareRight();
//方块在最右面 0 不可以右移 1可以右移
int CanSgareRight();
//右移限制
int CanSgareRight2();
//加速向下
void OnDown(HWND hWnd);
//变形 上键
void OnUp(HWND hWnd);
//3 * 3变形
void ChangeSqare();
//3 * 3变形限制
int CanSqareChangeSape();
//长条变形
void ChangeLineSqare();
//长条变形限制
int CanLineSqareChange();
//消除已满的行数
void DestroyOneLineSqare();
//显示分数
void ShowScore(HDC hMemDC);
//游戏结束
int CanGomeOver();
//7.回调函数
// 回调函数 一个窗口对应一个窗口句柄
//long类型 调用约定 函数名字(窗口句柄,无符号整形消息的ID, 参数 3无符号整形 4long 传递信息自己定可以)
LRESULT CALLBACK PELouSi(HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParan)
{
PAINTSTRUCT pt;
HDC hDC;//可以画的范围 也就是用户窗口可操作的范围(标识)
switch (nMsg)
{
case WM_CREATE://窗口消息处理程序接收的第一个消息-也是回掉函数的第一个消息-是WM_CREATE 这个消息只产生一次,一般用于初始化一些数据
OnCreate();
break;
//回掉函数的第二个消息
//当窗口显示区域的一部分显示内容或者全部变为“无效”,以至于必须“更新画面”时,将由这个消息通知程序
//窗口结构体的最后那个成员CS_HREDRAW | CS_VREDRAW,目的就是窗口大小发生变化的时候,产生WM_PAINT消息
//窗口重叠时,重叠部分渐渐出现时
case WM_TIMER://定时器消息
OnTimer(hWnd);
break;
case WM_PAINT:
hDC = BeginPaint(hWnd, &pt);//画窗口内容开始 有用getDC的
OnPaint(hDC);//画图的函数
EndPaint(hWnd, &pt);//画窗口内容结束
break;
case WM_KEYDOWN://WM_KEYDOWN键盘安下
switch (wParam)//wParam回掉函数第三个参数 区分是按得那个键
{
case VK_RETURN://回车键
OnReturn(hWnd);//开始
break;
case VK_LEFT://左键
OnLeft(hWnd);//左移
break;
case VK_RIGHT://右键
OnRight(hWnd);//右移
break;
case VK_UP://上键
OnUp(hWnd);//变形
break;
case VK_DOWN://下键
OnDown(hWnd);//加速
break;
}
break;
case WM_DESTROY://点×三种消息依次产生: WM_CLOSE -> WM_DESTROY销毁窗口 -> WM_QUIT退出消息 W:windows M:消息
KillTimer(hWnd, DEF_TIMER1);
PostQuitMessage(0);//传递退出消息
break;
}
return DefWindowProc(hWnd, nMsg, wParam, lParan);//功能 没有处理的消息系统自动处理 保证系统的连贯性 什么都不做 每次在窗口有点击、输入都会有消息
}
//1.头文件与主函数
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
//2.创建窗口结构体
//初始化窗口类
WNDCLASSEX wc;
HWND hWnd;
MSG mSg; //MSG 消息的结构体
//12个成员不能多不能少 要不 失败
wc.cbClsExtra = 0;//紧跟在窗口类尾部的一块额外的空间,不用设为0。
wc.cbSize = sizeof(WNDCLASSEX);//类的大小
wc.cbWndExtra = 0;//拓展窗口对话框
wc.hbrBackground = (HBRUSH)COLOR_SCROLLBAR;//背景颜色COLOR_BACKGROUND
wc.hCursor = NULL;//光标样式 LoadCursor(句柄系统定义填NULL 加载自定义填hInstance,样式 自定义添加资源文件)
wc.hIcon = NULL;//任务栏显示的图标 LoadIcon(句柄系统定义填NULL 加载自定义填hInstance,样式 自定义添加资源文件)
wc.hIconSm = NULL;//窗口左上角的图标 如果为空则默认为任务栏的图标
wc.hInstance = hInstance;//当前窗口的句柄 //句柄又系统传递
wc.lpfnWndProc = PELouSi;//回掉函数函数地址
wc.lpszClassName = L"elsfk";//窗口类的名字 名字不要重复 给系统看的 不是最上面那个名字
wc.lpszMenuName = NULL; //菜单
wc.style = CS_HREDRAW | CS_VREDRAW;///窗口显示风格 垂直刷新 水平刷新 最大化等
//3.注册窗口对象
if (0 == RegisterClassEx(&wc))//如果注册失败
{
//出错 不知道什么原因
int a = GetLastError();//用这个函数 返回一个值
return 0;
}
//4.创建窗口
hWnd = CreateWindowEx(WS_EX_TOPMOST, L"elsfk", L"俄罗斯方块", WS_OVERLAPPEDWINDOW, 100, 100, 500, 646, NULL, NULL, hInstance, NULL);
//(附加属性 (WS_EX_TOPMOST总是在最前端),
//窗口类的名字 名字不要重复 给系统看的 不是最上面那个名字 与上面的一样,
//窗口的名字 左上角的 人你看的... ,
//指定窗口的风格,
//int x;相对于桌面 坐标 是像素 左,
//int y;相对于桌面 坐标 是像素 上,
//宽度,
//高度,
//子句柄 子窗口,
//菜单的句柄 没有菜单NULL,
//当前实例句柄,
//(win下lp是指针类型)指向一个值得指针,多文档 多个编辑框);
if (NULL == hWnd) //窗口句柄 窗口的唯一标识
{
return 0;
}
//5.显示窗口
ShowWindow(hWnd, SW_SHOWNORMAL);//句柄,显示风格(最大化 最小化 默认nCmdShow等)
//隐藏显示返回0 正常显示返回非0
//6.消息循环
while (GetMessage(&mSg, NULL, 0, 0))//(指向MSG消息结构体的指针,窗口句柄(NULL与非NULL的区别NULL接收所以窗口消息非NULL接所填句柄的消息,3 4参数处理消息范围(0, 0是取所以范围))
//GetMessage取到消息返回非零值
{
//消息翻译 将输入设备的电信号转换成字符消息
TranslateMessage(&mSg);//参是一个指针指向结构体
//分发消息 分类 :标准消息 命令消息 通知消息 自定义消息
DispatchMessage(&mSg);//参是一个指针指向结构体
}
return 0;
}
/*
兼容性DC(就是在后台画好当前页面再给当前)
创建兼容性DC
HDC CreateCompatibleDC(HDC hdc);
创建兼容性位图
HBITMAP CreateCompatibleBitmap(HDC hdc, int nWidth, int nHeight);
将DC与位图绑定在一起
HGDIOBJ SelectObject(HDC hdc, HGDIOBJ hgdiobj);
释放DC
BOOL DeleteDC(HDC hdc);
将内存DC传递到窗口DC
BOOL BitBlt(HDC hdcDest, int nXDest, int nYDest, nt nWidth, int nHeight, HDC hdcSrc, int nXSrc, int nYSrc, DWORD dwRop);
(目标DC 窗口DC, 2 3参数 目标的起始位置 注意是基于我们的窗口, 4 5区域的大小, 源DC 也是我们的内存DC, 7 8内存图片的起始位置, 传递的方式)
返回值:失败返回0,成功返回非0
*/
/*
定时器:
启动定时器
UINT_PTR SetTimer(HWND hWnd, UINT_PTR nIDEvent, UINT uElapse, TIMERPROC lpTimerFunc);
(窗口句柄hWnd NULL, 定时器ID 不理会, 间隔时间 毫秒 1000ms = 1s, 设置为NULL 处理函数的地址);
返回值:成功返回非零
关闭定时器
BOOL KillTimer(HWND hWnd, UINT_PTR uIDEvent);
*/
/*
给方块图色
HBRUSH oldBrush;
创建一个颜色的画刷
HBRUSH newBrush = CreateSolidBrush(RGB(67, 132, 19));
绑定当前DC与画刷,返回系统默认画刷
oldBrush = SelectObject(hdc, newBrush);
使用完新画刷,把系统默认画刷选回来,返回创建的画刷
newBrush = SelectObject(hdc,oldBrush);
释放画刷句柄
DeleteObject(newBrush);
*/
//背景数组(二维数组)
char g_arrBackGroud[20][10] = { 0 };
//小方块数组
char g_arrSqare[2][4] = { 0 };
//标记小方块的形状
int g_nSqareID = -1;
// 记录位置
int g_nLine = -1;//行
int g_nList = -1;//列
//记分
int g_nScore = 0;
//函数实现
void OnPaint(HDC hDc)
{
//创建兼容性DC(dc编号)可以创建多个
HDC hMemDC = CreateCompatibleDC(hDc);
//位图(创建一张纸)
HBITMAP hBitmapBack = CreateCompatibleBitmap(hDc, 500, 646);//(,纸的大小)
//关联起来
SelectObject(hMemDC, hBitmapBack);
//显示方块
PaintSpare(hMemDC);
ShowSqare2(hMemDC);
//显示右面 显示分数
ShowScore(hMemDC);
//传递//源
BitBlt(hDc, 0, 0, 500, 600, hMemDC, 0, 0, SRCCOPY);
//释放DC
DeleteObject(hBitmapBack);//位图
DeleteDC(hMemDC);//编号
}
//显示分数
void ShowScore(HDC hMemDC)
{
char strScore[10] = { 0 };
Rectangle(hMemDC, 300, 0, 500, 646);//右边显示
itoa(g_nScore, strScore, 10);//转换成字符串
TextOut(hMemDC, 340, 100, L"得分:", strlen("得分:"));
TextOut(hMemDC, 400, 100, (LPCWSTR)strScore, strlen(strScore));//(句柄,x,y,一个字符串,字节数 有效的)
TextOut(hMemDC, 340, 180, L"回车开始", strlen("回车开始"));
TextOut(hMemDC, 340, 210, L"上键变形", strlen("上键变形"));
TextOut(hMemDC, 340, 240, L"下键加速", strlen("下键加速"));
TextOut(hMemDC, 340, 270, L"左键左移", strlen("左键左移"));
TextOut(hMemDC, 340, 300, L"右键右移", strlen("右键右移"));
TextOut(hMemDC, 350, 150, L"按键:", strlen("按键:"));
}
//初始化
void OnCreate()
{
srand((unsigned)time(NULL));
CreateRandmSqare();
CopySqareToBack();
}
//显示方块
void PaintSpare(HDC hMemDC)
{
int i = 0;
int j = 0;//i j 循环遍历用
//旧的画刷
HBRUSH hOldBrush;
//画刷 涂颜色
HBRUSH hNewBrush;
//画刷 涂颜色背景
hNewBrush = CreateSolidBrush(RGB(255, 255, 128));
//选入当前DC
hOldBrush = (HBRUSH)SelectObject(hMemDC, hNewBrush);
//画大方块
Rectangle(hMemDC, 0, 0, 300, 600);//(画板, 画窗口起始位置, 画结束位置 先横向 后竖向)
hNewBrush = (HBRUSH)SelectObject(hMemDC, hOldBrush);
DeleteObject(hNewBrush);
hNewBrush = CreateSolidBrush(RGB(0, 255, 0));
//选入当前DC
hOldBrush = (HBRUSH)SelectObject(hMemDC, hNewBrush);
//遍历
for (i = 0; i < 20; i++)//行
{
for (j = 0; j < 10; j++)//列
{
if (1 == g_arrBackGroud[i][j])
{
//画方块
Rectangle(hMemDC, j * 30, i * 30, j * 30 + 30, i * 30 + 30);
}
}
}
hNewBrush = (HBRUSH)SelectObject(hMemDC, hOldBrush);
DeleteObject(hNewBrush);
}
//随机小方块
int CreateRandmSqare()
{
int n = rand() % 7;
switch (n)//n
{
case 1:
g_arrSqare[0][0] = 1,g_arrSqare[0][1] = 1, g_arrSqare[0][2] = 0, g_arrSqare[0][3] = 0;
g_arrSqare[1][0] = 0, g_arrSqare[1][1] = 1, g_arrSqare[1][2] = 1, g_arrSqare[1][3] = 0;
g_nLine = 0;
g_nList = 3;
break;
case 2:
g_arrSqare[0][0] = 0,g_arrSqare[0][1] = 1, g_arrSqare[0][2] = 1, g_arrSqare[0][3] = 0;
g_arrSqare[1][0] = 1, g_arrSqare[1][1] = 1, g_arrSqare[1][2] = 0, g_arrSqare[1][3] = 0;
g_nLine = 0;
g_nList = 3;
break;
case 3:
g_arrSqare[0][0] = 1,g_arrSqare[0][1] = 1, g_arrSqare[0][2] = 1, g_arrSqare[0][3] = 0;
g_arrSqare[1][0] = 1, g_arrSqare[1][1] = 0, g_arrSqare[1][2] = 0, g_arrSqare[1][3] = 0;
g_nLine = 0;
g_nList = 3;
break;
case 4:
g_arrSqare[0][0] = 1, g_arrSqare[0][1] = 0, g_arrSqare[0][2] = 0, g_arrSqare[0][3] = 0;
g_arrSqare[1][0] = 1, g_arrSqare[1][1] = 1, g_arrSqare[1][2] = 1, g_arrSqare[1][3] = 0;
g_nLine = 0;
g_nList = 3;
break;
case 5:
g_arrSqare[0][0] = 0, g_arrSqare[0][1] = 1, g_arrSqare[0][2] = 1, g_arrSqare[0][3] = 0;
g_arrSqare[1][0] = 0, g_arrSqare[1][1] = 1, g_arrSqare[1][2] = 1, g_arrSqare[1][3] = 0;
break;
case 6:
g_arrSqare[0][0] = 1, g_arrSqare[0][1] = 1, g_arrSqare[0][2] = 1, g_arrSqare[0][3] = 1;
g_arrSqare[1][0] = 0, g_arrSqare[1][1] = 0, g_arrSqare[1][2] = 0, g_arrSqare[1][3] = 0;
g_nLine = 0;
g_nList = 4;
break;
case 0:
g_arrSqare[0][0] = 0, g_arrSqare[0][1] = 1, g_arrSqare[0][2] = 0, g_arrSqare[0][3] = 0;
g_arrSqare[1][0] = 1, g_arrSqare[1][1] = 1, g_arrSqare[1][2] = 1, g_arrSqare[1][3] = 0;
g_nLine = 0;
g_nList = 3;
break;
}
//小方块的ID
g_nSqareID = n;
return n;
}
//随机小方块贴进背景
void CopySqareToBack()
{
int i = 0;
int j = 0;
for (i = 0; i < 2; i++)
{
for (j = 0; j < 4; j++)
{
g_arrBackGroud[i][j + 3] = g_arrSqare[i][j];
}
}
}
//回车键函数
void OnReturn(HWND hWnd)
{
//打开定时器
SetTimer(hWnd, DEF_TIMER1, 600, NULL);
}
//方块下落
void SqareDwon()
{
int i = 0;
int j = 0;
for (i = 19; i >= 0; i--)
{
for (j = 0; j < 10; j++)
{
if (1 == g_arrBackGroud[i][j])
{
g_arrBackGroud[i + 1][j] = g_arrBackGroud[i][j];
g_arrBackGroud[i][j] = 0;
}
}
}
}
//定时器相应函数
void OnTimer(HWND hWnd)
{
//得到DC的函数
HDC hDc = GetDC(hWnd);
//判断是否能下落
if (1 == CanSgareDown() && 1 == CanSgareDown2())
{
//方块下落
SqareDwon();
g_nLine++;
}
else
{
//1变成2
Change1To2();
//消除已满的行数
DestroyOneLineSqare();
//游戏结束
if (0 == CanGomeOver())
{
//结束
KillTimer(hWnd, DEF_TIMER1);
return ;
}
//产生随机块
CreateRandmSqare();
//复制到背景上
CopySqareToBack();
}
//显示方块
//PaintSpare(hDc);
OnPaint(hDc);
//释放DC
ReleaseDC(hWnd, hDc);//内核对象 要程序员释放
}
//方块停在最底下 0 不可以下落 1可以下落
int CanSgareDown()
{
for (int i = 0; i < 10; i++)
{
if (1 == g_arrBackGroud[19][i])
{
return 0;
}
}
return 1;
}
//将1变成2
void Change1To2()
{
for (int i = 0; i < 20; i++)
{
for (int j = 0; j < 10; j++)
{
if (1 == g_arrBackGroud[i][j])
{
g_arrBackGroud[i][j] = 2;
}
}
}
}
//显示2
void ShowSqare2(HDC hMemDC)
{
//旧的画刷
HBRUSH hOldBrush;
//画刷 涂颜色
HBRUSH hNewBrush = CreateSolidBrush(RGB(109, 249, 252));
//选入当前DC
hOldBrush = (HBRUSH)SelectObject(hMemDC, hNewBrush);
for (int i = 0; i < 20; i++)
{
for (int j = 0; j < 10; j++)
{
if (2 == g_arrBackGroud[i][j])
{
Rectangle(hMemDC, j * 30, i * 30, j * 30 + 30, i * 30 + 30);
}
}
}
hNewBrush = (HBRUSH)SelectObject(hMemDC, hOldBrush);
DeleteObject(hNewBrush);
}
//下落
int CanSgareDown2()
{
for (int i = 19; i >= 0; i--)
{
for (int j = 0; j < 10; j++)
{
if (1 == g_arrBackGroud[i][j] && 2 == g_arrBackGroud[i + 1][j])
{
return 0;
}
}
}
return 1;
}
//左键
void OnLeft(HWND hWnd)
{
//方块向左移
if (1 == CanSgareLeft() && 1 == CanSgareLeft2())
{
//得到DC的函数
HDC hDc = GetDC(hWnd);
g_nList--;
SqareLeft();
//显示方块
OnPaint(hDc);
//释放DC
ReleaseDC(hWnd, hDc);
}
}
//左移
void SqareLeft()
{
for (int i = 0; i < 20; i++)
{
for (int j = 0; j < 10; j++)
{
if (1 == g_arrBackGroud[i][j])
{
g_arrBackGroud[i][j - 1] = g_arrBackGroud[i][j];
g_arrBackGroud[i][j] = 0;
}
}
}
}
//方块在最左面 0 不可以左移 1可以左移
int CanSgareLeft()
{
for (int i = 0; i < 20; i++)
{
if (1 == g_arrBackGroud[i][0])
{
return 0;
}
}
return 1;
}
//左移限制
int CanSgareLeft2()
{
for (int i = 0; i < 20; i++)
{
for (int j = 0; j < 10; j++)
{
if (1 == g_arrBackGroud[i][j] && 2 == g_arrBackGroud[i][j - 1])
{
return 0;
}
}
}
return 1;
}
//右键
void OnRight(HWND hWnd)
{
//右移
if (1 == CanSgareRight() && 1 == CanSgareRight2())
{
//得到一个DC函数
HDC hDc = GetDC(hWnd);
g_nList++;
SqareRight();
//显示方块
OnPaint(hDc);
//释放DC
ReleaseDC(hWnd, hDc);
}
}
//右移
void SqareRight()
{
for (int i = 0; i < 20; i++)
{
for (int j = 9; j >= 0; j--)
{
if (1 == g_arrBackGroud[i][j])
{
g_arrBackGroud[i][j + 1] = g_arrBackGroud[i][j];
g_arrBackGroud[i][j] = 0;
}
}
}
}
//方块在最右面 0 不可以右移 1可以右移
int CanSgareRight()
{
for (int i = 0; i < 20; i++)
{
if (1 == g_arrBackGroud[i][19])
{
return 0;
}
}
return 1;
}
//右移限制
int CanSgareRight2()
{
for (int i = 0; i < 20; i++)
{
for (int j = 0; j < 10; j++)
{
if (1 == g_arrBackGroud[i][j] && 2 == g_arrBackGroud[i][j + 1])
{
return 0;
}
}
}
return 1;
}
//加速向下
void OnDown(HWND hWnd)
{
OnTimer(hWnd);
}
//变形 上键
void OnUp(HWND hWnd)
{
HDC hDc = GetDC(hWnd);
switch (g_nSqareID)//g_nSqareID
{
case 0:
case 1:
case 2:
case 3:
case 4://普通变形
if (1 == CanSqareChangeSape())//3 * 3变形限制
{
ChangeSqare();//3 * 3变形
}
else
{
return;
}
break;
case 5:// 正方形
return;
break;
case 6://长条形
if (1 == CanLineSqareChange())//长条变形限制
{
ChangeLineSqare();//长条变形
}
break;
}
//显示
OnPaint(hDc);
}
//3 * 3变形
void ChangeSqare()
{
int nTemp = 2;
//用于交换的小方块
char arrSqare[3][3] = { 0 };
//小方块复制出来
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
arrSqare[i][j] = g_arrBackGroud[g_nLine + i][g_nList + j];
}
}
//变形后复制回去
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
g_arrBackGroud[g_nLine + i][g_nList + j] = arrSqare[nTemp][i];
nTemp--;
}
nTemp = 2;
}
}
//3 * 3变形限制
int CanSqareChangeSape()
{
//限制与其他小方块连在一起变形
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
if (2 == g_arrBackGroud[g_nLine + i][g_nList + j])
{
return 0;
}
}
}
//限制超出边境变形
/*if (g_nList < 0 || g_nList + 2 > 9) 第一种不好有些限制不能进行变形
{
return 0;
}*/
if (g_nList < 0)
{
g_nList = 0;
}
else if (g_nList + 2 > 9)
{
g_nList = 7;
}
return 1;
}
//长条变形
void ChangeLineSqare()
{
if (1 == g_arrBackGroud[g_nLine][g_nList - 1])//横的出现
{
//清零
g_arrBackGroud[g_nLine][g_nList - 1] = 0;
g_arrBackGroud[g_nLine][g_nList + 1] = 0;
g_arrBackGroud[g_nLine][g_nList + 2] = 0;
if (2 == g_arrBackGroud[g_nLine + 1][g_nList])
{
//赋值
g_arrBackGroud[g_nLine - 1][g_nList] = 1;
g_arrBackGroud[g_nLine - 2][g_nList] = 1;
g_arrBackGroud[g_nLine - 3][g_nList] = 1;
}
else if (2 == g_arrBackGroud[g_nLine + 2][g_nList])
{
//赋值
g_arrBackGroud[g_nLine + 1][g_nList] = 1;
g_arrBackGroud[g_nLine - 1][g_nList] = 1;
g_arrBackGroud[g_nLine - 2][g_nList] = 1;
}
else
{
//赋值
g_arrBackGroud[g_nLine - 1][g_nList] = 1;
g_arrBackGroud[g_nLine + 1][g_nList] = 1;
g_arrBackGroud[g_nLine + 2][g_nList] = 1;
}
}
else//竖的出现
{
//清零
g_arrBackGroud[g_nLine - 1][g_nList] = 0;
g_arrBackGroud[g_nLine + 1][g_nList] = 0;
g_arrBackGroud[g_nLine + 2][g_nList] = 0;
if (2 == g_arrBackGroud[g_nLine][g_nList + 1] || 9 == g_nList)
{
//赋值
g_arrBackGroud[g_nLine][g_nList - 1] = 1;
g_arrBackGroud[g_nLine][g_nList - 2] = 1;
g_arrBackGroud[g_nLine][g_nList - 3] = 1;
//标记改变
g_nList = g_nList - 2;
}
else if (2 == g_arrBackGroud[g_nLine][g_nList + 2] || 8 == g_nList)
{
//赋值
g_arrBackGroud[g_nLine][g_nList + 1] = 1;
g_arrBackGroud[g_nLine][g_nList - 1] = 1;
g_arrBackGroud[g_nLine][g_nList - 2] = 1;
//标记改变
g_nList = g_nList - 1;
}
else if (2 == g_arrBackGroud[g_nLine][g_nList - 1] || 0 == g_nList)
{
//赋值
g_arrBackGroud[g_nLine][g_nList + 1] = 1;
g_arrBackGroud[g_nLine][g_nList + 3] = 1;
g_arrBackGroud[g_nLine][g_nList + 2] = 1;
//标记改变
g_nList = g_nList + 1;
}
else
{
//赋值
g_arrBackGroud[g_nLine][g_nList - 1] = 1;
g_arrBackGroud[g_nLine][g_nList + 1] = 1;
g_arrBackGroud[g_nLine][g_nList + 2] = 1;
}
}
}
//长条变形限制
int CanLineSqareChange()
{
int i = 0, j = 0;
for (i = 1; i < 4; i++)
{
if (2 == g_arrBackGroud[g_nLine][g_nList + i] || g_nList + i > 9)
{
break;
}
}
for (j = 1; j < 4; j++)
{
if (2 == g_arrBackGroud[g_nLine][g_nList - j] || g_nList - j < 0)
{
break;
}
}
if ((i - 1 + j - 1) < 3)
{
return 0;
}
return 1;
}
//消除已满的行数
void DestroyOneLineSqare()
{
int i = 0, j = 0;
int nSum = 0;
int nTempi = 0;
for (i = 19; i >= 0; i--)
{
for (j = 0; j < 10; j++)
{
nSum += g_arrBackGroud[i][j];
}
if (20 == nSum)
{
//消除一行
for (nTempi = i - 1; nTempi >= 10; nTempi--)
{
for (j = 0; j < 10; j++)
{
g_arrBackGroud[nTempi + 1][j] = g_arrBackGroud[nTempi][j];
}
}
//记分用
g_nScore++;
//为了能消除多行
i = 20;
}
//清零
nSum = 0;
}
}
//游戏结束
int CanGomeOver()
{
int i = 0;
for (i = 0; i < 10; i++)
{
if (2 == g_arrBackGroud[0][i])
{
//游戏结束
MessageBox(NULL, L"游戏结束", L"提示", MB_OK);//消息盒子(句柄 可写可不写,字符串指针 内容, 字符串指针, 风格)
return 0;
}
}
return 1;
}
接下来我们来玩一玩这个游戏
点击调试
按回车键开启计时器
开始游戏
一切工作正常
那么今天的教程就到这里了