Windows平台C语言开发ASCII艺术游戏出现画面随机闪烁问题求解
闪烁问题产生原因
- 最核心原因是使用了
system("cls")清屏:该命令会调用系统终端进程清空整个屏幕内容,清空后到新内容输出前会存在短暂的全黑空白窗口,人眼可以明显捕捉到这个间隙,就会形成闪烁感。 - 休眠逻辑错误:你使用的
usleep单位为微秒,delta * 1000仅等于100微秒,相当于每帧间隔只有0.0001秒,过高的刷新频率会放大清屏带来的闪烁效果。 - 字符串无结束标识符:你定义的
scr数组没有预留\0的存储位置,每次printf(scr)时会出现越界读内存,可能输出异常乱码,加剧显示异常。 - Windows平台下
usleep兼容性差:该函数是POSIX标准接口,Windows原生环境没有对应实现,调用时可能出现不可预期的时序问题。
解决方案
按以下步骤修改代码即可完全解决闪烁问题:
- 替换清屏逻辑:使用Windows API将光标定位到终端左上角,直接用新内容覆盖旧内容,完全避免清屏带来的空白间隙。
- 修复休眠逻辑:使用Windows原生的
Sleep函数(单位为毫秒),设置合理的帧间隔。 - 补全字符串结束符:调整
scr数组大小,每次渲染完成后手动添加\0结束符。 - 可选优化:隐藏控制台光标,避免光标本身的闪烁叠加到游戏画面上。
修改后的完整可运行代码
#include <stdio.h> #include <windows.h> const int WIDTH = 20, HEIGTH = 5; const int AREA = (WIDTH) * HEIGTH; const int gl = HEIGTH - 2; // 地面层级 const int frame_delay = 100; // 帧间隔,单位毫秒,对应原0.1秒的帧率 char scr[AREA + 1]; // 多留1位存储字符串结束符 // 光标定位到指定坐标 void gotoxy(int x, int y) { COORD coord = {(SHORT)x, (SHORT)y}; SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord); } // 隐藏控制台光标 void hide_cursor() { CONSOLE_CURSOR_INFO cursor_info; GetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &cursor_info); cursor_info.bVisible = FALSE; SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &cursor_info); } int main() { char input; int i; int posx = 10, posy = gl - 1; // 玩家坐标 int vel = 0; // 玩家速度 hide_cursor(); // 启动时隐藏光标 while(1) { // TODO: 玩家输入处理 for(i = 0; i < AREA; i++) { if(i % WIDTH == 0 && i != 0) { scr[i] = '\n'; continue; } if(i / WIDTH >= gl) { // 地面层级赋值 scr[i] = '.'; continue; } scr[i] = ' '; } // 赋值玩家位置 scr[posy * WIDTH + posx + 1] = '@'; scr[(posy + 1) * WIDTH + posx + 1] = '@'; scr[AREA] = '\0'; // 补字符串结束符 gotoxy(0, 0); // 光标移到左上角,代替清屏 printf("%s", scr); // 输出画面 Sleep(frame_delay); // 按帧间隔休眠 } return 0; }
内容的提问来源于stack exchange,提问作者Amos
相关产品推荐
相关产品推荐

