问题
如果你要在控制台里“画”一些频繁更新的东西,比如做个小游戏,常见的思路是:
while(1)
{
//先清空
system("clear");
//再画
printf(".....");
}
然后控制台的就闪个不停,很瞎眼。
解决 0
降低刷新频率,能明显缓解问题。
也就是
#include <windows.h> //需要这个文件头
while(1)
{
//先清空
system("clear");
//再画
printf(".....");
//延时
Sleep(100);
}
解决 1
不要清空整个屏幕,只更新必要的部分。
利用 coino.h
的 gotoxy
函数,可以移动光标的位置,这样就可以做到只修改某行某列的字符了。
(如果用 visual studio,可以参考 https://zhuanlan.zhihu.com/p/460165739)
例如,地图 + 玩家,地图一般都是静态的,所以只用在开头的时候画一遍,后面人物移动就只更新人物即可。
画地图();
while(1)
{
if(玩家移动())
{
gotoxy(玩家新x, 玩家新y);
putchar('我');
//玩家原来的位置要恢复
gotoxy(玩家旧x, 玩家旧y);
putchar(地图上这一格对应的字符);
}
}
解决 2
直接覆写或输出空格来实现“清屏”,尽量避免使用 system("cls")
。
或者说是“部分清屏”。
改变思想:在计算机里,不需要的东西没必要一定丢掉清空,可以直接用新的覆盖上去。
解决 3
取消自动刷新缓冲区,然后手动刷新缓冲区。
这个可以解决光标鬼畜到处跑的问题,尤其是你的 gotoxy
用的比较多的时候这个问题比较明显。
while(1)
{
setvbuf(stdout, NULL, _IOFBF, 4096); // 1:修改刷新模式为手动刷新
//然后画你要画的东西
printf("...");
fflush(stdout); // 2:清空并输出缓冲区的内容
setvbuf(stdout, NULL, _IOLBF, 4096); // 3:刷新模式改回去
}
相当于原来是一行一行显示,改了之后就是一整块一整块显示。
原来每显示一行光标移一下,就造成了乱跑的问题。
(当然,你也可以选择直接隐藏光标)
例
源代码
int main()
{
while (1)
{
system("cls");
printf("%d\n", rand());
printf("%d\n", rand());
printf("%d\n", rand());
printf("%d\n", rand());
printf("%d\n", rand());
printf("%d\n", rand());
}
return 0;
}
降低刷新率:
int main()
{
while (1)
{
system("cls");
printf("%d\n", rand());
printf("%d\n", rand());
printf("%d\n", rand());
printf("%d\n", rand());
printf("%d\n", rand());
printf("%d\n", rand());
Sleep(100);
}
return 0;
}
改用 gotoxy 和直接覆盖:
(注意!延时没了)
int main()
{
while (1)
{
gotoxy(0, 0);
printf("%d", rand());
printf(" \n"); //因为数字长度不一样,所以用空格覆盖掉上次比这次长的部分
printf("%d", rand());
printf(" \n");
printf("%d", rand());
printf(" \n");
printf("%d", rand());
printf(" \n");
printf("%d", rand());
printf(" \n");
printf("%d", rand());
printf(" \n");
}
return 0;
}
手动刷新缓冲区:
int main()
{
while (1)
{
setvbuf(stdout, NULL, _IOFBF, 4096);
gotoxy(0, 0);
printf("%d", rand());
printf(" \n");
printf("%d", rand());
printf(" \n");
printf("%d", rand());
printf(" \n");
printf("%d", rand());
printf(" \n");
printf("%d", rand());
printf(" \n");
printf("%d", rand());
printf(" \n");
fflush(stdout);
setvbuf(stdout, NULL, _IOLBF, 4096);
}
return 0;
}