控制台遊戲/動畫頻繁 `printf` 刷新畫面時,用戶會看到逐幀繪製的過程(先出現局部、再補全),產生嚴重閃爍。雙緩衝將「繪製過程」放到非可見緩衝區,一次性切換顯示,實現無閃爍幀率。
| API | 作用 | 關鍵參數 |
|---|---|---|
CreateConsoleScreenBuffer | 創建新緩衝區 | `GENERIC_READ | GENERIC_WRITE`, `CONSOLE_TEXTMODE_BUFFER` |
SetConsoleActiveScreenBuffer | 切換活動緩衝區 | 緩衝區句柄 |
WriteConsole | 向指定緩衝區寫字符 | 句柄、字符串、長度、寫入字符數指針 |
SetConsoleCursorInfo | 隱藏/顯示光標 | `bVisible = FALSE` 消除光標閃爍 |
SetConsoleCursorPosition | 定位光標 | `COORD {0,0}` 歸零 |
#include <windows.h>
#include <stdio.h>
int main() {
// 1. 創建兩個緩衝區
HANDLE hBuffer[2];
hBuffer[0] = CreateConsoleScreenBuffer(GENERIC_READ | GENERIC_WRITE,
0, NULL, CONSOLE_TEXTMODE_BUFFER, NULL);
hBuffer[1] = CreateConsoleScreenBuffer(GENERIC_READ | GENERIC_WRITE,
0, NULL, CONSOLE_TEXTMODE_BUFFER, NULL);
if (hBuffer[0] == INVALID_HANDLE_VALUE || hBuffer[1] == INVALID_HANDLE_VALUE) return 1;
// 2. 隱藏光標
CONSOLE_CURSOR_INFO cci = {1, FALSE};
SetConsoleCursorInfo(hBuffer[0], &cci);
SetConsoleCursorInfo(hBuffer[1], &cci);
int front = 0; // 當前顯示緩衝區索引
COORD pos = {0, 0};
char frame[80 * 25 + 1]; // 假設 80x25 控制台
while (1) {
HANDLE back = hBuffer[1 - front]; // 後台緩衝區
// 3. 構建幀內容(示例:移動的字符)
static int x = 0, dir = 1;
memset(frame, ' ', sizeof(frame) - 1);
frame[x] = '*';
frame[sizeof(frame) - 1] = '\0';
x += dir;
if (x == 79 || x == 0) dir = -dir;
// 4. 寫入後台緩衝區
DWORD written;
SetConsoleCursorPosition(back, pos);
WriteConsole(back, frame, strlen(frame), &written, NULL);
// 5. 切換顯示
SetConsoleActiveScreenBuffer(back);
front = 1 - front;
Sleep(50); // 幀率控制 ~20 FPS
}
// 清理(實際需在退出循環時執行)
CloseHandle(hBuffer[0]);
CloseHandle(hBuffer[1]);
return 0;
}
Windows 控制台雙緩衝是平台特有但極其有效的無閃爍渲染技術。掌握「創建→寫後台→切換→循環」四步核心流程,配合光標隱藏、座標定位、屬性寫入,即可構建流暢的控制台遊戲/動畫引擎。跨平台項目建議抽象渲染層,Windows 用雙緩衝,Linux/macOS 用 ANSI/ncurses。