贪吃蛇闪烁现象
界面效果:
界面闪烁的原因是“如果打印左上角第一个字符到打印右下角最后一个字符时间间隔超过20ms,就会闪烁”
打印背景:
法一:根据一个整型二维数组来判断打印方块或空格
BlackBlock整型字符串为:
1 int BlackBlock[20][23] = { 2 { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, 3 { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }, 4 { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }, 5 { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }, 6 { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }, 7 { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }, 8 { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }, 9 { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }, 10 { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }, 11 { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }, 12 { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }, 13 { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }, 14 { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }, 15 { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }, 16 { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }, 17 { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }, 18 { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }, 19 { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }, 20 { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }, 21 { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, 22 };
打印的函数:
1 void show1() 2 { 3 int i, j; 4 while (1) 5 { 6 system("cls"); //清屏 7 for (i = 0; i < 20; i++) 8 { 9 for (j = 0; j < 23; j++) 10 if (1 == BlackBlock[i][j]) 11 printf("█"); 12 else 13 printf(" "); 14 printf("\n"); 15 } 16 Sleep(1000); //时间间隔是1000ms,即1s,若无此函数则循环高速进行,不停闪烁 17 } 18 } 19
这种方法,打印的背景闪烁很明显,很严重,用clock()函数测出每循环打印一次的时间:
1 void show1() 2 { 3 int i, j; 4 while (1) 5 { 6 start = clock(); //用clock()函数检测打印一次所需时间,测试后结果为24ms~53ms,超过20ms,人眼所能识别最小的时间间隔是20ms,所以会造成闪烁现象 7 system("cls"); 8 for (i = 0; i < 20; i++) 9 { 10 for (j = 0; j < 23; j++) 11 if (1 == BlackBlock[i][j]) 12 printf("█"); 13 else 14 printf(" "); 15 printf("\n"); 16 } 17 stop = clock(); 18 duration = ((double)(stop - start)) / CLK_TCK; 19 printf("duration = %lf\n", duration); 20 Sleep(1000); //时间间隔是1000ms,即1s 21 } 22 }
用clock()函数检测打印一次所需时间,测试后结果为24ms~53ms,超过20ms,人眼所能识别最小的时间间隔是20ms,所以会造成闪烁现象
法二:直接打印字符串
字符串数组为:
1 char BackGround[20][48] = { 2 "███████████████████████\n", 3 "█ █\n", 4 "█ █\n", 5 "█ █\n", 6 "█ █\n", 7 "█ █\n", 8 "█ █\n", 9 "█ █\n", 10 "█ █\n", 11 "█ █\n", 12 "█ █\n", 13 "█ █\n", 14 "█ █\n", 15 "█ █\n", 16 "█ █\n", 17 "█ █\n", 18 "█ █\n", 19 "█ █\n", 20 "█ █\n", 21 "███████████████████████\n" 22 };
显示的函数:
1 void show2() 2 { 3 int i; 4 while (1) 5 { 6 system("cls"); 7 for (i = 0; i < 20; i++) 8 printf(BackGround[i]); 9 Sleep(1000); 10 } 11 12 }
这种方法打印的背景几乎看不到闪烁现象,也用clock()函数测出每循环打印一次的时间:
1 void show2() 2 { 3 int i; 4 while (1) 5 { 6 system("cls"); 7 8 ////用clock()函数检测打印一次所需时间,测试后结果为0ms~10ms, 9 //且大多数情况下在0ms ~ 4ms,远小于20ms,所以几乎看不到闪烁现象 10 start = clock(); 11 for (i = 0; i < 20; i++) 12 printf(BackGround[i]); 13 stop = clock(); 14 duration = ((double)(stop - start)) / CLK_TCK; 15 printf("duration = %lf\n", duration); 16 Sleep(1000); 17 } 18 19 }
用clock()函数检测打印一次所需时间,测试后结果为0ms~10ms,
且大多数情况下在0ms ~ 4ms,远小于20ms,所以几乎看不到闪烁现象
█
法三:直接用一个一维字符数组存放法二中的所有字符串:
1 char backGround[960] = { 2 "███████████████████████\n" 3 "█ █\n" 4 "█ █\n" 5 "█ █\n" 6 "█ █\n" 7 "█ █\n" 8 "█ █\n" 9 "█ █\n" 10 "█ █\n" 11 "█ █\n" 12 "█ █\n" 13 "█ █\n" 14 "█ █\n" 15 "█ █\n" 16 "█ █\n" 17 "█ █\n" 18 "█ █\n" 19 "█ █\n" 20 "█ █\n" 21 "███████████████████████\n" 22 };
显示的函数:
1 void show3() 2 { 3 while (1) 4 { 5 system("cls"); 6 printf(backGround); 7 Sleep(1000); 8 } 9 }
法三的闪烁现象几乎看不到,这在法二的基础上又是一次改进和优化。
总结:各个函数的时间消耗主要在调用printf函数和打印字符,三种方法打印的字符都一样多,所以调用printf()的次数越少,则时间间隔越小,越优化,闪烁越不明显。