Skip to main content
Prettify; put in new versions of prog. and output.
Source Link

My first question is: How exactly does the program go through the for loops? They are nested, so would it create all of the columns (the jj for loop) first? Or does it increment both ii and jj after the block of code finishes?

Neither, really. Nested loops like this do not increment at the same time: the inner loop will run until jj violates the condition (j>numColumnsj > numColumns), then the ii loop (the outer loop) will increment and the whole inner loop will run again. Also, as @JayElston said, only one square is drawn at a time. What this means is that on each run through the inner loop the program draws one row of squares, one in each column. The outer loop repeatedly draws these rows to create the whole checkerboard. So the idea is that the inner loop does not draw whole columns, but rather the part of each column that is in the row currently being worked on.

Secondly, why do I set x = jx = j, and y = iy = i? xx is horizontal and jj is vertical, shouldn't I set x = ix = i and y = jy = j? Both seem to yield the same results.

As far as the x=jx=j and y=iy=i, what you've written isn't quite accurate. xx is actually set to jj times the width of a square, and y is set to i times the width of a square. So if we're on the fourth column, we are four squares horizontally from the starting point, and thus four times the width of a square in the x-direction from the edge. The fact that both yield the same results is only a coincidencecoincidence; it only happens because the checkerboard is square. Change numRowsnumRows to 915 and run the program, then flip-flop them and run it again and you should see the difference. The first time, the number of rows will be 915 (or 16 if you've written the program with <= in the for loops), as expected from the variable name. But when x=i*squareSizex=i*squareSize, the number of columns will be 915. Note that xx and yy are positions at which to draw the squares, not the numbers of the rows and columns. That may make it make more sense.

Something that might help would be to include the line System.out.println("i:"+i+"; j:"+j+"; x:"+x+"; x:"+y); in the inner loop right after GRect square.... (as I've demonstrated in my code below) In Java, System.out.println will show things on the console. Putting in that line will make the program spit out a line each time it draws a square, giving the values of ii, jj, xx, and yy.

import acm.graphics.GLabel; import acm.graphics.GRect; import acm.program.GraphicsProgram;

import acm.graphics.GLabel;
import acm.graphics.GRect;
import acm.program.GraphicsProgram;

public class CheckerBoard extends GraphicsProgram {

  public void run() {
    double squareSize = (double) getHeight() / numRows;

    /*
     * Make a variable to carry the number of the square
     * that's being made. So, the first square will be
     * number 0, the second will be number 1, etc.
     */
    int num = 0;

    /*
     * Run the contents once for each number between 0 and
     * numRows Note the < and not <=. Because we're starting
     * from 0, we need to use <. For example, suppose we
     * wrote int i=0; i<=1; i++. We would get our loop run
     * once with i=0 and once with i=1 before i would not be
     * <= 1. Since our numbers in this case are supposed to
     * be the number of rows, we don't want to loop after we
     * do the one before our numRows or numColumns
     */
    for (int i = 0; i < numRows; i++) {
      /*
       * Run the contents of this loop once for each number
       * between 0 and numColumns, including 0, not
       * including numColumns.
       */
      for (int j = 0; j < numColumns; j++) {
        /*
         * Calculate the position for the next square. If
         * we're in column 4, then the next square should be
         * at 4*(the width of each square).
         */
        double x = j * squareSize;
        double y = i * squareSize;

        /*
         * Create a square that's to be put at our x and y
         * positions calculated just above. Make its width
         * squareSize and its height squareSize.
         */
        GRect square = new GRect(x, y, squareSize, squareSize);

        /*
         * Make some text that will be put down. Use the
         * current value of num for its text
         * (Integer.toString just makes that integer into
         * text), and put it at the x-position we're working
         * with plus 1/4 of a squareSize and the y-position
         * we're working with plus 3/4 of a square. This
         * fakes centering the text in the squares.
         */
        GLabel label = new GLabel(Integer.toString(num), x + squareSize * .25,
            y + squareSize * .75);

        /*
         * Tell the user what our i, j, x, y, and num values
         * are.
         */
        System.out.println("i:" + i + "; j:" + j + "; X:" + x + "; Y:" + y
            + "; num: " + num);

        square.setFilled((i + j) % 2 != 0);
        add(square);

        /*
         * Stick that label on the page, just like with the
         * square.
         */
        add(label);

        /*
         * Increment the number variable (add one to it) so
         * the next square is num+1 (if this is square 0,
         * then the next one should be square 1)
         */
        num++;
      }
    }
  }

  // Change this to make the checkerboard non-square.
  private static final int numRows = 8;
  private static final int numColumns = 8;
}

public class CheckerBoard extends GraphicsProgram {And here's what I get on my console when I run it:

public void run() {
  double squareSize = (double)i:0; getHeight()j:0; /X:0.0; numRows;

Y:0.0; num: /*0
   * Make a variable to carryi:0; thej:1; numberX:25.0; ofY:0.0; thenum: square1
   * that'si:0; beingj:2; madeX:50. So, the first0; squareY:0.0; willnum: be2
  i:0; *j:3; numberX:75.0; Y:0, the second will be number 1, etc.
 0; num: */3
  inti:0; numj:4; =X:100.0; Y:0.0;

  num: /*4
   * Run the contents once for eachi:0; numberj:5; betweenX:125.0; Y:0 and
   * numRows Note the < and not <=. Because0; we'renum: starting5
  i:0; *j:6; fromX:150.0; Y:0, we need to use <. For example,0; supposenum: we6
   * wrote int i=0;i:0; i<=1;j:7; i++X:175. We would get0; ourY:0.0; loopnum: run7
   * once with i=0 and once with i=1 before i would not be
   *:1; <=j:0; 1X:0. Since our numbers in this case0; areY:25.0; supposednum: to8
   * be the number of rows, we don'ti:1; wantj:1; toX:25.0; loopY:25.0; afternum: we9
   * do the one before our numRowsi:1; orj:2; numColumns
X:50.0; Y:25.0; num: */10
  for (int i:1; =j:3; X:75.0; i < numRows; i++) {
  Y:25.0; num: /*11
i:1; j:4; X:100.0; Y:25.0; num: *12
i:1; Runj:5; theX:125.0; contentsY:25.0; ofnum: this13
i:1; loopj:6; onceX:150.0; forY:25.0; eachnum: number14
i:1; j:7; X:175.0; Y:25.0; num: *15
i:2; betweenj:0; X:0 and numColumns,.0; includingY:50.0; 0,num: not16
     *i:2; includingj:1; numColumnsX:25.
  0; Y:50.0; num: */17
    for (inti:2; j =:2; X:50.0; j < numColumns;Y:50.0; j++)num: {18
 i:2; j:3; X:75.0; Y:50.0; num: /*19
       * Calculate the position for thei:2; nextj:4; squareX:100. If
       * we're in column 4, then the next0; squareY:50.0; shouldnum: be20
       * at 4*(the width ofi:2; eachj:5; square)X:125.
    0; Y:50.0; num: */21
      double x =i:2; j * squareSize;
      double y:6; =X:150.0; iY:50.0; *num: squareSize;
22
 i:2; j:7; X:175.0; Y:50.0; num: /*23
       * Create a square that's to be puti:3; atj:0; ourX:0.0; xY:75.0; andnum: y24
       * positions calculatedi:3; justj:1; aboveX:25.0; MakeY:75.0; itsnum: width25
       * squareSize and itsi:3; heightj:2; squareSizeX:50.
    0; Y:75.0; num: */26
      GRect square =i:3; newj:3; GRect(x,X:75.0; y,Y:75.0; squareSize,num: squareSize);
27
 i:3; j:4; X:100.0; Y:75.0; num: /*28
       * Make some text that willi:3; bej:5; putX:125.0; downY:75.0; Usenum: the29
       *i:3; currentj:6; valueX:150.0; ofY:75.0; num for its: text30
      i:3; *j:7; (IntegerX:175.toString just makes0; thatY:75.0; integernum: into31
       * text), and put iti:4; atj:0; theX:0.0; x-positionY:100.0; we'renum: working32
       * with plus 1/4 ofi:4; aj:1; squareSizeX:25.0; andY:100.0; thenum: y-position33
       * we're working with plus 3/4 ofi:4; aj:2; squareX:50. This
       * fakes centering the text in the0; squaresY:100.
     0; num: */34
      GLabel label =i:4; newj:3; GLabel(IntegerX:75.toString(num), x + squareSize *0; Y:100.25,
          y + squareSize0; *num: .75);
35
 i:4; j:4; X:100.0; Y:100.0; num: /*36
       * Tell the user what our i,:4; j, x,:5; y,X:125.0; andY:100.0; num: values37
      i:4; *j:6; areX:150.
    0; Y:100.0; num: */38
    i:4; j:7; System.outX:175.println("i0; Y:"100.0; +num: 39
i + "; j:" +5; j + ";:0; X:" + x + ";0.0; Y:"125.0; +num: y40
        i:5; j:1; +X:25.0; ";Y:125.0; num: " + num);
41
      square.setFilled((i +:5; j):2; %X:50.0; 2Y:125.0; !=num: 0);42
 i:5; j:3; X:75.0; Y:125.0; num: add(square);
43
 i:5; j:4; X:100.0; Y:125.0; num: /*44
       * Stick that label on thei:5; page,j:5; justX:125.0; likeY:125.0; withnum: the45
      i:5; *j:6; squareX:150.
    0; Y:125.0; num: */46
 i:5; j:7; X:175.0; Y:125.0; num: add(label);
47
 i:6; j:0; X:0.0; Y:150.0; num: /*48
 i:6; j:1; X:25.0; Y:150.0; num: 49
i:6; *j:2; IncrementX:50.0; theY:150.0; numbernum: variable50
i:6; (addj:3; oneX:75.0; toY:150.0; it)num: so51
  i:6; j:4; X:100.0; Y:150.0; num: *52
i:6; thej:5; nextX:125.0; squareY:150.0; isnum: num+153
i:6; (ifj:6; thisX:150.0; isY:150.0; squarenum: 0,54
i:6; j:7; X:175.0; Y:150.0; num: 55
i:7; j:0; *X:0.0; thenY:175.0; thenum: next56
i:7; onej:1; shouldX:25.0; beY:175.0; squarenum: 1)57
  i:7; j:2; X:50.0; Y:175.0; num: */58
 i:7; j:3; X:75.0; Y:175.0; num: num++;59
 i:7; j:4; X:100.0; }
Y:175.0; num: }
}
60
// Change thisi:7; toj:5; makeX:125.0; theY:175.0; checkerboardnum: non-square.61
private statici:7; finalj:6; intX:150.0; numRowsY:175.0; =num: 8;62
private statici:7; finalj:7; intX:175.0; numColumnsY:175.0; =num: 15;63

}

My first question is: How exactly does the program go through the for loops? They are nested, so would it create all of the columns (the j for loop) first? Or does it increment both i and j after the block of code finishes?

Neither, really. Nested loops like this do not increment at the same time: the inner loop will run until j violates the condition (j>numColumns), then the i loop will increment and the whole inner loop will run again. Also, as @JayElston said, only one square is drawn at a time. What this means is that on each run through the inner loop the program draws one row of squares, one in each column. The outer loop repeatedly draws these rows to create the whole checkerboard. So the idea is that the inner loop does not draw whole columns, but rather the part of each column that is in the row currently being worked on.

Secondly, why do I set x = j, and y = i? x is horizontal and j is vertical, shouldn't I set x = i and y = j? Both seem to yield the same results.

As far as the x=j and y=i, what you've written isn't quite accurate. x is actually set to j times the width of a square. So if we're on the fourth column, we are four squares horizontally from the starting point, and thus four times the width of a square from the edge. The fact that both yield the same results is only a coincidence because the checkerboard is square. Change numRows to 9 and run the program, then flip-flop them and run it again and you should see the difference. The first time, the number of rows will be 9, as expected. But when x=i*squareSize, the number of columns will be 9. Note that x and y are positions at which to draw the squares, not the numbers of the rows and columns. That may make it make more sense.

Something that might help would be to include the line System.out.println("i:"+i+"; j:"+j+"; x:"+x+"; x:"+y); in the inner loop right after GRect square.... In Java, System.out.println will show things on the console. Putting in that line will make the program spit out a line each time it draws a square, giving the values of i, j, x, and y.

import acm.graphics.GLabel; import acm.graphics.GRect; import acm.program.GraphicsProgram;

public class CheckerBoard extends GraphicsProgram {

public void run() {
  double squareSize = (double) getHeight() / numRows;

  /*
   * Make a variable to carry the number of the square
   * that's being made. So, the first square will be
   * number 0, the second will be number 1, etc.
   */
  int num = 0;

   /*
   * Run the contents once for each number between 0 and
   * numRows Note the < and not <=. Because we're starting
   * from 0, we need to use <. For example, suppose we
   * wrote int i=0; i<=1; i++. We would get our loop run
   * once with i=0 and once with i=1 before i would not be
   * <= 1. Since our numbers in this case are supposed to
   * be the number of rows, we don't want to loop after we
   * do the one before our numRows or numColumns
   */
  for (int i = 0; i < numRows; i++) {
    /*
     * Run the contents of this loop once for each number
     * between 0 and numColumns, including 0, not
     * including numColumns.
     */
    for (int j = 0; j < numColumns; j++) {
      /*
       * Calculate the position for the next square. If
       * we're in column 4, then the next square should be
       * at 4*(the width of each square).
       */
      double x = j * squareSize;
      double y = i * squareSize;

      /*
       * Create a square that's to be put at our x and y
       * positions calculated just above. Make its width
       * squareSize and its height squareSize.
       */
      GRect square = new GRect(x, y, squareSize, squareSize);

      /*
       * Make some text that will be put down. Use the
       * current value of num for its text
       * (Integer.toString just makes that integer into
       * text), and put it at the x-position we're working
       * with plus 1/4 of a squareSize and the y-position
       * we're working with plus 3/4 of a square. This
       * fakes centering the text in the squares.
       */
      GLabel label = new GLabel(Integer.toString(num), x + squareSize * .25,
          y + squareSize * .75);

      /*
       * Tell the user what our i, j, x, y, and num values
       * are.
       */
      System.out.println("i:" + i + "; j:" + j + "; X:" + x + "; Y:" + y
          + "; num: " + num);

      square.setFilled((i + j) % 2 != 0);
      add(square);

      /*
       * Stick that label on the page, just like with the
       * square.
       */
      add(label);

      /*
       * Increment the number variable (add one to it) so
       * the next square is num+1 (if this is square 0,
       * then the next one should be square 1)
       */
      num++;
    }
  }
}

// Change this to make the checkerboard non-square.
private static final int numRows = 8;
private static final int numColumns = 15;

}

My first question is: How exactly does the program go through the for loops? They are nested, so would it create all of the columns (the j for loop) first? Or does it increment both i and j after the block of code finishes?

Neither, really. Nested loops like this do not increment at the same time: the inner loop will run until j violates the condition (j > numColumns), then the i loop (the outer loop) will increment and the whole inner loop will run again. Also, as @JayElston said, only one square is drawn at a time. What this means is that on each run through the inner loop the program draws one row of squares, one in each column. The outer loop repeatedly draws these rows to create the whole checkerboard. So the idea is that the inner loop does not draw whole columns, but rather the part of each column that is in the row currently being worked on.

Secondly, why do I set x = j, and y = i? x is horizontal and j is vertical, shouldn't I set x = i and y = j? Both seem to yield the same results.

As far as the x=j and y=i, what you've written isn't quite accurate. x is actually set to j times the width of a square, and y is set to i times the width of a square. So if we're on the fourth column, we are four squares horizontally from the starting point, and thus four times the width of a square in the x-direction from the edge. The fact that both yield the same results is a coincidence; it only happens because the checkerboard is square. Change numRows to 15 and run the program, then flip-flop them and run it again and you should see the difference. The first time, the number of rows will be 15 (or 16 if you've written the program with <= in the for loops), as expected from the variable name. But when x=i*squareSize, the number of columns will be 15. Note that x and y are positions at which to draw the squares, not the numbers of the rows and columns. That may make it make more sense.

Something that might help would be to include the line System.out.println("i:"+i+"; j:"+j+"; x:"+x+"; x:"+y); in the inner loop right after GRect square.... (as I've demonstrated in my code below) In Java, System.out.println will show things on the console. Putting in that line will make the program spit out a line each time it draws a square, giving the values of i, j, x, and y.

import acm.graphics.GLabel;
import acm.graphics.GRect;
import acm.program.GraphicsProgram;

public class CheckerBoard extends GraphicsProgram {

  public void run() {
    double squareSize = (double) getHeight() / numRows;

    /*
     * Make a variable to carry the number of the square
     * that's being made. So, the first square will be
     * number 0, the second will be number 1, etc.
     */
    int num = 0;

    /*
     * Run the contents once for each number between 0 and
     * numRows Note the < and not <=. Because we're starting
     * from 0, we need to use <. For example, suppose we
     * wrote int i=0; i<=1; i++. We would get our loop run
     * once with i=0 and once with i=1 before i would not be
     * <= 1. Since our numbers in this case are supposed to
     * be the number of rows, we don't want to loop after we
     * do the one before our numRows or numColumns
     */
    for (int i = 0; i < numRows; i++) {
      /*
       * Run the contents of this loop once for each number
       * between 0 and numColumns, including 0, not
       * including numColumns.
       */
      for (int j = 0; j < numColumns; j++) {
        /*
         * Calculate the position for the next square. If
         * we're in column 4, then the next square should be
         * at 4*(the width of each square).
         */
        double x = j * squareSize;
        double y = i * squareSize;

        /*
         * Create a square that's to be put at our x and y
         * positions calculated just above. Make its width
         * squareSize and its height squareSize.
         */
        GRect square = new GRect(x, y, squareSize, squareSize);

        /*
         * Make some text that will be put down. Use the
         * current value of num for its text
         * (Integer.toString just makes that integer into
         * text), and put it at the x-position we're working
         * with plus 1/4 of a squareSize and the y-position
         * we're working with plus 3/4 of a square. This
         * fakes centering the text in the squares.
         */
        GLabel label = new GLabel(Integer.toString(num), x + squareSize * .25,
            y + squareSize * .75);

        /*
         * Tell the user what our i, j, x, y, and num values
         * are.
         */
        System.out.println("i:" + i + "; j:" + j + "; X:" + x + "; Y:" + y
            + "; num: " + num);

        square.setFilled((i + j) % 2 != 0);
        add(square);

        /*
         * Stick that label on the page, just like with the
         * square.
         */
        add(label);

        /*
         * Increment the number variable (add one to it) so
         * the next square is num+1 (if this is square 0,
         * then the next one should be square 1)
         */
        num++;
      }
    }
  }

  // Change this to make the checkerboard non-square.
  private static final int numRows = 8;
  private static final int numColumns = 8;
}

And here's what I get on my console when I run it:

i:0; j:0; X:0.0; Y:0.0; num: 0
i:0; j:1; X:25.0; Y:0.0; num: 1
i:0; j:2; X:50.0; Y:0.0; num: 2
i:0; j:3; X:75.0; Y:0.0; num: 3
i:0; j:4; X:100.0; Y:0.0; num: 4
i:0; j:5; X:125.0; Y:0.0; num: 5
i:0; j:6; X:150.0; Y:0.0; num: 6
i:0; j:7; X:175.0; Y:0.0; num: 7
i:1; j:0; X:0.0; Y:25.0; num: 8
i:1; j:1; X:25.0; Y:25.0; num: 9
i:1; j:2; X:50.0; Y:25.0; num: 10
i:1; j:3; X:75.0; Y:25.0; num: 11
i:1; j:4; X:100.0; Y:25.0; num: 12
i:1; j:5; X:125.0; Y:25.0; num: 13
i:1; j:6; X:150.0; Y:25.0; num: 14
i:1; j:7; X:175.0; Y:25.0; num: 15
i:2; j:0; X:0.0; Y:50.0; num: 16
i:2; j:1; X:25.0; Y:50.0; num: 17
i:2; j:2; X:50.0; Y:50.0; num: 18
i:2; j:3; X:75.0; Y:50.0; num: 19
i:2; j:4; X:100.0; Y:50.0; num: 20
i:2; j:5; X:125.0; Y:50.0; num: 21
i:2; j:6; X:150.0; Y:50.0; num: 22
i:2; j:7; X:175.0; Y:50.0; num: 23
i:3; j:0; X:0.0; Y:75.0; num: 24
i:3; j:1; X:25.0; Y:75.0; num: 25
i:3; j:2; X:50.0; Y:75.0; num: 26
i:3; j:3; X:75.0; Y:75.0; num: 27
i:3; j:4; X:100.0; Y:75.0; num: 28
i:3; j:5; X:125.0; Y:75.0; num: 29
i:3; j:6; X:150.0; Y:75.0; num: 30
i:3; j:7; X:175.0; Y:75.0; num: 31
i:4; j:0; X:0.0; Y:100.0; num: 32
i:4; j:1; X:25.0; Y:100.0; num: 33
i:4; j:2; X:50.0; Y:100.0; num: 34
i:4; j:3; X:75.0; Y:100.0; num: 35
i:4; j:4; X:100.0; Y:100.0; num: 36
i:4; j:5; X:125.0; Y:100.0; num: 37
i:4; j:6; X:150.0; Y:100.0; num: 38
i:4; j:7; X:175.0; Y:100.0; num: 39
i:5; j:0; X:0.0; Y:125.0; num: 40
i:5; j:1; X:25.0; Y:125.0; num: 41
i:5; j:2; X:50.0; Y:125.0; num: 42
i:5; j:3; X:75.0; Y:125.0; num: 43
i:5; j:4; X:100.0; Y:125.0; num: 44
i:5; j:5; X:125.0; Y:125.0; num: 45
i:5; j:6; X:150.0; Y:125.0; num: 46
i:5; j:7; X:175.0; Y:125.0; num: 47
i:6; j:0; X:0.0; Y:150.0; num: 48
i:6; j:1; X:25.0; Y:150.0; num: 49
i:6; j:2; X:50.0; Y:150.0; num: 50
i:6; j:3; X:75.0; Y:150.0; num: 51
i:6; j:4; X:100.0; Y:150.0; num: 52
i:6; j:5; X:125.0; Y:150.0; num: 53
i:6; j:6; X:150.0; Y:150.0; num: 54
i:6; j:7; X:175.0; Y:150.0; num: 55
i:7; j:0; X:0.0; Y:175.0; num: 56
i:7; j:1; X:25.0; Y:175.0; num: 57
i:7; j:2; X:50.0; Y:175.0; num: 58
i:7; j:3; X:75.0; Y:175.0; num: 59
i:7; j:4; X:100.0; Y:175.0; num: 60
i:7; j:5; X:125.0; Y:175.0; num: 61
i:7; j:6; X:150.0; Y:175.0; num: 62
i:7; j:7; X:175.0; Y:175.0; num: 63
Source Link

My first question is: How exactly does the program go through the for loops? They are nested, so would it create all of the columns (the j for loop) first? Or does it increment both i and j after the block of code finishes?

Neither, really. Nested loops like this do not increment at the same time: the inner loop will run until j violates the condition (j>numColumns), then the i loop will increment and the whole inner loop will run again. Also, as @JayElston said, only one square is drawn at a time. What this means is that on each run through the inner loop the program draws one row of squares, one in each column. The outer loop repeatedly draws these rows to create the whole checkerboard. So the idea is that the inner loop does not draw whole columns, but rather the part of each column that is in the row currently being worked on.

Secondly, why do I set x = j, and y = i? x is horizontal and j is vertical, shouldn't I set x = i and y = j? Both seem to yield the same results.

As far as the x=j and y=i, what you've written isn't quite accurate. x is actually set to j times the width of a square. So if we're on the fourth column, we are four squares horizontally from the starting point, and thus four times the width of a square from the edge. The fact that both yield the same results is only a coincidence because the checkerboard is square. Change numRows to 9 and run the program, then flip-flop them and run it again and you should see the difference. The first time, the number of rows will be 9, as expected. But when x=i*squareSize, the number of columns will be 9. Note that x and y are positions at which to draw the squares, not the numbers of the rows and columns. That may make it make more sense.

Mostly, I would just like to know how the for loop runs each time around. a basic run or two through the program.

Something that might help would be to include the line System.out.println("i:"+i+"; j:"+j+"; x:"+x+"; x:"+y); in the inner loop right after GRect square.... In Java, System.out.println will show things on the console. Putting in that line will make the program spit out a line each time it draws a square, giving the values of i, j, x, and y.

Finally, here's an expanded version of the program with lots of comments. It also tells you about its progress, which hopefully will help you see what's happening. Note that I wouldn't normally use multiline comments (/*...*/) anywhere near this much.

import acm.graphics.GLabel; import acm.graphics.GRect; import acm.program.GraphicsProgram;

public class CheckerBoard extends GraphicsProgram {

public void run() {
  double squareSize = (double) getHeight() / numRows;

  /*
   * Make a variable to carry the number of the square
   * that's being made. So, the first square will be
   * number 0, the second will be number 1, etc.
   */
  int num = 0;

  /*
   * Run the contents once for each number between 0 and
   * numRows Note the < and not <=. Because we're starting
   * from 0, we need to use <. For example, suppose we
   * wrote int i=0; i<=1; i++. We would get our loop run
   * once with i=0 and once with i=1 before i would not be
   * <= 1. Since our numbers in this case are supposed to
   * be the number of rows, we don't want to loop after we
   * do the one before our numRows or numColumns
   */
  for (int i = 0; i < numRows; i++) {
    /*
     * Run the contents of this loop once for each number
     * between 0 and numColumns, including 0, not
     * including numColumns.
     */
    for (int j = 0; j < numColumns; j++) {
      /*
       * Calculate the position for the next square. If
       * we're in column 4, then the next square should be
       * at 4*(the width of each square).
       */
      double x = j * squareSize;
      double y = i * squareSize;

      /*
       * Create a square that's to be put at our x and y
       * positions calculated just above. Make its width
       * squareSize and its height squareSize.
       */
      GRect square = new GRect(x, y, squareSize, squareSize);

      /*
       * Make some text that will be put down. Use the
       * current value of num for its text
       * (Integer.toString just makes that integer into
       * text), and put it at the x-position we're working
       * with plus 1/4 of a squareSize and the y-position
       * we're working with plus 3/4 of a square. This
       * fakes centering the text in the squares.
       */
      GLabel label = new GLabel(Integer.toString(num), x + squareSize * .25,
          y + squareSize * .75);

      /*
       * Tell the user what our i, j, x, y, and num values
       * are.
       */
      System.out.println("i:" + i + "; j:" + j + "; X:" + x + "; Y:" + y
          + "; num: " + num);

      square.setFilled((i + j) % 2 != 0);
      add(square);

      /*
       * Stick that label on the page, just like with the
       * square.
       */
      add(label);

      /*
       * Increment the number variable (add one to it) so
       * the next square is num+1 (if this is square 0,
       * then the next one should be square 1)
       */
      num++;
    }
  }
}

// Change this to make the checkerboard non-square.
private static final int numRows = 8;
private static final int numColumns = 15;

}