c++ - 我应该如何为我的 C++ 程序实现泛洪填充功能?

标签 c++ vector flood-fill

我目前正在寻找像这样的东西:

.............
.............
..XXX.....X..
..XXX.....X..
..XXX........
..XXX........
..XXXXXXX....
..XXXXXXX....
..XXXXXXX....
.............
.............

进入这个:

.............
.............
..XXX.....O..
..XXX.....O..
..XXX........
..XXX........
..XXXXXXX....
..XXXXXXX....
..XXXXXXX....
.............
.............

用户输入 ./a.exe input4.txt floodfill 2 10 o

我相信我需要在程序中实现一些递归才能只查看与用户指针匹配的索引(包括上、下、左和右的位置),而不是读取整个 vector (我不介意这样做,但不知道我会如何开始这样做)。

这是我目前为止的洪水填充功能代码:

void floodfilll(vector<vector<char>> &vec, int x, int y, char r, char dum)
{
 int ii; 
 ii = 0;
 int jj; 
 jj = 0;
for (int i = 0; i < vec.size(); i ++) {
        for (int j = 0; j < vec[i].size(); j++) {
            if (vec[i][j] == r) {
                vec[i][j] == r;
                if ((i + ii) > 0) {
                    if (vec[i-1][j] == r)
                        vec[i-1][j] = dum;
                        vec[i][j] == r;
                    ii--;
                    floodfilll(vec, x + ii, y, r, dum);
                }
                if ((j + jj) > 0) {
                    if(vec[i][j-1] != r)
                        vec[i][j-1] = dum;
                        vec[i][j] == r;
                    jj--;
                    floodfilll(vec, x, y + jj, r, dum);
                }
                if ((i + ii)<vec.size()) {
                    if (vec[i+1][j] != r)
                        vec[i+1][j] = dum;
                        vec[i][j] == r;
                    ii++;
                    floodfilll(vec, x + ii, y, r, dum);
                }
                if ((j + jj)<vec[i].size()) {
                    if (vec[i][j+1] != r)
                        vec[i][j+1] = dum;
                        vec[i][j] == r;
                    jj++;
                    floodfilll(vec, x, y + jj, r, dum);
                }
            }
        }
        replacee(vec, dum, r);
    }
}

注意:我使用名为 replacee 的函数将 Var dum 替换为 Var R。Var dum 被分配为“i”,r 为“X”。

此外,文本文件被解析为 char 的 (char) 的 2d vector **

这正是我程序的其余部分所基于的方式。这是替换函数:

    void replacee(vector<vector<char>> &vec, char oldd, char neww)
    {
        for (vector<char> &v : vec) // reference to innver vector
        {
            replace(v.begin(), v.end(), oldd, neww); // standard library algorithm
        }
    }

这是我使用的 int 主文件:

int main(int argc, char* argv[]) {

fstream fin; char ch;
string name (argv[1]); //File Name.
vector<vector<char>> data;
// 2D Vector.
vector<char> temp;
// Temporary vector to be pushed 
// into vec, since its a vector of vectors.
fin.open(name.c_str(),ios::in);
// Assume name as an arbitary file.
string argument2 (argv[2]);
while(fin)
{
    ch = fin.get();
    if(ch!='\n') {
        temp.push_back(ch);
    }
    else 
    { 
        data.push_back(temp); 
        temp.clear(); 
    }
}
if (argument2 == "floodfill") {
    string argument3 (argv[3]);
    string argument4 (argv[4]);
    string argument5 (argv[5]);
    int x = 0;
    int y = 0;
    stringstream xx(argument3);
    stringstream yy(argument4);
    xx >> x;
    yy >> y;
    floodfilll(data, x, y, argument5[0], 'i');
    for (int m = 0; m < data.size(); m ++) {
        for (int n = 0; n < data[m].size(); n++) {
            cout << data[m][n];
        }
        cout << endl;
    }
}

fin.close();
} 

抱歉,如果我看起来只是为了抓取而粘贴代码,这是为了防止任何人有超出我的思维模式的解决方案。 int mainreplacee 函数按预期工作。我只是需要帮助想出一种方法来制作 floodfilll正常工作。

这是我的代码得到的输出:

$ ./a.exe input4.txt floodfill 2 10 o
.............
.............
..XXX.....X..
..XXX.....X..
..XXX........
..XXX........
..XXXXXXX....
..XXXXXXX....
..XXXXXXX....
.............

最佳答案

为什么要在每次递归中遍历整个字段?

通常情况下,洪水填充的工作方式如下:

  1. 您有一个特定的起点。
  2. 你用预期的颜色填充这个起点
  3. 您检查四个(或 8 个,如果您也考虑对角线)邻居中的每一个,它们的颜色是否与起点最初的颜色相同;如果是,则递归地继续。

所以一个实现可能是这样的:

void floodfill
(
        std::vector<std::vector<char>>& v,
        unsigned int x, unsigned int y, char r
)
{
    char p = v[x][y];
    v[x][y] = r;
    if(x > 0 && v[x - 1][y] == p)
        floodfill(v, x - 1, y, r);
    if(x + 1 < v.size() && v[x + 1][y] == p)
        floodfill(v, x + 1, y, r);
    if(y > 0 && v[x][y - 1] == p)
        floodfill(v, x, y - 1, r);
    if(y + 1 < v[x].size() && v[x][y + 1] == p)
        floodfill(v, x, y + 1, r);
}

请注意,我没有检查要填充的颜色是否与起始像素相同,我最初也没有检查 xy< 的范围检查。为了提高效率,我不会在递归函数中添加这些检查,而是在启动递归的特定入口函数中,因此它们只在需要时执行一次,而不会不必要地重复。

关于c++ - 我应该如何为我的 C++ 程序实现泛洪填充功能?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53247243/

相关文章:

c# - 奇怪的括号行为的 Visual Studio 可能的错误

c++ - 如何制作抽象模板类的 vector

c - Minecraft 洪水填充

matlab - 计算数组中的重复整数

c++ - vector 到函数内的数组

javascript - JavaScript 中的洪水填充算法 - 太多递归

ios - 对 UIImage 执行 floodfill

复杂浮点类型的 C++20 概念

C++ 传递结构化内容的方式?

c++ - 警告 : address of local variable 'angles' returned [-Wreturn-local-addr]