201909-3 《字符畫》 簡單易懂,使用最簡單的代碼

在這裏插入圖片描述
不追求最精簡的代碼,追求最易讀懂的代碼,努力讓讀者understand,自己再寫出代碼

一、審題

按照題目的意思,每行輸入的區域顏色,沒有區分前景色,背景色。題目更改的都是背景色,因此默認都只更改背景色。

1、初始時終端的前景色和背景色都爲默認值(前景白色,背景黑色)

如果第一塊區域計算的前景色或背景色爲默認值,則不需要輸出到終端,但是要輸出空格。

2、如果下一個字符和顏色剛好與默認值完全相同,你應當直接使用重置轉義序列,而非手動更改顏色。

3、 如果某個字符的前景色/背景色與其前一個字符相同,或者對顏色的更改並不影響最終的顯示效果,則不應該出現更改這個屬性的控制序列。

能省就省,不要忘記輸出空格。

4、在輸每一行字符後,如果終端顏色不是默認值,你應該重置終端的顏色狀態。

每一行最後也需要輸出換行符 \n

5、需要處理特殊情況#aabbcc可以寫成#abc,#aaaaaa可以寫成#a

就三種情況,單獨拿出來處理一下okk

二、算法策略

1、顏色存儲,顏色換算,使用 dot [m][n] 標記任意座標的顏色。

struct dot{
	int R;
	int G;
	int B;
	dot(int a,int b,int c){
		R = a;
		G = b;
		B = c;
	}
}

將string轉換爲 dot,單獨拿出來一個函數。

3、區域計算,區域數量爲(m×n)/(p×q),行數爲n/q,使用vector 鏈接,注意區分行就行。

4、初始背景色,前景色,在每行開始的時候設置爲前驅,標記前驅來省略對顏色的更改。

5、模擬的時候不要漏掉題目給的情況,宏觀上嚴密把控後,再局部實現。

void outputRGB()
{
    int size = list.size(); //區域的塊數
    int gap = m/p;       // 每行gap個區域
    int i;
    dot pre; //前一個區域
    dot curr; //當前區域
    for(i=0;i<size;i++)
    {
        curr = list[i];
        if(i%gap == 0) // 1、每行第一個設置前驅爲默認背景色
            pre = defaultDot;

        if(isEqual(curr,pre))   // 2、當前顏色和前驅顏色相同,不做更改直接輸出一個空格
            outputSpace();
        else if(isEqual(curr,defaultDot)){ // 3、當前顏色爲默認背景顏色
            outputDefaultRGB();     // 輸出重置終端,而不是當前顏色
            outputSpace();         //輸出一個空格
        }
        else{ // 普通輸出
            outputSingleRGB(curr);
        }
        if( (i+1)%gap ==0 && !isEqual(curr,defaultDot)){ // 每行最後一個不是默認顏色
            outputDefaultRGB();
        }
        if( (i+1)%gap == 0 ) // 每行最後一個
            printf(R"(\x0A)"); //輸出'\n'

        pre = curr; // 更新前驅
    }
}

確保上訴不漏掉題目所給出的情況後,再一一實現子函數。

最終AC代碼如下。

#include <iostream>
#include <cstdio>
#include <string>
#include <vector>
using namespace std;
int m,n;
int p,q;
struct dot{
    int R;
    int G;
    int B;
    dot(int a,int b,int c){
        R = a;
        G = b;
        B = c;
    }
    dot(){
        R=G=B=0;
    }
};
dot arr[1100][2000];
dot defaultDot(0,0,0); // 默認背景色
vector<dot> list;
int toAscii(char ch)
{
    if(ch>='a')
        return ch-'a'+10;
    else
        return ch-'0';
}
dot strToDot(string str)
{
    str.erase(str.begin()); //刪除前導#
    dot res;
    int len = str.length();
    if(len == 6){
        res.R = toAscii(str[0])*16 + toAscii(str[1]);
        res.G = toAscii(str[2])*16 + toAscii(str[3]);
        res.B = toAscii(str[4])*16 + toAscii(str[5]);
    }
    else if(len == 1){
        str += str[0];
        res.R = res.G = res.B = toAscii(str[0])*16 + toAscii(str[1]);
    }
    else{ //len = 3
        res.R = toAscii(str[0])*16 + toAscii(str[0]);
        res.G = toAscii(str[1])*16 + toAscii(str[1]);
        res.B = toAscii(str[2])*16 + toAscii(str[2]);
    }
    return res;
}
dot countDot(int row,int endRow,int col,int endCol)
{
    dot res;
    int i,j;
    for(i=row;i<endRow;i++)
        for(j=col;j<endCol;j++)
        {
            res.R += arr[i][j].R;
            res.G += arr[i][j].G;
            res.B += arr[i][j].B;
        }
    int area = (endRow-row)*(endCol-col);
    res.R /= area;
    res.G /= area;
    res.B /= area;
    return res;
}
bool isEqual(dot a,dot b)
{
    return (a.R==b.R && a.G==b.G && a.B==b.B);
}
void outputDefaultRGB()
{
    printf(R"(\x1B\x5B\x30\x6D)"); // ESC[0m
}
void outputNumber(int num)
{
    string str;
    str = to_string(num);
    for(char i : str)
    {
        int a = int(i); //轉化爲ascii碼
        printf(R"(\x)");
        printf("%X",a);
    }
}
void outputSingleRGB(dot curr)
{
    printf(R"(\x1B\x5B\x34\x38\x3B\x32\x3B)"); // ESC[48;2;
    outputNumber(curr.R);
    printf(R"(\x3B)");
    outputNumber(curr.G);
    printf(R"(\x3B)");
    outputNumber(curr.B);
    printf(R"(\x6D\x20)");     // m+space
}
void outputSpace()
{
    printf(R"(\x20)");
}
void outputRGB()
{
    int size = list.size();
    int gap = m/p;       // 每行gap個區域
    int i;
    dot pre; //前一個區域
    dot curr; //當前區域
    for(i=0;i<size;i++)
    {
        curr = list[i];
        if(i%gap == 0) // 1、每行第一個設置前驅爲默認背景色
            pre = defaultDot;

        if(isEqual(curr,pre))   // 2、當前顏色和前驅顏色相同,不做更改直接輸出一個空格
            outputSpace();
        else if(isEqual(curr,defaultDot)){ // 3、當前顏色爲默認背景顏色
            outputDefaultRGB();     // 輸出重置終端,而不是當前顏色
            outputSpace();         //輸出一個空格
        }
        else{ // 普通輸出
            outputSingleRGB(curr);
        }
        if( (i+1)%gap ==0 && !isEqual(curr,defaultDot)){ // 每行最後一個不是默認顏色
            outputDefaultRGB();
        }
        if( (i+1)%gap == 0 ) // 每行最後一個
            printf(R"(\x0A)"); //輸出'\n'

        pre = curr; // 更新前驅
    }
}
int main() {
    cin>>m>>n;
    cin>>p>>q;
    int i,j;
    string str;
    for(i=1;i<=n;i++)
        for(j=1;j<=m;j++)
        {
            cin>>str;
            arr[i][j] = strToDot(str);
        }
    i = j = 1;
    while( i<=n )
    {
        dot t = countDot(i,i+q,j,j+p);
        list.push_back(t);
        j += p;
        if( j > m )
        {
            j = 1;
            i += q;
        }
    }
    outputRGB();
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章