1. 程式人生 > 實用技巧 >【C語言/C++程式設計師程式設計】一小時做出來的數字雨(一顆開花的樹)!

【C語言/C++程式設計師程式設計】一小時做出來的數字雨(一顆開花的樹)!

相信大家看過許許多多的關於計算機黑客、駭客、人工智慧、AI方面的電影,每當黑客入侵某個五角大樓,某個網站時,都會出現這樣一副畫面:


入侵

或者這樣的:


數字雨

然後就輕而易舉的成功入侵奪取管理員許可權了,這時候的我們,心情肯定是激動的無以復加,心裡大喊著:666!!!如果我有這麼厲害的技術就好了!

所以大家想到今天要說的是什麼了嗎?沒錯,

(^U^)ノ~YO

和這並沒有太大的關係,今天我們要講的,是《數字雨》!

好了,我們來看下什麼是數字雨。


數字雨,顧名思義,就是類似於天上下雨一樣,往下掉數字或者是文字。

如下動態圖:


這樣看起來是不是感覺我們像是進入了一個科幻的虛擬世界呢?

當然了程式執行後還會有個小小的驚喜哦?

/**********************************************************************************

專案名稱:數字雨《一棵開花的樹》


***********************************************************************************/

#include

#include

#include

#pragma comment(lib, "WINMM.LIB")

#define NumOfColumn 25 //顯示列的列數
typedef struct charList { struct charList * prev; TCHAR ch; //放字元 struct charList * next; }CharList; typedef struct tagCharColumn { struct charList * head, *cur; int x, y, iShownLen, iStrNum; //顯示字數,字元數 }CharQueue; struct showChar { TCHAR myChar[60]; int iNum; //字元個數 }charArr[7] = {//《一棵開花的樹》
{ TEXT("如何讓你遇見我,在我最美麗的時刻"),16 }, { TEXT("為這,我已在佛前求了五百年,求他讓我們結一段塵緣"),24 }, { TEXT("佛於是把我化作一棵樹,長在你必經的路旁"),19 }, { TEXT("陽光下慎重地開滿了花,朵朵都是我前世的盼望"),21 }, { TEXT("當你走近,請你細聽,那顫抖的葉是我等待的熱情"),21 }, { TEXT("而當你終於無視地走過,在你身後落了一地的"), 20 }, { TEXT("朋友啊,那不是花瓣,是我凋零的心"),16 } }; LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam); int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow) { TCHAR szClassName[] = TEXT("數字雨"); HWND hwnd; MSG msg; WNDCLASS wndclass; wndclass.style = CS_HREDRAW | CS_VREDRAW; wndclass.lpfnWndProc = WndProc; wndclass.cbClsExtra = 0; wndclass.cbWndExtra = 0; wndclass.hInstance = hInstance; wndclass.hIcon = NULL; wndclass.hCursor = NULL; wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); wndclass.lpszMenuName = NULL; wndclass.lpszClassName = szClassName; if (!RegisterClass(&wndclass)) { return 0; } hwnd = CreateWindow(szClassName, NULL, WS_DLGFRAME | WS_THICKFRAME | WS_POPUP, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN), NULL, NULL, hInstance, NULL); Show Window(hwnd, SW_SHOWMAXIMIZED); Update Window(hwnd); Show Cursor(FALSE); srand(time(0)); //訊息機制 while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } Show Cursor(TRUE); return msg.wParam; } void CreateQueue(CharQueue * cc, int cyScreen, int x) { //bug -- 呼叫API---寫介面---ctrl+c/ctrl+v CharList * front; int NumTemp = rand() % 6; cc->x = x; cc->y = rand() % 10 ? rand() % cyScreen : 0; //大約9/10的概率從中間開始下落。 cc->iShownLen = 1; //一開始就顯示一個字元,然後慢慢增加,增加到等於歌詞字元數時保持不變 cc->iStrNum = charArr[NumTemp].iNum; //歌詞字元數 cc->head = cc->cur = front = (CharList *)calloc(cc->iStrNum, sizeof(CharList)); //建立顯示列 //生成每個節點 int i; for (i = 0; iiStrNum - 1; i++) { cc->cur->prev = front; cc->cur->ch = charArr[NumTemp].myChar[i]; front = cc->cur++; front->next = cc->cur; } //最後一個是標點符號 cc->cur->prev = front; cc->cur->ch = charArr[NumTemp].myChar[i]; cc->cur->next = cc->head; cc->head->prev = cc->cur; cc->cur = cc->head; } LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { HDC hdc; static HDC hdcMem; static HBITMAP hBitmap; static CharQueue * AllChar; HFONT hFont; static int cxScreen, cyScreen; static int iFontWidth = 20, iFontHeight = 20; int i, j, y, greenToblack; CharQueue * ccElem; CharList * temp; switch (message) { case WM_CREATE: cxScreen = GetSystemMetrics(SM_CXSCREEN); cyScreen = GetSystemMetrics(SM_CYSCREEN); SetTimer(hwnd, 1, 70, NULL); hdc = GetDC(hwnd); hdcMem = CreateCompatibleDC(hdc); hBitmap = CreateCompatibleBitmap(hdc, cxScreen, cyScreen); SelectObject(hdcMem, hBitmap); ReleaseDC(hwnd, hdc); hFont = CreateFont(iFontHeight, iFontWidth, 0/*角度設定*/, 0/*角度設定*/, FW_BOLD/*黑體*/, 0, 0, 0,/*斜體 下劃線 啊、刪除線*/ DEFAULT_CHARSET/*字符集*/, OUT_DEFAULT_PRECIS/*指定輸出精度*/, CLIP_DEFAULT_PRECIS/*指定裁剪精度*/, DRAFT_QUALITY/*指向輸出質量*/, FIXED_PITCH | FF_SWISS/*指定字型間距| 字型族*/, TEXT("宋體")); SelectObject(hdcMem, hFont); DeleteObject(hFont); SetBkMode(hdcMem, TRANSPARENT); PlaySound(L"素材.wav", NULL, SND_FILENAME | SND_ASYNC | SND_LOOP);//非同步迴圈播放 AllChar = (CharQueue *)calloc(NumOfColumn, sizeof(CharQueue));//自動初始化為o for (i = 0; i { CreateQueue(AllChar + i, cyScreen, 50 * i + 20); } return 0; case WM_TIMER: //該函式使用當前選入指定裝置環境中的刷子繪製給定的矩形區域。通過使用給出的光柵操作來對該刷子的顏色和表面顏色進行組合。 PatBlt(hdcMem, 0, 0, cxScreen, cyScreen, BLACKNESS); for (i = 0; i { ccElem = AllChar + i; temp = ccElem->head; SetTextColor(hdcMem, RGB(255, 255, 255)); TextOut(hdcMem, ccElem->x, ccElem->y, &temp->ch, 1/*字元個數*/); y = ccElem->y; greenToblack = 0; ccElem->head = ccElem->head->next; temp = temp->prev; for (j = 1; jiShownLen; j++) { SetTextColor(hdcMem, RGB(/*greenToblack*5%255*/0, 255 - 255 * (greenToblack++) / (ccElem->iStrNum), 0)); TextOut(hdcMem, ccElem->x, y -= iFontHeight, &temp->ch, 1); temp = temp->prev; } if (ccElem->iShownLeniStrNum) { ccElem->iShownLen++; } ccElem->y += iFontHeight; if (ccElem->y - ccElem->iStrNum*iFontHeight>cyScreen) { free(ccElem->cur); CreateQueue(ccElem, cyScreen, 128 * i + 17); } } hdc = GetDC(hwnd); BitBlt(hdc, 0, 0, cxScreen, cyScreen, hdcMem, 0, 0, SRCCOPY); ReleaseDC(hwnd, hdc); return 0; case WM_RBUTTONDOWN: KillTimer(hwnd, 1); return 0; case WM_RBUTTONUP: SetTimer(hwnd, 1, 70, NULL); return 0; //case WM_LBUTTONDOWN: case WM_KEYDOWN: case WM_DESTROY: KillTimer(hwnd, 1); for (i = 0; i { ccElem = AllChar + i; free(ccElem->cur); } free(AllChar); DeleteObject(hBitmap); DeleteDC(hdcMem); PostQuitMessage(0); break; } return DefWindowProc(hwnd, message, wParam, lParam); }


看完了今天的效果圖和程式碼,細心的同學是不是發現了什麼?

學C/C++不易,此路應攜手前行。

歡迎關注我的程式設計公眾號【草莓味狸貓】!


如果你想跟著小編一起學程式設計的話!

可以來我的C語言C++程式設計學習基地,【點選進入】

還有(原始碼,零基礎教程,專案實戰教學視訊)!