这是我跟着一个视频教程做的。先看效果,后上代码,核心是二维数组(矩阵)的遍历和win32的一些基础,有时间谈谈细节。
我使用的是vc++6.0,更高版本也可以,vc++6.0下载地址:
1.打开vs,新建项目:右上角依次打开File->选择New... 或者直接Ctr+N;
2.输入项目名字,比如我输入Russia,你接下来可以选择你的项目存放路径;
3.点击Win32 Application,然后单击OK按钮,也可以直接双击Win32 Application;
4.单选按钮默认为An empty project,我们无须更改什么,直接点击Finish;
5.弹出的New Project Information对话框直接选择ok;
6.这是一个空项目,我们需要为其添加我们的c程序,类似第1步的方法Ctrl+N打开创建文件对话框;
7.填写文件名字,比如main.c,然后点击选择C++ Source File,点击ok,或者填完文件名后直接双击;
8.文件创建好后,光标会在工作台上闪烁(背景由灰变白),你就可以在上面编辑main.c文件了。复制下面的代码到你的main.c文件里:
#include <windows.h>
#include <time.h>
#define DEF_TIMER1 1234
// 背景数组
char g_arrBackGround[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;
LRESULT CALLBACK PEluosi(HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam);
void OnPaint(HDC hdc);
void CreateRandomSqare();
void OnCreate();
void CopySqareToBack();
void PaintSqare(HDC hMenDc);
void OnReturn();
void SqareDown();
void OnTimer(HWND hWnd);
int CanSqareDown();
void Change1To2();
void PaintSqare2(HDC hMenDc);
int CanSqareDown2();
void OnLeft(HWND hWnd);
void SqareLeft();
int CanSqareLeft();
int CanSqareLeft2();
void OnRight(HWND hWnd);
void SqareRight();
int CanSqareRight();
int CanSqareRight2();
void OnDown(HWND hWnd);
void OnChangeSqare(HWND hWnd);
void ChangeSqare();
int CanSqareChangeShape();
void ChangeLineSqare();
int CanLineSqareChange();
void DestroyOneLineSqare();
void ShowScore(HDC hMenDc);
int CanGameOver();
// 1.WINAPI:调用约定
//1号参数句柄 一个整数, 窗口的唯一标识,2号参数 前一个 没什么用 , 3号参数 命令行参数
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPreInstance, LPTSTR IpCmdLine, int nCmdShow)
{
//初始化窗口类
WNDCLASSEX wc;
HWND hWnd;
MSG msg;
wc.cbClsExtra = 0;
wc.cbSize = sizeof(WNDCLASSEXA);
wc.cbWndExtra = 0;
wc.hbrBackground = (HBRUSH)COLOR_3DLIGHT;
wc.hCursor = LoadCursor(NULL, IDC_HELP); //光标
wc.hIcon = LoadIcon(NULL, IDI_HAND); //图标
wc.hIconSm = NULL;
wc.hInstance = hInstance;
wc.lpfnWndProc = PEluosi; //回调函数地址
wc.lpszClassName = "els"; //窗口类的名字,不重复,操作系统看
wc.lpszMenuName = NULL;
wc.style = CS_HREDRAW | CS_VREDRAW;
//注册窗口对象
if (RegisterClassEx(&wc) == 0)
{
int a = GetLastError(); //函数 errno
return 0;
}
//创建窗口
hWnd = CreateWindowEx(WS_EX_TOPMOST, "els", "RR\'s Block", WS_OVERLAPPEDWINDOW,100,40, 500, 641,NULL, NULL,hInstance, NULL);
if (hWnd == NULL) //窗口句柄 123 窗口唯一标识
{
return 0;
}
//显示窗口
ShowWindow(hWnd, SW_NORMAL); //返回值 0:隐藏 非零:显示
//消息循环
while (GetMessage(&msg, NULL, 0, 0))
{
//翻译消息
TranslateMessage(&msg);
//分发消息
DispatchMessage(&msg);
}
return 0;
}
//win32控制台 主函数 int main()
//win32项目 主函数
LRESULT CALLBACK PEluosi(HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam)
{
PAINTSTRUCT pt;
HDC hdc;
switch (nMsg)
{
case WM_CREATE: //窗口创建初期只产生一次
OnCreate();
break;
case WM_TIMER:
OnTimer(hWnd);
break;
case WM_PAINT:
hdc = BeginPaint(hWnd, &pt);
//画窗口的内容
OnPaint(hdc);
EndPaint(hWnd, &pt);
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:
OnChangeSqare(hWnd);
break;
case VK_DOWN:
OnDown(hWnd);
break;
}
break;
case WM_DESTROY:
KillTimer(hWnd, DEF_TIMER1);
PostQuitMessage(0);
break;
}
return DefWindowProc(hWnd, nMsg, wParam, lParam); //功能:
}
void OnCreate()
{
srand((unsigned int)time(NULL));
CreateRandomSqare();
CopySqareToBack();
}
void CreateRandomSqare()
{
int nIndex = rand() % 7;
switch(nIndex)
{
case 0:
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 1:
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 2:
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 3:
g_arrSqare[0][0] = 0, g_arrSqare[0][1] = 0, g_arrSqare[0][2] = 1, 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 4:
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;
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;
g_nLine = 0;
g_nList = 4;
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;
}
g_nSqareID = nIndex;
}
void CopySqareToBack()
{
int i, j;
for (i = 0; i < 2; i++)
for (j = 0; j < 4; j++)
g_arrBackGround[i][j + 3] = g_arrSqare[i][j];
}
void PaintSqare(HDC hMenDc)
{
HBRUSH hOldBrush;
HBRUSH hNewBrush;
int i , j;
Rectangle(hMenDc, 0, 0, 300 ,600);
hNewBrush = CreateSolidBrush(RGB(245, 253, 98));
hOldBrush = SelectObject(hMenDc, hNewBrush);
for (i = 0; i < 20; i++)
{
for (j = 0; j < 10; j++)
if (g_arrBackGround[i][j] == 1)
Rectangle(hMenDc, j * 30, i * 30, j * 30 + 30 , i * 30 + 30);
}
hNewBrush = SelectObject(hMenDc, hOldBrush);
DeleteObject(hNewBrush);
}
void PaintSqare2(HDC hMenDc)
{
int i , j;
HBRUSH hOldBrush;
HBRUSH hNewBrush = CreateSolidBrush(RGB(130, 64, 238));
hOldBrush = SelectObject(hMenDc, hNewBrush);
for (i = 0; i < 20; i++)
{
for (j = 0; j < 10; j++)
if (g_arrBackGround[i][j] == 2)
Rectangle(hMenDc, j * 30, i * 30, j * 30 + 30 , i * 30 + 30);
}
hNewBrush = SelectObject(hMenDc, hOldBrush);
DeleteObject(hNewBrush);
}
void OnPaint(HDC hdc)
{
//创建兼容性DC
HDC hMenDc = CreateCompatibleDC(hdc);
//创建一张纸
HBITMAP hBitmapBack = CreateCompatibleBitmap(hdc, 500, 600);
//关联起来
SelectObject(hMenDc, hBitmapBack);
PaintSqare(hMenDc);
PaintSqare2(hMenDc);
//传递
ShowScore(hMenDc);
BitBlt(hdc, 0, 0, 500, 600, hMenDc, 0, 0, SRCCOPY);
DeleteObject(hBitmapBack);
DeleteDC(hMenDc);
}
void OnReturn(HWND hWnd)
{
//打开定时器
SetTimer(hWnd, DEF_TIMER1, 500, NULL);
}
//方块下落
void SqareDown()
{
int i, j;
for (i = 19; i >= 0; i--)
{
for (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 (CanSqareDown() && CanSqareDown2())
{
SqareDown();
g_nLine++;
}
else
{
// 1 to 2
Change1To2();
DestroyOneLineSqare();
//游戏结束
if (!CanGameOver())
{
KillTimer(hWnd, DEF_TIMER1);
return ;
}
//产生随机块
CreateRandomSqare();
CopySqareToBack();
}
//显示方块
OnPaint(hDc);
ReleaseDC(hWnd, hDc); //人工释放
}
void Change1To2()
{
int i, j;
for (i = 0; i < 20; i++)
{
for (j = 0; j < 10; j++)
{
if (g_arrBackGround[i][j] == 1)
{
g_arrBackGround[i][j] = 2;
}
}
}
}
int CanSqareDown()
{
int i;
for (i = 0; i < 10; i++)
{
if (g_arrBackGround[19][i] == 1)
{
return 0;
}
}
return 1;
}
int CanSqareDown2()
{
int i, j;
for (i = 19; i >= 0; i--)
{
for (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)
{
HDC hDc = GetDC(hWnd);
if (CanSqareLeft() && CanSqareLeft2())
{
// 方块左移
SqareLeft();
g_nList--;
//显示方块
OnPaint(hDc);
ReleaseDC(hWnd, hDc);
}
}
void SqareLeft()
{
int i, j;
for (i = 0; i < 20; i++)
{
for (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 CanSqareLeft()
{
int i;
for (i = 0; i < 20; i++)
{
if (g_arrBackGround[i][0] == 1)
{
return 0;
}
}
return 1;
}
int CanSqareLeft2()
{
int i, j;
for (i = 0; i < 20; i++)
{
for (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 (CanSqareRight() && CanSqareRight2())
{
HDC hDc = GetDC(hWnd);
// 方块右移
g_nList++;
SqareRight();
OnPaint(hDc);
ReleaseDC(hWnd, hDc);
}
}
void SqareRight()
{
int i, j;
for (i = 0; i < 20; i++)
{
for (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 CanSqareRight()
{
int i;
for (i = 0; i < 20; i++)
{
if (g_arrBackGround[i][9] == 1)
return 0;
}
return 1;
}
int CanSqareRight2()
{
int i,j;
for (i = 0; i < 20; i++)
{
for (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 OnChangeSqare(HWND hWnd)
{
HDC hDc = GetDC(hWnd);
switch (g_nSqareID)
{
case 0:
case 1:
case 2:
case 3:
case 4:
if (CanSqareChangeShape())
{
ChangeSqare();
}
else
{
return;
}
break;
case 5:
return ;
case 6:
if (CanLineSqareChange())
{
ChangeLineSqare();
}
break;
}
OnPaint(hDc);
ReleaseDC(hWnd, hDc);
}
void ChangeSqare()
{
char arrSqare[3][3] = {0};
int i, j;
int nTemp = 2;
for (i = 0; i < 3; i++)
{
for (j = 0; j < 3; j++)
{
arrSqare[i][j] = g_arrBackGround[g_nLine + i][g_nList + j];
}
}
//变形后复制回去
for (i = 0; i < 3; i++)
{
for (j = 0; j < 3; j++)
{
g_arrBackGround[g_nLine + i][g_nList + j] = arrSqare[nTemp--][i];
}
nTemp = 2;
}
}
int CanSqareChangeShape()
{
int i, j;
for (i = 0; i < 3; i++)
{
for (j = 0; j < 3; j++)
{
if (g_arrBackGround[g_nLine + i][g_nList + j] == 2)
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 (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 - 1][g_nList] = 1;
g_arrBackGround[g_nLine - 2][g_nList] = 1;
g_arrBackGround[g_nLine - 3][g_nList] = 1;
}
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;
}
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 || 9 == g_nList)
{
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 = g_nList - 2;
}
else if (g_arrBackGround[g_nLine][g_nList + 2] == 2 || 8 == g_nList)
{
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 = g_nList - 1;
}
else if (g_arrBackGround[g_nLine][g_nList - 1] == 2 || !g_nList)
{
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 = g_nList + 1;
}
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 CanLineSqareChange()
{
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 + j < 5)
return 0;
return 1;
}
void DestroyOneLineSqare()
{
int i, j, n;
int nSum = 0;
for (i = 19; i >= 0; i--)
{
for (j = 0; j < 10; j++)
{
nSum += g_arrBackGround[i][j];
}
if (nSum == 20)
{
for(n = i - 1; n >= 0; n--)
{
for (j = 0; j < 10; j++)
{
g_arrBackGround[n + 1][j] = g_arrBackGround[n][j];
}
}
g_nScore++;
// 消除两行的bug
i = 20;
}
nSum = 0;
}
}
void ShowScore(HDC hMenDc)
{
char strScore[10] = {0};
Rectangle(hMenDc, 300, 0, 500, 600);
itoa(g_nScore, strScore, 10);
TextOut(hMenDc, 356, 140, "分数:", strlen("分数:"));
TextOut(hMenDc, 390, 140, strScore, strlen(strScore));
}
int CanGameOver()
{
int i;
for (i = 0; i < 10; i++)
{
if (g_arrBackGround[0][i] == 2)
{
//游戏结束
MessageBox(NULL, "GameOver", "提示", MB_OK);
return 0;
}
}
return 1;
}
9,复制好后,摁F7,观测下面的编译输出信息:如果是0 error(s), 0 warning (s)。那么只需摁Ctrl+F5就可以看到我们刚开始看到的效果了。如果还是有问题,那么要么是环境的问题(中文乱码),要么是你执行步骤的问题。
未完待续...