win32-c語言實現俄羅斯方塊
這是我跟著一個視訊教程做的。先看效果,後上程式碼,核心是二維陣列(矩陣)的遍歷和win32的一些基礎,有時間談談細節。
我使用的是vc++6.0,更高版本也可以,vc++6.0下載地址: http://download.csdn.net/download/richard1997/10252249
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就可以看到我們剛開始看到的效果了。如果還是有問題,那麼要麼是環境的問題(中文亂碼),要麼是你執行步驟的問題。
未完待續...
相關文章
- canvas實現俄羅斯方塊Canvas
- 使用JavaScript實現一個俄羅斯方塊JavaScript
- Flutter Web 實戰 - 俄羅斯方塊FlutterWeb
- 俄羅斯方塊練習
- c#實現簡單的俄羅斯方塊C#
- 函數語言程式設計嘗試之俄羅斯方塊函數程式設計
- 俄羅斯方塊聯機小遊戲的實現遊戲
- 俄羅斯方塊(JS+CSS)JSCSS
- Tetris 俄羅斯方塊遊戲遊戲
- 初學者——Java之實現簡易俄羅斯方塊Java
- 【Java遊戲】java俄羅斯方塊!Java遊戲
- 最新《 java實戰開發俄羅斯方塊教程》Java
- Python 實戰開發俄羅斯方塊遊戲Python遊戲
- Python:遊戲:300行程式碼實現俄羅斯方塊Python遊戲行程
- 300行Python程式碼實現俄羅斯方塊,致敬逝去的童年Python
- 基於Flutter的俄羅斯方塊小遊戲Flutter遊戲
- 如何讓 Emacs 俄羅斯方塊變得更難Mac
- wxpython入門第十一步(俄羅斯方塊)Python
- 基於MonoGame重製《俄羅斯方塊》遊戲MonoGAM遊戲
- Python3+pygame實現的俄羅斯方塊 程式碼完整 有演示效果PythonGAM
- 【補檔STM32】STM32F103俄羅斯方塊遊戲實現遊戲
- 如何讓AI教機器自己玩俄羅斯方塊?AI
- 用React、Redux、Immutable做俄羅斯方塊 | 掘金技術徵文ReactRedux
- 從俄羅斯方塊,邁向強化學習大門強化學習
- 俄羅斯方塊歷史發展與變革創新
- 使用C#和MonoGame開發俄羅斯方塊遊戲C#MonoGAM遊戲
- “漢字俄羅斯方塊”《一字不落》今日上架Steam
- 為了上班摸魚我用Python製作了俄羅斯方塊?Python
- python開發俄羅斯方塊小遊戲程式碼例項Python遊戲
- [分享]純python3手寫Tetris(俄羅斯方塊)遊戲Python遊戲
- 用 SQL 寫的俄羅斯方塊遊戲「GitHub 熱點速覽」SQL遊戲Github
- pyqt5製作俄羅斯方塊小遊戲-----原始碼解析QT遊戲原始碼
- 俄羅斯玩偶
- 俄羅斯:‘區塊鏈屬於我們’區塊鏈
- 回顧「俄羅斯方塊」曾經的一段蒸汽波時代
- 《俄羅斯方塊》系列 35 週年 一窺遊戲歷年玩法演變遊戲
- 超越《俄羅斯方塊》後,《我的世界》想打造一個更具野心的世界
- 俄羅斯軍方正在建設區塊鏈研究實驗室區塊鏈
- 前端筆記之JavaScript物件導向(四)元件化開發&輪播圖|俄羅斯方塊實戰前端筆記JavaScript物件元件化