0

I'm attempting to create a square shape from X's and O's (the border being X's and the interior being O's), and I'm trying to avoid the last bit of code with my for loop printing on the same line. Any help would be greatly appreciated!

#include <iostream>
using namespace std;

int main() {
  int x = 0;
  cout << "Please enter an integer for the dimension that will represent the "
          "rows and columns: "
       << endl;
  cin >> x;
  cout << endl;

  for (int i = 0; i <= x; i++) {
    for (int j = x; j > i; j--)
      cout << "X";
    cout << endl;
  }

  for (int i = 0; i < x; i++) {
    for (int j = 0; j < i; j++) {
      cout << " ";
    }
    for (int k = x; k >= i + 1; k--) {
      cout << "X";
    }
    cout << endl;
  }
  cout << endl;

  for (int m = 0; m < x; m++) {
    cout << "X";
  }
  for (int m = 0; m < x - 2; m++) {
    cout << "X";
    for (int n = 0; n < x - 2; n++) {
      cout << "O";
    }
  }
  for (int m = 0; m < x; m++) {
    cout << "X";
  }
  cout << endl;

  return 0;
}
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
Ollivander
  • 11
  • 4
  • Please include sample output of your application and what you want the correct output to be like – eike Oct 03 '19 at 11:36
  • Also, I would advise against using `std::endl` for new lines as that includes an extra `std::flush`. Just use `'\n'` for newlines. – eike Oct 03 '19 at 11:44
  • What do you mean by last bit of code ? – Lars Nielsen Oct 03 '19 at 11:49
  • By the way, you can check the [following link](https://stackoverflow.com/questions/1452721/why-is-using-namespace-std-considered-bad-practice) to understand why `using namespace std;` is the incarnation of evil :) – Fareanor Oct 03 '19 at 12:13

3 Answers3

2

It seems you mean the following editions of your last pattern output.

for (int m = 0; m < x; m++){
        cout << "X";
    }
    cout << endl;
    ^^^^^^^^^^^^^
    for (int m = 0; m < x - 2; m++){
        cout << "X";
        for (int n = 0; n < x - 2; n++){
            cout << "O";
        }
        cout << "X" << endl;
        ^^^^^^^^^^^^^^^^^^^^
    }
    for (int m = 0; m < x; m++){
        cout << "X";
    }
cout << endl;

You could write a separate function that used only one loop to output the pattern.

Here is a demonstration program.

#include <iostream>
#include <iomanip>

std::ostream & square( unsigned int n, 
                       char outer = 'X', 
                       char inner = 'O', 
                       std::ostream &os = std::cout )
{
    if ( n )
    {
        for ( unsigned int i = 0; i < n; i++ )
        {
            os << outer;
            if ( n != 1 )
            {
                os << std::setw( n - 1 ) 
                   << std::setfill( i % ( n - 1 ) == 0 ? outer : inner )
                   << outer;
            }
            os << '\n';
        }
    }

    return os;
}

int main() 
{
    const unsigned int N = 10;

    for ( unsigned int i = 1; i < N; i++ ) square( i ) << '\n';

    return 0;
}

Its output is

X

XX
XX

XXX
XOX
XXX

XXXX
XOOX
XOOX
XXXX

XXXXX
XOOOX
XOOOX
XOOOX
XXXXX

XXXXXX
XOOOOX
XOOOOX
XOOOOX
XOOOOX
XXXXXX

XXXXXXX
XOOOOOX
XOOOOOX
XOOOOOX
XOOOOOX
XOOOOOX
XXXXXXX

XXXXXXXX
XOOOOOOX
XOOOOOOX
XOOOOOOX
XOOOOOOX
XOOOOOOX
XOOOOOOX
XXXXXXXX

XXXXXXXXX
XOOOOOOOX
XOOOOOOOX
XOOOOOOOX
XOOOOOOOX
XOOOOOOOX
XOOOOOOOX
XOOOOOOOX
XXXXXXXXX
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
0
  1. Split your code into functions that fullfill the simplest task ( according to the saying divide and conquer )
  2. Avoid repeating the code

I'd do something like this:

#include <iostream>
#include <sstream>

static void printEdge(const size_t length) {
    std::stringstream out;
    for(size_t idx{}; idx < length; ++idx) {
        out << "X" << ((idx +1 < length) ? " " : "" );
    }
    std::cout << out.str() << std::endl;
}

static void printLine(const size_t length) {
    std::stringstream out;
    out << "X ";
    for(size_t idx{}; idx < length-2; ++idx) {
        out << "O" << ((idx +1 < length-2) ? " " : "" );
    }
    out << " X";
    std::cout << out.str() << std::endl;
}

static void printRectangle(const size_t length) {
    printEdge(length);
    for(size_t idx{}; idx < length -2; ++idx) {
        printLine(length);
    }
    printEdge(length);
}


int main() {
    int x = 0;
    std::cout
        << "Please enter an integer for the dimension that will represent the rows and columns: "
        << std::endl;
    std::cin >> x;
    printRectangle(x);
}
Verthais
  • 300
  • 3
  • 14
  • Too much code for such a simple function. Splitting is fine until a certain limit. Splitting for too atomic operations adds unnecessary function calls / noise (think that the code needs to be as readable as possible). – Fareanor Oct 03 '19 at 11:59
0

How do I avoid this printing on the same line?

I'm not sure that I have well understood your question but you just have to print on a new line by using \n (Escaping n will be interpreted as a line feed).
For example:

std::cout << '\n'; // Add a new line

So a possible implementation would be:

void drawSquareShape(size_t rows, size_t cols)
{
    for(size_t i = 0; i < rows; ++i)
    {
        for(size_t j = 0; j < cols; ++j)
        {
            std::cout << ( (i == 0 || j == 0 || i == rows-1 || j == cols-1) ? 'X' : 'O' );
            if(j < cols-1)
                std::cout << ' ';
        }
        std::cout << '\n';
    }
    std::cout.flush();
}

And could be used as follows:

int main()
{
    drawSquareShape(5, 8);

    return 0;
}

Which draws in the console the following output:

X X X X X X X X
X O O O O O O X
X O O O O O O X
X O O O O O O X
X X X X X X X X

EDIT:

I know this is a rectangle and not a square, but it's easy to modify/specialize this function to draw a square.
For example:

void drawSquare(size_t s)
{
    drawSquareShape(s, s);
}
Fareanor
  • 5,900
  • 2
  • 11
  • 37