meo83
meo83

Reputation: 31

Creating an X pattern with user input in Java?

I've been at this for a long time now, a few days actually, and I just can't seem to understand what's wrong with my loops!

I have to create an 'X' pattern with user input. If the user entered four, it would be like this:

X      X
 X    X
  X  X
   XX
   XX
  X  X
 X    X
X      X

It's basically a "V" stacked on top of an upside down one. But, my coding results in something really weird.

    XX
    XX
    XX
    XX
X    X
X    X
X    X
X    X

The top part only prints out the beginning spaces and the second part only prints out the middle ones!

    int num = 0;
    System.out.println("Enter a value between 2 and 10.");
    num = keyNum.nextInt();
    } 
    for (int a = 0; a < num; a++) 
    {
        System.out.println("");
        for (int b = 0; b <= (num - 1); b++) 
        {
            System.out.print(" ");
        }
        System.out.print("X");
        for (int c = num + 2; c <= 0; c -= 2)
        {
            System.out.print(" ");  
        }
        System.out.print("X");
    for (int d = 0; d < num; d++) 
    {
        System.out.println("");
        for (int e = (num - 1); e <= 0; e--) 
        {
            System.out.print(" ");
        }
        System.out.print("X");
        for (int f = 0; f <= num + 2; f += 2)
        {
            System.out.print(" ");  
        }
        System.out.print("X");
    }

Any kind of help would be appreciated. Thanks in advance!

Upvotes: 2

Views: 1122

Answers (5)

jrook
jrook

Reputation: 3519

Other answers do a good job addressing the issues in the OP's code. Here is a recursive approach to the problem:

import java.util.Scanner;

public class DrawX {
    public static void main(String[] args) {
        int n = Integer.valueOf(new Scanner(System.in).nextLine());
        //To obtain a figure similar to the OP's
        drawX(2*(n - 1), 2* (n - 1), false);
    }

    static void drawX(int n, int limit, boolean z) {
        if(Math.abs(n) > limit) return;
        System.out.println(
          String.join("", Collections.nCopies((limit-Math.abs(n))/2, " ")) +
          "x" + //First x
          String.join("", Collections.nCopies(Math.abs(n), " ")) + 
          "x"  //Second x
          );
        if(n==0 && !z) drawX(n, limit, true); //This only happens once!
        else drawX(n - 2, limit, false);
    }
}

Execution:

10
x                  x
 x                x
  x              x
   x            x
    x          x
     x        x
      x      x
       x    x
        x  x
         xx
         xx
        x  x
       x    x
      x      x
     x        x
    x          x
   x            x
  x              x
 x                x
x                  x

The idea is to calculate the number of spaces needed before the first x and the spaces between xs for each line -both obtainable by some simple mathematical observations- and print lines recursively using String.join and Collections.nCopies to repeat spaces. Since the line corresponding to n=0 needs to be printed twice, we need to add a Boolean variable to keep track of when this happens.

It should be easy to convert the recursive function to a loop and I'll leave that to the OP.

Upvotes: 0

Chai T. Rex
Chai T. Rex

Reputation: 3020

For your spacing loops, you use a variable, num, which doesn't change after each line. For example:

for (int b = 0; b <= (num - 1); b++)
{
    System.out.print(" ");
}

This leads to the spacing staying the same throughout both outer loops. Perhaps you meant to use the loop variables a and d or something like that.

Upvotes: 0

Khalid Shah
Khalid Shah

Reputation: 3232

you simple add two conditions for print asterisks on both diagonals otherwise just print the space.

import java.util.Scanner;

public class XPattern {

  public static void main(String[] args) {
    Scanner scan = new Scanner(System.in);
    System.out.print("Enter a number : ");
    int size = scan.nextInt();
    printXPattern(size*2);
  }

  private static void printXPattern(int size) {
    for (int i = 0; i < size ; i++) {
      for (int j = 0; j < size ; j++) {
        if (i == j || i + j == size - 1) {//conditions for diagonals
          System.out.print("*");
        } else {
          System.out.print(" ");
        }
      }
      System.out.println();
    }
  }
}

output :

Enter a number : 5
*        *
 *      * 
  *    *  
   *  *   
    **    
    **    
   *  *   
  *    *  
 *      * 
*        *

Upvotes: 0

flakes
flakes

Reputation: 23614

You can figure this out with some simple math. First lets plot some 2D functions.

Z = Y + X                             Z = Y - X

x/y| 0  1  2  3  4  5  6  7           x/y| 0  1  2  3  4  5  6  7 
---|-----------------------           ---|----------------------- 
 0 | 0  1  2  3  4  5  6  7            0 | 0 -1 -2 -3 -4 -5 -6 -7 
   |                                     |                        
 1 | 1  2  3  4  5  6  7  8            1 | 1  0 -1 -2 -3 -4 -5 -6 
   |                                     |                        
 2 | 2  3  4  5  6  7  8  9            2 | 2  1  0 -1 -2 -3 -4 -5  
   |                                     |                        
 3 | 3  4  5  6  7  8  9  10           3 | 3  2  1  0 -1 -2 -3 -4  
   |                                     |                        
 4 | 4  5  6  7  8  9  10 11           4 | 4  3  2  1  0 -1 -2 -3
   |                                     |                        
 5 | 5  6  7  8  9  10 11 12           5 | 5  4  3  2  1  0 -1 -2
   |                                     |                        
 6 | 6  7  8  9  10 11 12 13           6 | 6  5  4  3  2  1  0 -1
   |                                     |                        
 7 | 7  8  9  10 11 12 13 14           7 | 7  6  5  4  3  2  1  0

You can see that the backward diagonal is determined by the invariant Z = 0 = Y - X and the forward diagonal is determined by Z = 7 = Y + X where 7 is 2*inputSize - 1

Putting this altogether:

int inputSize = 4;
int forwardDiagonal = inputSize*2 - 1;
for (int y = 0; y < inputSize*2; y++) {
    for (int x = 0; x < inputSize*2; x++) {
        if (y - x == 0) {
            System.out.print("X");
        } else if (y + x == forwardDiagonal) {
            System.out.print("X");
        } else {
            System.out.print(" ");
        }
    }
    System.out.println();
}

Upvotes: 1

OneCricketeer
OneCricketeer

Reputation: 191681

You should focus on one line at a time, then figure out the math required to get a loop

For example, first line

X      X

Could be expressed by method calls (don't worry if you've not learned methods, this is only hiding the logic of the loops)

printSpaces(0); printX(); printSpaces(6); printX(); printSpaces(0);

Then, the following line, the same method calls, only different numbers

printSpaces(1); printX(); printSpaces(4); printX(); printSpaces(1);

Now, you might start to notice that the outer spaces increase by 1 each time, and the inner spaces decrease by 2.

The inner spaces will decrease by two until reaching zero, but rather than writing a backwards loop, you can actually express that mathematically in terms of the increasing outer spaces amount, 2 X's and the width of the drawn X.

inner_space = (num * 2) - 2 - (outer_spaces * 2)

For the shown examples

inner_space = (4 * 2) - 2 - (0 * 2) = 6
inner_space = (4 * 2) - 2 - (1 * 2) = 4

Therefore, you'd write a top loop like

int num = 4;
// loop 0..3
for (int outerSpace = 0; outerSpace < num; outerSpace++) {
    int innerSpaces =  (num * 2) - 2 - (outerSpace * 2);

    // printSpaces(outerSpace); 
    printX();
    // printSpaces(innerSpaces);
    printX();
    // printSpaces(outerSpace);
}

Now, whether you use methods or loops, is an implementation detail, but this is the pseudo-code for getting the top of the X

Upvotes: 0

Related Questions