Search code examples
c++printingdatagridgridascii

how to print 2 nested grids to console in C++?


I'm trying to print a grid inside each of the cells of another grid. to be specific. imagine a 7x7 grid which each cell is 3x3. also i need padding between each cells of parent grid. for the second grid which is 3v3 , each cell prints a number between 1-9 which is given in the function of child grid.

for example

function childGridprinter(int a, int b, int c, int d)
{
//the result of child grind should be like this:
  a
b   c
  d
return "\n..a";
}

this will be embedder into parent grid like for 3v3 inside 3v3 :

  a       a      a
b   c   b   c  b    c
  d       d       d

  a       a      a
b   c   b   c  b    c
  d       d       d

  a       a      a
b   c   b   c  b    c
  d       d       d

if its not possible using console, whats the easy solution. thanks in advance.

I already have a printing function which prints a grid with values but expanding it to show more data was needed. for example each cell needs to show north,east,west and south data(between 1-9). i don't wanna go for opengl because its hard to implement it in my code.


Solution

  • #include <cassert>
    #include <vector>
    #include <iostream>
    
    auto make_grid(const std::size_t horizontal_repeat, const std::size_t vertical_repeat, const std::vector<std::vector<char>>& stamp)
    {
    #if _DEBUG
        assert(horizontal_repeat >= 1);
        assert(vertical_repeat >= 1);
        assert(stamp.size() >= 1);
        assert(stamp[0].size() >= 1);
    
        for (const auto& row : stamp)
        {
            assert(stamp[0].size() == row.size());
        }
    #endif
    
        // The total width and height of the output
        // (width-1) spaces and (heigh-1) empty lines will be added.
        std::size_t total_width = (horizontal_repeat * stamp.size()) + (horizontal_repeat - 1ul);
        std::size_t total_height = (vertical_repeat * stamp.size()) + (vertical_repeat - 1ul);
    
        // the output array
        std::vector<std::vector<char>> grid(total_height, std::vector<char>(total_width));
    
        // allow for 1 extra space or extra empty line
        std::size_t stamp_height = { stamp.size() + 1ul };
        std::size_t stamp_width = { stamp[0].size() + 1ul };
    
        for (std::size_t y{ 0ul }; y < total_height; ++y)
        {
            // calculate the vertical offset in the stamp
            // but also allow for an space
            std::size_t stamp_y = y % stamp_height;
    
            for (std::size_t x{ 0ul }; x < total_width; ++x)
            {
                std::size_t stamp_x = x % stamp_width;
    
                // if the horizontal or vertical offset are outside the size of the input stamp
                // output a space otherwise use the values from the stamp
                auto output_char = ((stamp_y == stamp.size()) || (stamp_x == stamp[0].size())) ? ' ' : stamp[stamp_y][stamp_x];
                grid[y][x] = output_char;
            }
        }
    
        return grid;
    }
    
    std::ostream& operator<<(std::ostream& os, const std::vector<std::vector<char>>& grid)
    {
        for (const auto& row : grid)
        {
            for (const auto c : row)
            {
                std::cout << c;
            }
            std::cout << "\n";
        }
    
        return os;
    }
    
    // and then the program is just those two lines.
    int main()
    {
        std::vector<std::vector<char>> stamp{ {'.','e','.'}, {'f','*','g'}, {'.','h','.'} };
        std::cout << make_grid(4, 3, stamp);
    
        return 0;
    }