Print 10 × 10 square of X and O characters, split diagonally I'm going through a beginners exercise for writing a small program in Java. My task is to print out (i.e. find an algorithm) the following output:


XOOOOOOOOO
XXOOOOOOOO
XXXOOOOOOO
XXXXOOOOOO
XXXXXOOOOO
XXXXXXOOOO
XXXXXXXOOO
XXXXXXXXOO
XXXXXXXXXO
XXXXXXXXXX



I have figured out how to do it but the code I wrote seems repetitive and tedious. How can I shorten my code?

package helloWorld;

public class HelloWorld {

public static void main(String[] args) 
{
    // Output


    // Algorithm 1

    boolean ft = true;

    String s = new String();
    for(int i = 0; i &lt; 10; i++)
    {
        s  += "X";
        for(int j = 0; j &lt; 9; j++)
        {
            if(i == 0)
            {

                s += "O";
            }

            if(i == 1)
            {

                if(ft == true)
                {
                    s+="X";
                    ft = false;
                }
                if(j == 8)
                {
                    continue;
                }
                s += "O";
            }

            if(i == 2)
            {

                if(ft == true)
                {
                    s+= "XX";
                    ft = false;

                }

                if(j == 7)
                {

                    break;
                }
                s += "O";

            }

            if(i == 3)
            {

                if(ft == true)
                {
                    s+= "XXX";
                    ft = false;

                }

                if(j == 6)
                {

                    break;
                }
                s += "O";
            }

            if( i == 4)
            {
                if(ft == true)
                {
                    s+= "XXXX";
                    ft = false;

                }

                if(j == 5)
                {

                    break;
                }
                s += "O";
            }

            if( i == 5)
            {
                if(ft == true)
                {
                    s+= "XXXXX";
                    ft = false;

                }

                if(j == 4)
                {

                    break;
                }
                s += "O";
            }

            if( i == 6)
            {
                if(ft == true)
                {
                    s+= "XXXXXX";
                    ft = false;

                }

                if(j == 3)
                {

                    break;
                }
                s += "O";
            }

            if( i == 7)
            {
                if(ft == true)
                {
                    s+= "XXXXXXX";
                    ft = false;

                }

                if(j == 2)
                {

                    break;
                }
                s += "O";
            }

            if( i == 8)
            {
                if(ft == true)
                {
                    s+= "XXXXXXXX";
                    ft = false;

                }

                if(j == 1)
                {

                    break;
                }
                s += "O";
            }

            if( i == 9)
            {
                if(ft == true)
                {
                    s+= "XXXXXXXXX";
                    ft = false;

                }

                if(j == 0)
                {

                    break;
                }
                s += "O";
            }


        }
        System.out.println(s);
        s = "";
        ft = true;

    }
}

}
Lots of answers already, but most of them seem to be about alternative solutions. I'll review your code on the details and show you how to refactor your code step by step. (This is a long answer, link to bottom of answer)



String s = new String();


Creating a new String could be simplified to "". The only time you'll actually use the String constructor is for creating strings from arrays like char[] or byte[].

The first line of output

for(int i = 0; i &lt; 10; i++)
{
    s  += "X";
    for(int j = 0; j &lt; 9; j++)
    {
        if(i == 0)
        {

            s += "O";
        }


Seems simple enough. Add an X, then add 9 O's.

The second line of output

for(int i = 0; i &lt; 10; i++)
{
    s  += "X";
    for(int j = 0; j &lt; 9; j++)
    {

        if(i == 1)
        {

            if(ft == true)
            {
                s+="X";
                ft = false;
            }
            if(j == 8)
            {
                continue;
            }
            s += "O";
        }


ft starts off true. Like that, you'll print 1 X, then enter the j loop, add one more X, then an O, and you loop from there to add the remaining characters. This leads to the problem that you have one character extra... so you have to add the j == 8 check to stop the algorithm from printing a line with 10 characters.

You can check boolean conditions without an equality operator, like so:

if(ft)
{
    s+="X";
    ft = false;
}


This will work just as well as the ft == true check.

The third line of output

for(int i = 0; i &lt; 10; i++)
{
    s  += "X";
    for(int j = 0; j &lt; 9; j++)
    {

        if(i == 2)
        {

            if(ft == true)
            {
                s+= "XX";
                ft = false;

            }

            if(j == 7)
            {

                break;
            }
            s += "O";

        }


Same as the second line, except here you add two X on the first iteration, and to compensate, you break one iteration earlier. This is kind of problematic, since you now have to duplicate your code for each iteration. You're missing out on the power of the for-loop.

Did you know Strings come with a length() method? You can retrieve the current length with it.

We can use that method to change the for loop so that each iteration adds just one character.

        if(i == 2)
        {

            if(ft == true)
            {
                s+= "XX";
                ft = false;

            }

            if(j == 7)
            {

                break;
            }
            s += "O";

        }


If we use the length() method here to determine ft...

        if(i == 2)
        {
            if(ft == true)
            {
                s+= "XX";
                ft = s.length() &lt; 3;
            }

            if(j == 7)
            {

                break;
            }
            s += "O";

        }


Then we can change the code so that it only adds one character at a time, removing the condition that was added to prevent going over 10 characters.

        if(i == 2)
        {
            if(ft == true)
            {
                s+= "X";
                ft = s.length() &lt; 3;
            } 
            else
            {
                s += "O";
            }
        }


We could copy this change for all cases...

        if(i == 3)
        {
            if(ft == true)
            {
                s+= "X";
                ft = s.length() &lt; 4;
            } 
            else
            {
                s += "O";
            }
        }


but that seems like we're still duplicating code.

Fortunately, it seems we can make use of the fact that... if i == n, then the check needs to be s.length() &lt; n + 1.

So let's apply that change.

        if(i == 3)
        {
            if(ft == true)
            {
                s+= "X";
                ft = s.length() &lt; (i + 1);
            } 
            else
            {
                s += "O";
            }
        }


Now all the cases look like this:

        if(i == 2)
        {
            if(ft == true)
            {
                s+= "X";
                ft = s.length() &lt; (i + 1);
            } 
            else
            {
                s += "O";
            }
        }

        if(i == 3)
        {
            if(ft == true)
            {
                s+= "X";
                ft = s.length() &lt; (i + 1);
            } 
            else
            {
                s += "O";
            }
        }


Seems like we can merge the cases i == 1 through i == 9 because they're all the same. And since i only goes to 9 because of the i &lt; 10 condition, all we're interested in is checking that it's not the first iteration:

        if(i != 0)
        {
            if(ft == true)
            {
                s+= "X";
                ft = s.length() &lt; (i + 1);
            } 
            else
            {
                s += "O";
            }
        }


Here's where we're at now.

boolean ft = true;

String s = "";
for(int i = 0; i &lt; 10; i++)
{
    s  += "X";
    for(int j = 0; j &lt; 9; j++)
    {
        if(i == 0)
        {

            s += "O";
        }

        if(i != 0)
        {
            if(ft)
            {
                s+= "X";
                ft = s.length() &lt; (i + 1);
            } 
            else
            {
                s += "O";
            }
        }

    }
    System.out.println(s);
    s = "";
    ft = true;

}


Now... if we modified the setting of ft to do the s.length() &lt; (i + 1) check before we tried to add a new character to the line, we could even merge the i == 0 case.

for(int i = 0; i &lt; 10; i++)
{
    s  += "X";
    for(int j = 0; j &lt; 9; j++)
    {
        ft = s.length() &lt; i;
        if(i == 0)
        {

            s += "O";
        }

        if(i != 0)
        {
            if(ft)
            {
                s += "X";
            } 
            else
            {
                s += "O";
            }
        }

    }
    System.out.println(s);
    s = "";
    ft = true;

}


Now, in the case i == 0, ... you enter the j-for loop with one "X" in your string already. So ft would be set to false, always. And in the i != 0 case, if ft is not true... we do the same thing as the i == 0 case. So we can remove the checks whether i is or is not 0, as it will work just fine:

for(int i = 0; i &lt; 10; i++)
{
    s  += "X";
    for(int j = 0; j &lt; 9; j++)
    {
        ft = s.length() &lt; i;
        if(ft)
        {
            s += "X";
        } 
        else
        {
            s += "O";
        }
    }
    System.out.println(s);
    s = "";
    ft = true;

}


Now that we've made that change, the code is short. But it's not that clear yet. ft is a pretty meaningless variable. If we renamed it to notEnoughXYet, the code becomes a bit more clearer:

boolean notEnoughXYet = true;

String s = "";
for(int i = 0; i &lt; 10; i++)
{
    s  += "X";
    for(int j = 0; j &lt; 9; j++)
    {
        notEnoughXYet = s.length() &lt; i;
        if(notEnoughXYet)
        {
            s += "X";
        } 
        else
        {
            s += "O";
        }
    }
    System.out.println(s);
    s = "";
    notEnoughXYet = true;

}


... We can still go further, though.

There are two places we set notEnoughXYet to true and s to "". Maybe we can merge them?

What about putting it at the start of each iteration of the i for loop?

for(int i = 0; i &lt; 10; i++)
{
    boolean notEnoughXYet = true;

    String s = "";
    s  += "X";
    for(int j = 0; j &lt; 9; j++)
    {
        notEnoughXYet = s.length() &lt; i;
        if(notEnoughXYet)
        {
            s += "X";
        } 
        else
        {
            s += "O";
        }
    }
    System.out.println(s);
    s = "";
    notEnoughXYet = true;

}


Like this, we see that we can eliminate some more duplication: the setting of s and notEnoughXYet at the bottom can disappear. And s could be initialized to X.

for(int i = 0; i &lt; 10; i++)
{
    boolean notEnoughXYet = true;
    String s = "X";
    for(int j = 0; j &lt; 9; j++)
    {
        notEnoughXYet = s.length() &lt; i;
        if(notEnoughXYet)
        {
            s += "X";
        } 
        else
        {
            s += "O";
        }
    }
    System.out.println(s);
}


You could even move notEnoughXYet to the inner for loop...

for(int i = 0; i &lt; 10; i++)
{
    String s = "X";
    for(int j = 0; j &lt; 9; j++)
    {
        boolean notEnoughXYet = s.length() &lt; i;
        if(notEnoughXYet)
        {
            s += "X";
        } 
        else
        {
            s += "O";
        }
    }
    System.out.println(s);
}


Or get rid of it entirely.

for(int i = 0; i &lt; 10; i++)
{
    String s = "X";
    for(int j = 0; j &lt; 9; j++)
    {
        if(s.length() &lt; i)
        {
            s += "X";
        } 
        else
        {
            s += "O";
        }
    }
    System.out.println(s);
}


There's still a double setting of X to s, though. If you wanted to change the characters you'd have to change it in two places. Maybe you should just make the inner loop also do 10 iterations?

for(int i = 0; i &lt; 10; i++)
{
    String s = "";
    for(int j = 0; j &lt; 10; j++)
    {
        if(s.length() &lt;= i)
        {
            s += "X";
        } 
        else
        {
            s += "O";
        }
    }
    System.out.println(s);
}


Note that I have changed the s.length() &lt; i to s.length() &lt;= i because now the first iteration also needs to put an X.

The result

What we've just done, is step for step, identifying duplication or similarities, and then looking for the differences in that duplication to merge the duplication. The end result is code which, whilst containing more complexity because it doesn't spell out each case individually, is considerably shorter and should be more understandable.