我正在尝试创建自己的矩阵编写算法,该算法使用Run Length Encoding将矩阵写入C控制台。我的想法是,不打印矩阵中的每一个值,我们可以将一行中相同的矩阵值聚集成一行并打印该行,然后对下一组相同的值进行同样的操作,并继续这样做,直到我们到达行的末尾,这将允许我对彩色ASCII图形使用SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE))
,因为我可以只为每组着色。例如,如果我们的矩阵中有01110000
作为一行,我们将只使用三个打印命令:一个用于初始零,另一个用于3个零,最后一个用于4个零。我们可以这样做,以避免浪费将所有值单独打印到控制台的过程时间,问题是我的代码中有很多未定义的行为,这导致控制台输出与预期的非常不同。
代码:
#include <stdio.h>
#include <time.h>
#include <windows.h>
const int sizeX = 20;
const int sizeY = 20;
char line[20];
int grid[20][20] = {{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}};
void clearScreen(){
COORD cursorPosition; cursorPosition.X = 0; cursorPosition.Y = 0; SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), cursorPosition);
}
void draw_screen(){
clearScreen();
int y, x;
for(y=0;y<sizeY;y++){
for(x=0;x<sizeX;x++){
if(grid[y][x] == 1){
line[x] = '1';
if(grid[y][x+1] != 1){
fputs(line, stdout);
if(grid[y][x+1] > sizeX){
putc('n', stdout);
}
}
}
else if(grid[y][x] == 2){
line[x] = '2';
if(grid[y][x+1] != 2){
fputs(line, stdout);
if(grid[y][x+1] > sizeX){
putc('n', stdout);
}
}
}
else if(grid[y][x] == 0){
line[x] = '0';
if(grid[y][x+1] != 0){
fputs(line, stdout);
if(grid[y][x+1] > sizeX){
putc('n', stdout);
}
}
}
}
putc('n', stdout);
}
}
int main(void) {
int x, y;
float frameTime, FPS;
while (1) {
clock_t start = clock();
draw_screen();
clock_t stop = clock();
frameTime = (float)(stop - start) / CLOCKS_PER_SEC;
FPS = 1.0 / frameTime;
printf("FPS: %fn", FPS);
}
}
输出:
100000000000000000001000000000000000000010000000000000001110
0000000000000000000000000000010000000000
00000000000000000000000100000000000000000001000000000000000000010000010000000000
0000000000000000000000000000000200000000
00000000000000000000
预期输出:
10000000000000001110
00000000000000000000
00000000000000000000
00000000000000000000
00000000010000000000
00000000000000000000
00000000000000000000
00000000000000000000
00010000010000000000
00000000000000000000
00000000000000000000
00000000000000000000
00000000000200000000
00000000000000000000
00000000000000000000
00000000000000000000
00000000000000000000
00000000000000000000
00000000000000000000
00000000000000000000
预期FPS:100-500
您的问题被误解了。我的抱怨是代码很难阅读(而且重复(。
puts()
将不可避免地在其输出的每个字符串上附加一个"\n"。
你可以尝试";"缓冲";一系列重复的字符,只在数据发生变化(或到达网格行末尾(时输出该"块",但这会使代码更加混乱。imho,更重要的是,对于学习来说,代码要尽可能干净。对算法进行优化(比如速度(,直到你解决了更大的问题。
您有一个20x20的int
"网格",并希望将其输出为字符网格,但注入一个操作来更改下一系列字符的字体颜色。
下面的例子"注入"了一个额外的字符,指示您可以为后续输出更改字体颜色的位置。
保持简单,避免复制/粘贴/改编的诱惑。使用更少的代码。
#include <stdio.h>
int grid[][20] = {
{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
};
void draw_screen() {
int r, c; // I prefer 'r'ow and 'c'ol
int prev = -1; // force code to select 1st colour
for( r = 0; r < 20; r++ ) {
for( c = 0; c < 20; c++) {
if( grid[r][c] != prev ) {
// pick a colour (or character) for subsequent output
char cc = grid[r][c] == 0 ? '*' : grid[r][c] == 1 ? '+' : '=';
putchar( cc ); // demonstrate "colour change" happening
}
putchar( grid[r][c] + '0' ); // int to char conversion
prev = grid[r][c];
}
putchar( 'n' );
}
}
int main() {
draw_screen();
return 0;
}
输出
+1*000000000000000+111*0
00000000000000000000
00000000000000000000
00000000000000000000
000000000+1*0000000000
00000000000000000000
00000000000000000000
00000000000000000000
000+1*00000+1*0000000000
00000000000000000000
00000000000000000000
00000000000000000000
00000000000=2*00000000
00000000000000000000
00000000000000000000
00000000000000000000
00000000000000000000
00000000000000000000
00000000000000000000
00000000000000000000
编辑:试图将此OP指向紧凑的解决方案似乎只会让所有相关人员感到沮丧。
下面是上面代码的一个(明显的(扩展,它是有效的。我不想"改变颜色";,但是通过插入";特殊字符";在输出流中,这显示了程序如何检测和响应数据中的转换。
(我们为他人编写免费代码的费用是多少?请提醒我。(
const char c_red = '*', c_green = '+', c_blue = '=';
void setFontColor( char color ) {
// do whatever you need to do here.
// This version outputs a "special" character
// indicating the color to be used
fwrite( &color, sizeof color, 1, stdout );
}
void out( char buf[], int n ) {
char color;
switch( buf[0] ) {
case '0': color = c_red; break;
case '1': color = c_green; break;
case '2': color = c_blue; break;
default:
fprintf( stderr, "Unknown character '%c'n", buf[0] );
exit( 1 );
}
setFontColor( color );
fwrite( buf, sizeof buf[0], n, stdout );
}
void draw_screen() {
char prev = '#', obuf[ 20 ];
for( int bInd = 0, r = 0; r < 20; r++ ) {
for( int c = 0; c < 20; c++ ) {
char ch = (char)(grid[r][c] + '0');
if( ( c || r ) && ch != prev )
out( obuf, bInd ), bInd = 0;
prev = obuf[ bInd++ ] = ch;
}
out( obuf, bInd ), bInd = 0; // End of row
putchar( 'n' ); // or, tack LF onto end of obuf[]...
}
}
int main() {
draw_screen();
return 0;
}
在上面的例子中,每个缓冲行都是离散的(最多20个字符(。缓冲LF,而不是用自己的颜色开始每一行,留给读者一个练习。
我相信我也解决了这个问题,我将line
字符串更改为字符绘制算法。
#include <stdio.h>
#include <time.h>
#ifdef __unix__
# include <unistd.h>
#elif defined _WIN32
# include <windows.h>
#define sleep(x) Sleep(1000 * (x))
#endif
#include <windows.h>
const int sizeX = 20;
const int sizeY = 20;
int counter0,counter1,counter2;
int grid[20][20] = {{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}};
void print_chars(unsigned int number_of_spaces, char character) {
char* spaces = malloc(sizeof(char)*number_of_spaces + 1);
memset (spaces,character,number_of_spaces);
spaces[number_of_spaces] = ' ';
fputs(spaces, stdout);
free(spaces);
}
void draw_screen(){
int y, x;
for(y=0;y<sizeY;y++){
for(x=0;x<sizeX;x++){
sleep(0.1);
if(grid[y][x] == 0){
counter0++;
if(grid[y][x+1] != 0 || x+1 >= sizeX){
print_chars(counter0, '1');
counter0 = 0;
}
}
else if(grid[y][x] == 1){
counter1++;
if(grid[y][x+1] != 1 || x+1 >= sizeX){
print_chars(counter1, '@');
counter1 = 0;
}
}
}
printf("n");
}
}
int main(void) {
int x, y;
float frameTime, FPS;
clock_t start = clock();
draw_screen();
clock_t stop = clock();
frameTime = (float)(stop - start) / CLOCKS_PER_SEC;
printf("Frame: %fn", frameTime);
}